""" # Generate DB PR neo4j xml file. - https://theorchard.atlassian.net/browse/PP-241 - https://github.com/theorchard/database/pull/16700 ## Source Data Neo4J Queries Used the following Neo4J queries to generate the input CSV files. #### complicated_stress_test_user.csv ```cypher MATCH(i:Identity {id: "f415420b-2227-4d9f-8676-a7bddcd74fc8"})--(p:Profile)--(l:Label) RETURN p.profileId as profile_id, p.uuid as profile_uuid, i.id as identity_uuid, l.uuid as tenant_uuid, l.id as vendor_id, p.profileType as profile_type, p.roles[0] as profile_role; ``` #### simple_stress_test_user.csv ```cypher MATCH (v:Vendor) WHERE v.uuid IN ['16bad0cd-489e-4e17-b75b-eef3b013fa6d'] RETURN 0 as profile_id, v.uuid as profile_uuid, v.uuid as tenant_uuid, v.vendorId as vendor_id, "LabelProfile" as profile_type, "administrator" as profile_role; ``` #### integration_test_user.csv ```cypher MATCH (v:Vendor) WHERE v.uuid IN ['fff741c2-6def-4493-bfdf-c2bcb1128e02'] RETURN 0 as profile_id, v.uuid as profile_uuid, v.uuid as tenant_uuid, v.vendorId as vendor_id, "LabelProfile" as profile_type, "administrator" as profile_role; ``` #### Validation Query ```cypher // Should return 597 records MATCH(i:Identity)--(p:Profile)--(l:Label) WHERE i.email in ["pdpteststresscomplicated@theorchard.com", "pdptest@theorchard.com", "pdpteststresssimple@theorchard.com"] RETURN p.profileId as profile_id, i.email as email, i.id as identity_uuid, l.uuid as tenant_uuid, l.id as vendor_id, p.profileType as profile_type, p.roles[0] as profile_role ORDER BY profile_id; // or just row counts MATCH(i:Identity)--(p:Profile)--(l:Label) WHERE i.email in ["pdpteststresscomplicated@theorchard.com", "pdptest@theorchard.com", "pdpteststresssimple@theorchard.com"] RETURN count(p); ``` > Rollback Cypher Queries // Delete pdpteststresscomplicated Profile nodes and relationships and Identity MATCH(i:Identity {email:'pdpteststresscomplicated@theorchard.com'})-[:HAS_PROFILE]->(p:Profile) DETACH DELETE p; MATCH(i:Identity {email:'pdpteststresscomplicated@theorchard.com'}) DETACH DELETE i; // MATCH(i:Identity {email:'pdptest@theorchard.com'})-[:HAS_PROFILE]->(p:Profile) DETACH DELETE p; MATCH(i:Identity {email:'pdptest@theorchard.com'}) DETACH DELETE i; // MATCH(i:Identity {email:'pdpteststresssimple@theorchard.com'})-[:HAS_PROFILE]->(p:Profile) DETACH DELETE p; MATCH(i:Identity {email:'pdpteststresssimple@theorchard.com'}) DETACH DELETE i; """ import codecs import textwrap from csv import DictReader XML_HEADER = textwrap.dedent(""" """) XML_FOOTER = textwrap.dedent(""" """) def generate_qa_refresh_cypher(input_fn, output_fn, email, identity_uuid, identity_name, auth0_id, start_profile_id, identityVarName, identity_num, output_fn_mode='w'): """ Generate the `11_pdp_stress_test_profiles.cypher` output file to be included in https://github.com/theorchard/python-neo4j-cypher-scheduler """ # Create new profile ids and uuids per distinct tenant uuid current_profile_id = start_profile_id profile_to_vendor_lookup = set() # 1st lines to crate the identity node. lines = [] # read the input csv with codecs.open(input_fn, 'r', 'utf-8-sig') as csvfile: rdr = DictReader(csvfile) p_count = 1 for i, row in enumerate(rdr): # remove extra double-quotes row = dict([(k, v.replace('"', "")) for k, v in row.items()]) tenant_uuid = row['tenant_uuid'] if tenant_uuid in profile_to_vendor_lookup: # allow only 1 entry per label.uuid (tenant_uuid) continue # generate new profile uuid profile_to_vendor_lookup.add(tenant_uuid) current_profile_id += 1 p_node_name = f"p{identity_num}_{p_count}" v_node_name = f"v{identity_num}_{p_count}" ip_rel_name = f"ip_rel_{identityVarName}" pv_rel_name = f"pv_rel_{p_node_name}" p_count += 1 line = textwrap.dedent(f""" MERGE ({identityVarName}:Identity {{email: '{email}'}}) ON CREATE SET {identityVarName}.id = '{identity_uuid}', {identityVarName}.name = '{identity_name}', {identityVarName}.auth0UserId='{auth0_id}' WITH {identityVarName} MERGE (increment:IncrementId {{nodeName: 'Profile'}}) ON CREATE SET increment.id = 2 ON MATCH SET increment.id = increment.id + 1 CREATE ({p_node_name}:Profile {{ profileId: (increment.id-1), profileType: 'FauxLabelProfile', profileName: 'FauxLabelProfile_{p_node_name}', roles: ['administrator'], uuid: apoc.create.uuid() }}) MERGE ({identityVarName})-[{ip_rel_name}:HAS_PROFILE]->({p_node_name}) WITH {identityVarName}, {p_node_name} MATCH ({v_node_name}:Vendor{{id: {row['vendor_id']}}}) MERGE ({p_node_name})-[{pv_rel_name}:HAS_ACCESS_TO]->({v_node_name});""") lines.append(line) # lines.append(";\n\n") print(f"Added {len(lines)} lines") # write the file: # output_fn_mode will create a new file (w) or append to an existing file (a) with open(output_fn, output_fn_mode) as fp: for line in lines: fp.write(line + '\n') print(f"wrote to {output_fn}") return lines def to_xml(lines, output_fn): """ Generate XML for (p1_1) WITH i1, p1_1 MATCH (v1_1:Vendor{id: 6971}) MERGE (p1_1)-[pv_rel_p1_1:HAS_ACCESS_TO]->(v1_1); ]]> """ change_num = 1 with open(output_fn, "w") as fp: fp.write(XML_HEADER) for change_num, line in enumerate(lines): shifted_line = "" slines = line.splitlines() for j, e in enumerate(slines): if not e.strip(): continue if j < len(slines) - 1: shifted_line += f"{16 * ' '}{e}\n" else: shifted_line += f"{16 * ' '}{e.replace(';', '')}" changeset = f""" """ fp.write(changeset) change_num += 1 fp.write(XML_FOOTER) print(f"wrote to {output_fn}") if __name__ == '__main__': l1 = generate_qa_refresh_cypher(input_fn='./data/integration_test_user.csv', output_fn="./data/11_pdp_stress_test_profiles.cypher", email='pdptest@theorchard.com', identity_uuid="4d5f24f5-83f9-4989-9f82-0924a5feaf88", identity_name="Integration Test User", auth0_id="6446c6827eadbdf56f275c32", identityVarName="i1", identity_num=1, start_profile_id=36000) l2 = generate_qa_refresh_cypher(input_fn='./data/simple_stress_test_user.csv', output_fn="./data/11_pdp_stress_test_profiles.cypher", email='pdpteststresssimple@theorchard.com', identity_uuid="ef7cd70d-4314-49f9-b158-f3b3be66372f", identity_name="Stress Test Simple User", identityVarName="i2", auth0_id="64808e1030bb6f683cf4dce8", start_profile_id=36001, identity_num=2, output_fn_mode="a" ) l3 = generate_qa_refresh_cypher(input_fn='./data/complicated_stress_test_user.csv', output_fn="./data/11_pdp_stress_test_profiles.cypher", email='pdpteststresscomplicated@theorchard.com', identity_uuid="5f0f10e0-9a9a-48e5-9616-a02886837e9", identity_name="Stress Test Complicated User", auth0_id="64808e48e65313dafa723db2", identityVarName="i3", output_fn_mode="a", identity_num=3, start_profile_id=36002) output_lines = l1 + l2 + l3 to_xml(lines=output_lines, output_fn="./data/PP-241-qa-pdptest-stress-test-user-jul18.xml")