#!/usr/bin/python3 """ Add a list of UNIs to the target group Replace current members if the replace flag is t (true) Example: grouper_add_members.py -m dev -f -g -r """ import argparse import requests from requests.auth import HTTPBasicAuth import json import sys,string import os def grouperAddMembers(grouper_credentials, grouper_ws_uri, groupName, subject_list, replace_flag): """Add group member""" if replace_flag != 't' and replace_flag != 'f': print(f"replace flag {replace_flag} must be t or f") exit(1) # listOfSubjectDictionaries contains a list of dictionaries listOfSubjectDictionaries = [] for nsubjects in range(0,len(subject_list)): listOfSubjectDictionaries.append({'subjectId':subject_list[nsubjects]}) body = { "WsRestAddMemberRequest": { "wsGroupLookup": { "groupName": groupName }, "replaceAllExisting": replace_flag, "subjectLookups": listOfSubjectDictionaries } } return grouperWSRequest(grouper_credentials, grouper_ws_uri+"/groups/"+groupName+"/members", "PUT", body) def grouperGetUuid(grouper_credentials, grouper_ws_uri, groupName): """Get UUID for the specified group""" thisuuid = 0 body = { "WsRestFindGroupsRequest": { "wsQueryFilter": { "groupName": groupName, "queryFilterType": "FIND_BY_GROUP_NAME_EXACT", } } } findGroups = grouperWSRequest(grouper_credentials, grouper_ws_uri+"/groups", "POST", body) if findGroups and findGroups['WsFindGroupsResults']['resultMetadata']['success'] and 'groupResults' in findGroups['WsFindGroupsResults']: thisuuid = findGroups['WsFindGroupsResults']['groupResults'][0]['uuid'] return thisuuid def grouperWSRequest(grouper_credentials, url, method, body=None): """Send a request to the Grouper Web Service.""" try: response = requests.request(method, url, json=body, auth=grouper_credentials) response.raise_for_status() except requests.RequestException as e: raise SystemExit(e) from None return response.json() def add_members(mode, uni_list, group_id_path, replace_flag): """Add a list of UNIs to a group. Args: mode (str): The environment mode ('dev', 'prod'). uni_list (str): The UNI file name. group_id_path (str): The group to be updated. replace_flag (str): The replace flag ('t', 'f'). """ # set the Grouper Web Service username and password grouper_username = 'abc1234' grouper_password = 'xxxxxxxxxxxxxxxxxxxx' grouper_credentials = HTTPBasicAuth(grouper_username,grouper_password) # the Grouper Web Service URI should point to dev or prod Grouper devGrouperURI = 'https://grouper-dev.cc.columbia.edu/grouper-ws/servicesRest/v2_4_000' prodGrouperURI = 'https://grouper.cc.columbia.edu/grouper-ws/servicesRest/v2_4_000' if mode == 'prod': grouper_ws_uri = prodGrouperURI else: grouper_ws_uri = devGrouperURI # Verify that the target group exists and is accessible by this user if grouperGetUuid(grouper_credentials,grouper_ws_uri,group_id_path) == 0: print(f"{group_id_path} group not found (does not exist or is not accessible)") return # Verify that the file exists if not os.path.exists(uni_list): print(f"input file not found: {uni_list}") return # Read the list of UNIs from the input file infil = open(uni_list, 'r') subject_list = [] while 1: line = infil.readline() if not line: break line = line.rstrip() # remove the newline character subject_list.append(line) # add this UNI to the list infil.close() # Add the members to the group result = grouperAddMembers(grouper_credentials,grouper_ws_uri,group_id_path,subject_list,replace_flag) if ( not result or not result['WsAddMemberResults']['results'][0]['resultMetadata']['success'] ): print(f"Unable to add members to {group_id_path}") return print(f"UNIs have been added to {group_id_path}") def main(): """Parses command-line arguments and calls add_member.""" parser = argparse.ArgumentParser( description="Add a list of UNIs to the specified group.", epilog=("Replace current members if the replace flag is t (true)."), ) parser.add_argument( "-m", action="store", dest="mode", required=True, choices=["dev", "prod"], type=str.lower, help="the Grouper environment mode", ) parser.add_argument( "-f", action="store", dest="uni_list", required=True, help="UNI file name", ) parser.add_argument( "-g", action="store", dest="group_id_path", required=True, help="the group ID path of the group to be updated", ) parser.add_argument( "-r", action="store", dest="replace_flag", required=True, choices=["t", "f"], type=str.lower, help="replace flag", ) args = parser.parse_args() add_members(args.mode, args.uni_list, args.group_id_path, args.replace_flag) if __name__ == "__main__": main()