From f0d93237a1fafd2cb97d19a5192be8e25b5e024c Mon Sep 17 00:00:00 2001 From: Cam Date: Mon, 30 Jun 2025 08:06:18 -0500 Subject: [PATCH 1/2] First attempt at comparing Alta users to Neon users --- altaAudit.py | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ neonUtil.py | 17 ++++++++++++ openPathUtil.py | 7 +++++ 3 files changed, 93 insertions(+) create mode 100644 altaAudit.py diff --git a/altaAudit.py b/altaAudit.py new file mode 100644 index 0000000..d0f2c14 --- /dev/null +++ b/altaAudit.py @@ -0,0 +1,69 @@ +################## Asmbly Neon API Integrations ################### +# Neon API docs - https://developer.neoncrm.com/api-v2/ # +################################################################# + +import pdb +import openPathUtil +import neonUtil +import logging +import argparse + + + +def getParserArgs(): + parser = argparse.ArgumentParser( + prog='Alta User Audit', + description='Help find users who have an entry in the Alta database, but are not supported by an entry in Neon.', + ) + parser.add_argument('-v', '--verbose', action='store_true') + args = parser.parse_args() + return args + + +def getLogger(verbose=True): + logLevel = logging.DEBUG if verbose else logging.INFO + logging.basicConfig( + format='%(asctime)s %(levelname)-8s %(message)s', + level=logLevel, + datefmt='%Y-%m-%d %H:%M:%S') + return logging.getLogger(__name__) + + +def main(): + args = getParserArgs() + log = getLogger(args.verbose) + + # Get the list of users from the Alta database + altaUsers = openPathUtil.getAllUsersMock() + neonUsers = neonUtil.getRealAccountsMock() + + # Find all users in Alta who _are not_ in Neon + extraAltaUsers = [] + for uid, user in altaUsers.items(): + match = False + log.debug(f'Checking for Alta user {uid}') + for nuid, neonUser in neonUsers.items(): + log.debug(f'Comparing Alta user {uid} to Neon user {nuid}') + opid = neonUser.get('OpenPathID') + log.debug(f'Neon user {nuid} has OpenPathID {opid}') + if opid and int(uid) == int(opid): + match = True + log.debug(f'Alta user {uid} is Neon user {neonUser.get("fullName")} ({nuid})') + continue + else: + log.debug('No match') + if not match: + log.debug('No match found for {uid}') + extraAltaUsers.append(uid) + + # Display + if len(extraAltaUsers) == 0: + log.info('All users in Alta are supported by a Neon entry') + else: + log.info('The following Alta users are not found in Neon:') + for uid in extraAltaUsers: + log.info(f'{uid}: {altaUsers[uid]}') + + +if __name__ == '__main__': + main() diff --git a/neonUtil.py b/neonUtil.py index 5ca46fa..e4fb410 100644 --- a/neonUtil.py +++ b/neonUtil.py @@ -482,6 +482,23 @@ def getRealAccounts(): return neonAccountDict +#################################################################### +# MOCK: Get all staf and current/past members from Neon, incuding detailed subscription info +#################################################################### +def getRealAccountsMock(): + return { + '12af34e5': { # What does this value look like? Int/hex/string? + 'OpenPathID': '4321', + 'validMembership': True, + 'fullName': 'Cam Herringshaw', + }, + '12a34': { + 'OpenPathID': '1234', + 'fullName': 'Test User', + }, + } + + #################################################################### # Helper function: is this Neon account marked with any type #################################################################### diff --git a/openPathUtil.py b/openPathUtil.py index c9c366b..52f407a 100644 --- a/openPathUtil.py +++ b/openPathUtil.py @@ -97,6 +97,13 @@ def getAllUsers(): return opUsers +#################################################################### +# MOCK: Return a fake list of users +#################################################################### +def getAllUsersMock(): + return { 4321: { 'id': 4321 } } + + #################################################################### # Get a single OpenPath user by OpenPath ID #################################################################### From e5a4d0f8b715d20d3cb2ede286dc68f1428fe421 Mon Sep 17 00:00:00 2001 From: Cam Date: Mon, 30 Jun 2025 08:11:29 -0500 Subject: [PATCH 2/2] Minor cleanup, add another test case --- altaAudit.py | 3 --- openPathUtil.py | 9 ++++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/altaAudit.py b/altaAudit.py index d0f2c14..89c2db2 100644 --- a/altaAudit.py +++ b/altaAudit.py @@ -2,14 +2,12 @@ # Neon API docs - https://developer.neoncrm.com/api-v2/ # ################################################################# -import pdb import openPathUtil import neonUtil import logging import argparse - def getParserArgs(): parser = argparse.ArgumentParser( prog='Alta User Audit', @@ -56,7 +54,6 @@ def main(): log.debug('No match found for {uid}') extraAltaUsers.append(uid) - # Display if len(extraAltaUsers) == 0: log.info('All users in Alta are supported by a Neon entry') else: diff --git a/openPathUtil.py b/openPathUtil.py index 52f407a..cb268cb 100644 --- a/openPathUtil.py +++ b/openPathUtil.py @@ -101,7 +101,14 @@ def getAllUsers(): # MOCK: Return a fake list of users #################################################################### def getAllUsersMock(): - return { 4321: { 'id': 4321 } } + return { + 4321: { + 'id': 4321, + }, + 12345: { + 'id': 12345, + }, + } ####################################################################