"""This script reads a CSV file containing user data and inserts each user into an A360 profile in a Neo4j database.""" import csv import os import re from typing import Any import uuid import connector_neo4j from dotenv import load_dotenv load_dotenv() NEO4J_URL = os.environ.get('NEO4J_URL') NEO4J_USERNAME = os.environ.get('NEO4J_USERNAME') NEO4J_PASSWORD = os.environ.get('NEO4J_PASSWORD') NEO4J_MAX_RETRY_TIME = os.environ.get('NEO4J_MAX_RETRY_TIME') or 60 connector_neo4j.configure( NEO4J_URL, NEO4J_USERNAME, NEO4J_PASSWORD, max_transaction_retry_time=NEO4J_MAX_RETRY_TIME, ) HEADERS = [ "OA User Id", "First Name", "Last Name", "Owner", "Active", "Email", "Group", "Existing ABACUS Access" ] CYPHER_QUERY_R = f""" MATCH (i:Identity {{ email: $email }}) RETURN i.id AS identityId """ CYPHER_QUERY = """ MATCH (i:Identity {email: $email}) MATCH (v:Vendor { id: '*' }) MATCH (inc:IncrementId {nodeName: 'Profile'}) CALL apoc.atomic.add(inc, 'id', 1, 3) YIELD newValue AS increment WITH i, v, AS increment MERGE (i)-[:HAS_PROFILE]->(p:Profile {profileType: 'Account360Profile'}) ON CREATE SET p.profileId = (increment.id-1), p.profileName = 'Account360Profile', p.roles = ['account360'], p.uuid = apoc.create.uuid(), p.createdAt = datetime(), p.createdBy = 'lambda/attachA360Profile, p.lastModifiedAt = datetime(), p.lastModifiedBy = 'lambda/attachA360Profile’, p.fullCatalogAccess = false MERGE (p1)-[r:HAS_ACCESS_TO]->(v) SET r.createdBy = 'lambda/attachA360Profile', r.lastModifiedBy = 'lambda/attachA360Profile', r.lastModifiedAt = datetime(), r.createdAt = datetime() RETURN i.id AS identityId """ COMPANY_BRANDS = [ {"name": "knr", "uuid": "77c6c150-19f3-451f-a692-1a5d7ef30e85"}, {"name": "theorchard", "uuid": "d25a4cd1-e820-45f2-be5c-56edcfeb8298"}, {"name": "hrs", "uuid": "ae886607-ae74-42f4-b7a7-d33f6a6288f4"}, {"name": "sme", "uuid": "9b36a627-4be9-4762-b790-5628676f5f90"}, {"name": "awal", "uuid": "31f4f0f0-cbb4-4a2c-9eb0-d7288c5a2588"}, {"name": "msk", "uuid": "581557e3-94a4-40a1-8f85-1b4328170144"}, {"name": "ab", "uuid": "7c8b382c-fc37-4179-9115-2165b1a93bed"}, {"name": "drm", "uuid": "9c270cea-cde6-4240-81cb-945ec2bac811"}, {"name": "ma", "uuid": "567e4261-ad8a-4e89-8875-d44c26b96f2c"}, {"name": "altafonte", "uuid": "2ed1077d-bcd3-4db6-9a47-c37da82aab18"}, ] def to_snake_case(s): return re.sub(r'[\s\-]+', '_', re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', s)).lower() def parse_users_csv(filename: str) -> list[dict]: users = [] with open(filename, newline='') as csvfile: reader = csv.DictReader(csvfile) reader.fieldnames = [to_snake_case(h) for h in reader.fieldnames] for row in reader: users.append({to_snake_case(k): v for k, v in row.items()}) return users def insert_a360_profile(user: dict, session: Any) -> uuid.UUID | None: """ Insert a user into the A360 profile. :param user: User dictionary containing user details. :return: None """ result = session.run( CYPHER_QUERY_R, email=user['email'] ) record = result.single() if record and record.get('identityId'): print("Creating A360 profile for:", user['email']) try: return uuid.UUID(record['identityId']) except ValueError: print(f"Invalid UUID for identityId: {record['identityId']} for user {user['email']}") return None return None def generate_pdp_csv(uuids: list[uuid.UUID]) -> None: with open('pdp.csv', 'w', newline='') as csvfile: fieldnames = ['identity_uuid', 'tenant_uuid', 'tenant_type', 'role', 'operation'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() for identity_uuid in uuids: for company_brand in COMPANY_BRANDS: writer.writerow({ 'identity_uuid': str(identity_uuid), 'tenant_uuid': company_brand['uuid'], 'tenant_type': 'company_brand', 'role': 'contract_viewer', 'operation': 'attach' }) @connector_neo4j.Neo4jSession( transaction=False, use_v2=True, database='graph.db' ) def main(): session = connector_neo4j.get_session() users = parse_users_csv('ABACUS-View-Only-Users.csv') user_uuids = [] for user in users: uuid = insert_a360_profile(user, session) if uuid: user_uuids.append(uuid) generate_pdp_csv(user_uuids) if __name__ == '__main__': main()