async def test_realm_stats_ok(alice_backend_sock, realm): # Create new data await block_create(alice_backend_sock, realm_id=realm, block_id=BlockID.new(), block=b"1234") rep = await realm_stats(alice_backend_sock, realm_id=realm) assert rep == {"status": "ok", "blocks_size": 4, "vlobs_size": 0} # Create new metadata await vlob_create(alice_backend_sock, realm_id=realm, vlob_id=VlobID.new(), blob=b"1234") rep = await realm_stats(alice_backend_sock, realm_id=realm) assert rep == {"status": "ok", "blocks_size": 4, "vlobs_size": 4}
async def test_organization_stats_data(alice_backend_sock, realm, realm_factory, alice, backend): stats = await organization_stats(alice_backend_sock) assert stats == { "status": "ok", "data_size": 0, "metadata_size": ANY, "users": 3, "active_users": 3, "users_per_profile_detail": [ { "profile": UserProfile.ADMIN, "active": 2, "revoked": 0 }, { "profile": UserProfile.STANDARD, "active": 1, "revoked": 0 }, { "profile": UserProfile.OUTSIDER, "active": 0, "revoked": 0 }, ], "realms": 4, } initial_metadata_size = stats["metadata_size"] # Create new metadata await backend.vlob.create( organization_id=alice.organization_id, author=alice.device_id, realm_id=realm, encryption_revision=1, vlob_id=VlobID.new(), timestamp=pendulum.now(), blob=b"1234", ) stats = await organization_stats(alice_backend_sock) assert stats == { "status": "ok", "data_size": 0, "metadata_size": initial_metadata_size + 4, "users": 3, "active_users": 3, "users_per_profile_detail": [ { "profile": UserProfile.ADMIN, "active": 2, "revoked": 0 }, { "profile": UserProfile.STANDARD, "active": 1, "revoked": 0 }, { "profile": UserProfile.OUTSIDER, "active": 0, "revoked": 0 }, ], "realms": 4, } # Create new data await backend.block.create( organization_id=alice.organization_id, author=alice.device_id, block_id=BlockID.new(), realm_id=realm, block=b"1234", ) stats = await organization_stats(alice_backend_sock) assert stats == { "status": "ok", "data_size": 4, "metadata_size": initial_metadata_size + 4, "users": 3, "active_users": 3, "users_per_profile_detail": [ { "profile": UserProfile.ADMIN, "active": 2, "revoked": 0 }, { "profile": UserProfile.STANDARD, "active": 1, "revoked": 0 }, { "profile": UserProfile.OUTSIDER, "active": 0, "revoked": 0 }, ], "realms": 4, } # create new workspace await realm_factory(backend, alice) stats = await organization_stats(alice_backend_sock) assert stats == { "status": "ok", "data_size": 4, "metadata_size": initial_metadata_size + 4, "users": 3, "active_users": 3, "users_per_profile_detail": [ { "profile": UserProfile.ADMIN, "active": 2, "revoked": 0 }, { "profile": UserProfile.STANDARD, "active": 1, "revoked": 0 }, { "profile": UserProfile.OUTSIDER, "active": 0, "revoked": 0 }, ], "realms": 5, }
async def test_organization_stats_data(backend_rest_send, realm, realm_factory, alice, backend): async def organization_stats(): status, _, body = await backend_rest_send( f"/administration/organizations/{alice.organization_id}/stats") assert status == (200, "OK") return organization_stats_rep_serializer.load(body) rep = await organization_stats() assert rep == { "data_size": 0, "metadata_size": ANY, "users": 3, "active_users": 3, "users_per_profile_detail": [ { "profile": UserProfile.ADMIN, "active": 2, "revoked": 0 }, { "profile": UserProfile.STANDARD, "active": 1, "revoked": 0 }, { "profile": UserProfile.OUTSIDER, "active": 0, "revoked": 0 }, ], "realms": 4, } initial_metadata_size = rep["metadata_size"] # Create new metadata await backend.vlob.create( organization_id=alice.organization_id, author=alice.device_id, realm_id=realm, encryption_revision=1, vlob_id=VlobID.new(), timestamp=pendulum.now(), blob=b"1234", ) rep = await organization_stats() assert rep == { "data_size": 0, "metadata_size": initial_metadata_size + 4, "users": 3, "active_users": 3, "users_per_profile_detail": [ { "profile": UserProfile.ADMIN, "active": 2, "revoked": 0 }, { "profile": UserProfile.STANDARD, "active": 1, "revoked": 0 }, { "profile": UserProfile.OUTSIDER, "active": 0, "revoked": 0 }, ], "realms": 4, } # Create new data await backend.block.create( organization_id=alice.organization_id, author=alice.device_id, block_id=BlockID.new(), realm_id=realm, block=b"1234", ) rep = await organization_stats() assert rep == { "data_size": 4, "metadata_size": initial_metadata_size + 4, "users": 3, "active_users": 3, "users_per_profile_detail": [ { "profile": UserProfile.ADMIN, "active": 2, "revoked": 0 }, { "profile": UserProfile.STANDARD, "active": 1, "revoked": 0 }, { "profile": UserProfile.OUTSIDER, "active": 0, "revoked": 0 }, ], "realms": 4, } # create new workspace await realm_factory(backend, alice) rep = await organization_stats() assert rep == { "data_size": 4, "metadata_size": initial_metadata_size + 4, "users": 3, "active_users": 3, "users_per_profile_detail": [ { "profile": UserProfile.ADMIN, "active": 2, "revoked": 0 }, { "profile": UserProfile.STANDARD, "active": 1, "revoked": 0 }, { "profile": UserProfile.OUTSIDER, "active": 0, "revoked": 0 }, ], "realms": 5, }
async def test_block_create_check_access_rights(backend, alice, bob, bob_backend_sock, realm, next_timestamp): block_id = BlockID.new() # User not part of the realm rep = await block_create(bob_backend_sock, block_id, realm, BLOCK_DATA, check_rep=False) assert rep == {"status": "not_allowed"} # User part of the realm with various role for role, access_granted in [ (RealmRole.READER, False), (RealmRole.CONTRIBUTOR, True), (RealmRole.MANAGER, True), (RealmRole.OWNER, True), ]: await backend.realm.update_roles( alice.organization_id, RealmGrantedRole( certificate=b"<dummy>", realm_id=realm, user_id=bob.user_id, role=role, granted_by=alice.device_id, granted_on=next_timestamp(), ), ) block_id = BlockID.new() rep = await block_create(bob_backend_sock, block_id, realm, BLOCK_DATA, check_rep=False) if access_granted: assert rep == {"status": "ok"} else: assert rep == {"status": "not_allowed"} # Ensure user that used to be part of the realm have no longer access await backend.realm.update_roles( alice.organization_id, RealmGrantedRole( certificate=b"<dummy>", realm_id=realm, user_id=bob.user_id, role=None, granted_by=alice.device_id, granted_on=next_timestamp(), ), ) rep = await block_create(bob_backend_sock, block_id, realm, BLOCK_DATA, check_rep=False) assert rep == {"status": "not_allowed"}
async def test_access_during_reencryption( backend, alice_backend_sock, alice, realm_factory, next_timestamp ): # First initialize a nice realm with block and vlob realm_id = await realm_factory(backend, author=alice) vlob_id = VlobID.new() block_id = BlockID.new() await backend.vlob.create( organization_id=alice.organization_id, author=alice.device_id, realm_id=realm_id, encryption_revision=1, vlob_id=vlob_id, timestamp=next_timestamp(), blob=b"v1", ) await backend.block.create( organization_id=alice.organization_id, author=alice.device_id, realm_id=realm_id, block_id=block_id, block=b"<block_data>", ) async def _assert_write_access_disallowed(encryption_revision): rep = await vlob_create( alice_backend_sock, realm_id=realm_id, vlob_id=VlobID.new(), blob=b"data", encryption_revision=encryption_revision, check_rep=False, ) assert rep == {"status": "in_maintenance"} rep = await vlob_update( alice_backend_sock, vlob_id, version=2, blob=b"data", encryption_revision=encryption_revision, check_rep=False, ) assert rep == {"status": "in_maintenance"} rep = await block_create( alice_backend_sock, block_id=block_id, realm_id=realm_id, block=b"data", check_rep=False ) assert rep == {"status": "in_maintenance"} async def _assert_read_access_allowed(encryption_revision, expected_blob=b"v1"): rep = await vlob_read( alice_backend_sock, vlob_id=vlob_id, version=1, encryption_revision=encryption_revision ) assert rep["status"] == "ok" assert rep["blob"] == expected_blob rep = await block_read(alice_backend_sock, block_id=block_id) assert rep == {"status": "ok", "block": b"<block_data>"} # For good measure, also try those read-only commands even if they # are encryption-revision agnostic rep = await vlob_list_versions(alice_backend_sock, vlob_id=vlob_id) assert rep["status"] == "ok" rep = await vlob_poll_changes(alice_backend_sock, realm_id=realm_id, last_checkpoint=0) assert rep["status"] == "ok" async def _assert_read_access_bad_encryption_revision(encryption_revision, expected_status): rep = await vlob_read( alice_backend_sock, vlob_id=vlob_id, version=1, encryption_revision=encryption_revision ) assert rep == {"status": expected_status} # Sanity check just to make we can access the data with initial encryption revision await _assert_read_access_allowed(1) # Now start reencryption await backend.realm.start_reencryption_maintenance( organization_id=alice.organization_id, author=alice.device_id, realm_id=realm_id, encryption_revision=2, per_participant_message={alice.user_id: b"<whatever>"}, timestamp=pendulum_now(), ) # Only read with old encryption revision is now allowed await _assert_read_access_allowed(1) await _assert_read_access_bad_encryption_revision(2, expected_status="in_maintenance") await _assert_write_access_disallowed(1) await _assert_write_access_disallowed(2) # Actually reencrypt the vlob data, this shouldn't affect us for the moment # given reencryption is not formally finished await backend.vlob.maintenance_save_reencryption_batch( organization_id=alice.organization_id, author=alice.device_id, realm_id=realm_id, encryption_revision=2, batch=[(vlob_id, 1, b"v2")], ) await _assert_read_access_allowed(1) await _assert_read_access_bad_encryption_revision(2, expected_status="in_maintenance") await _assert_write_access_disallowed(1) await _assert_write_access_disallowed(2) # Finish the reencryption await backend.realm.finish_reencryption_maintenance( organization_id=alice.organization_id, author=alice.device_id, realm_id=realm_id, encryption_revision=2, ) # Now only the new encryption revision is allowed await _assert_read_access_allowed(2, expected_blob=b"v2") await _assert_read_access_bad_encryption_revision(1, expected_status="bad_encryption_revision")