def testRefreshFileStartsFlow(self): self.Open("/#/clients/C.0000000000000001/vfs/fs/os/c/Downloads/") # Select a file and start a flow by requesting a newer version. self.Click("css=tr:contains(\"a.txt\")") self.Click("css=li[heading=Download]") self.Click("css=button:contains(\"Collect from the client\")") # Create a new file version (that would have been created by the flow # otherwise) and finish the flow. # Make sure that the flow has started (when button is clicked, the HTTP # API request is sent asynchronously). def MultiGetFileStarted(): return compatibility.GetName(transfer.MultiGetFile) in [ f.flow_class_name for f in data_store.REL_DB.ReadAllFlowObjects( client_id=self.client_id) ] self.WaitUntil(MultiGetFileStarted) flow_test_lib.FinishAllFlowsOnClient(self.client_id, check_flow_errors=False) time_in_future = rdfvalue.RDFDatetime.Now() + rdfvalue.DurationSeconds( "1h") # We have to make sure that the new version will not be within a second # from the current one, otherwise the previous one and the new one will # be indistinguishable in the UI (as it has a 1s precision when # displaying versions). gui_test_lib.CreateFileVersion(self.client_id, "fs/os/c/Downloads/a.txt", "The newest version!".encode("utf-8"), timestamp=time_in_future) # Once the flow has finished, the file view should update and add the # newly created, latest version of the file to the list. The selected # option should still be "HEAD". self.WaitUntilContains("HEAD", self.GetText, "css=.version-dropdown > option[selected]") # The file table should also update and display the new timestamp. self.WaitUntilContains(gui_test_lib.DateTimeString(time_in_future), self.GetText, "css=.version-dropdown > option:nth(1)") # The file table should also update and display the new timestamp. self.WaitUntil( self.IsElementPresent, "css=grr-file-table tbody > tr td:contains(\"%s\")" % (gui_test_lib.DateTimeString(time_in_future))) # Make sure the file content has changed. self.Click("css=li[heading=TextView]") self.WaitUntilContains("The newest version!", self.GetText, "css=div.monospace pre") # Go to the flow management screen and check that there was a new flow. self.Click("css=a:contains('Manage launched flows')") self.Click("css=grr-flows-list tr:contains('MultiGetFile')") self.WaitUntilContains(transfer.MultiGetFile.__name__, self.GetText, "css=#main_bottomPane") self.WaitUntilContains( "c/Downloads/a.txt", self.GetText, "css=#main_bottomPane table > tbody td.proto_key:contains(\"Path\") " "~ td.proto_value")
def testRefreshFileStartsFlow(self): self.Open("/") self.Type("client_query", "C.0000000000000001") self.Click("client_query_submit") self.WaitUntilEqual(u"C.0000000000000001", self.GetText, "css=span[type=subject]") # Choose client 1. self.Click("css=td:contains('0001')") # Go to Browse VFS. self.Click("css=a:contains('Browse Virtual Filesystem')") self.Click("css=#_fs i.jstree-icon") self.Click("css=#_fs-os i.jstree-icon") self.Click("css=#_fs-os-c i.jstree-icon") # Test file versioning. self.WaitUntil(self.IsElementPresent, "css=#_fs-os-c-Downloads") self.Click("link=Downloads") # Select a file and start a flow by requesting a newer version. self.Click("css=tr:contains(\"a.txt\")") self.Click("css=li[heading=Download]") self.Click("css=button:contains(\"Collect from the client\")") # Create a new file version (that would have been created by the flow # otherwise) and finish the flow. client_id = rdf_client.ClientURN("C.0000000000000001") fd = aff4.FACTORY.Open(client_id.Add("flows"), token=self.token) # Make sure that the flow has started (when button is clicked, the HTTP # API request is sent asynchronously). def MultiGetFileStarted(): return transfer.MultiGetFile.__name__ in list( x.__class__.__name__ for x in fd.OpenChildren()) self.WaitUntil(MultiGetFileStarted) flows = list(fd.ListChildren()) client_mock = action_mocks.MultiGetFileClientMock() for flow_urn in flows: flow_test_lib.TestFlowHelper(flow_urn, client_mock, client_id=client_id, check_flow_errors=False, token=self.token) time_in_future = rdfvalue.RDFDatetime.Now() + rdfvalue.Duration("1h") # We have to make sure that the new version will not be within a second # from the current one, otherwise the previous one and the new one will # be indistinguishable in the UI (as it has a 1s precision when # displaying versions). with test_lib.FakeTime(time_in_future): gui_test_lib.CreateFileVersion( rdf_client.ClientURN("C.0000000000000001"), "fs/os/c/Downloads/a.txt", "The newest version!", timestamp=rdfvalue.RDFDatetime.Now(), token=self.token) # Once the flow has finished, the file view should update and add the # newly created, latest version of the file to the list. The selected # option should still be "HEAD". self.WaitUntilContains("HEAD", self.GetText, "css=.version-dropdown > option[selected]") # The file table should also update and display the new timestamp. self.WaitUntilContains(gui_test_lib.DateTimeString(time_in_future), self.GetText, "css=.version-dropdown > option:nth(1)") # The file table should also update and display the new timestamp. self.WaitUntil( self.IsElementPresent, "css=grr-file-table tbody > tr td:contains(\"%s\")" % (gui_test_lib.DateTimeString(time_in_future))) # Make sure the file content has changed. self.Click("css=li[heading=TextView]") self.WaitUntilContains("The newest version!", self.GetText, "css=div.monospace pre") # Go to the flow management screen and check that there was a new flow. self.Click("css=a:contains('Manage launched flows')") self.Click("css=grr-flows-list tr:contains('MultiGetFile')") self.WaitUntilContains(transfer.MultiGetFile.__name__, self.GetText, "css=#main_bottomPane") self.WaitUntilContains( "c/Downloads/a.txt", self.GetText, "css=#main_bottomPane table > tbody td.proto_key:contains(\"Path\") " "~ td.proto_value")
def testVersionDropDownChangesFileContentAndDownloads(self): """Test the fileview interface.""" self.Open("/#/clients/%s" % self.client_id) # Go to Browse VFS. self.Click("css=a[grrtarget='client.vfs']") self.Click("css=#_fs i.jstree-icon") self.Click("css=#_fs-os i.jstree-icon") self.Click("css=#_fs-os-c i.jstree-icon") # Test file versioning. self.WaitUntil(self.IsElementPresent, "css=#_fs-os-c-Downloads") self.Click("link=Downloads") # Verify that we have the latest version in the table by default. self.assertIn(gui_test_lib.DateString(gui_test_lib.TIME_2), self.GetText("css=tr:contains(\"a.txt\")")) # Click on the row. self.Click("css=tr:contains(\"a.txt\")") self.WaitUntilContains("a.txt", self.GetText, "css=div#main_bottomPane h1") self.WaitUntilContains("HEAD", self.GetText, "css=.version-dropdown > option[selected]") self.WaitUntilContains(gui_test_lib.DateString(gui_test_lib.TIME_2), self.GetText, "css=.version-dropdown > option:nth(1)") # Check the data in this file. self.Click("css=li[heading=TextView]") self.WaitUntilContains("Goodbye World", self.GetText, "css=div.monospace pre") downloaded_files = [] def FakeDownloadHandle(unused_self, args, token=None): _ = token # Avoid unused variable linter warnings. downloaded_files.append((args.file_path, args.timestamp)) return api_call_handler_base.ApiBinaryStream( filename=os.path.basename(args.file_path), content_generator=range(42)) with utils.Stubber(api_vfs.ApiGetFileBlobHandler, "Handle", FakeDownloadHandle): # Try to download the file. self.Click("css=li[heading=Download]") self.WaitUntilContains( gui_test_lib.DateTimeString(gui_test_lib.TIME_2), self.GetText, "css=grr-file-download-view") self.Click("css=button:contains(\"Download\")") # Select the previous version. self.Click( "css=select.version-dropdown > option:contains(\"%s\")" % gui_test_lib.DateString(gui_test_lib.TIME_1)) # Now we should have a different time. self.WaitUntilContains( gui_test_lib.DateTimeString(gui_test_lib.TIME_1), self.GetText, "css=grr-file-download-view") self.Click("css=button:contains(\"Download\")") self.WaitUntil(self.IsElementPresent, "css=li[heading=TextView]") # the FakeDownloadHandle method was actually called four times, since # a file download first sends a HEAD request to check user access. self.WaitUntil(lambda: len(downloaded_files) == 4) # Both files should be the same... self.assertEqual(downloaded_files[0][0], u"fs/os/c/Downloads/a.txt") self.assertEqual(downloaded_files[2][0], u"fs/os/c/Downloads/a.txt") # But from different times. The downloaded file timestamp is only accurate # to the nearest second. self.assertEqual(downloaded_files[0][1], None) self.assertAlmostEqual(downloaded_files[2][1], gui_test_lib.TIME_1, delta=rdfvalue.DurationSeconds("1s")) self.Click("css=li[heading=TextView]") # Make sure the file content has changed. This version has "Hello World" in # it. self.WaitUntilContains("Hello World", self.GetText, "css=div.monospace pre")