From 1cc0df010a057cccf0d990b5df8cc066d158293d Mon Sep 17 00:00:00 2001
From: PETIT Jeremy <Jeremy.PETIT@ext.ec.europa.eu>
Date: Tue, 21 Mar 2023 16:52:25 +0100
Subject: [PATCH] Diego/scratv2.2.9: sid_user.py now manage last data model,
 fix scrat issues on format

---
 bin/sid_user.py | 177 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 144 insertions(+), 33 deletions(-)

diff --git a/bin/sid_user.py b/bin/sid_user.py
index 209e4ee..101b88e 100755
--- a/bin/sid_user.py
+++ b/bin/sid_user.py
@@ -231,12 +231,12 @@ def ec_ldap_get():
 
 def sid_create_user(diego, dfqdn, res_rw_user, user, block_to_update, context_uid=666000002, verify=True, error_stop=False):
 
-    scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify)
+    scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify, group="DIGIT_SNET_PROX")
     try:
         (scrat_json, scratres) = scrat_inst.scratQuery(block_to_update, Full=True)
     except Exception as e:
         scratres = '409'
-        scrat_json = e
+        scrat_json = 'Creation failed'
 
     if str(scratres) != '200':
         '''Scrat just add the vlan to the trunked list'''
@@ -261,38 +261,138 @@ def sid_create_user(diego, dfqdn, res_rw_user, user, block_to_update, context_ui
             # print('scrat %s update cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
 
 
+def sid_associate_user_to_group(diego, user, ec_ldap_sid_results, scrat, logger):
+    """
+        Function that happen one user to the member of any group.
+
+        Args:
+            diego: Diego Object
+            user: User to assiciate
+            ec_ldap_sid_results: Data content related to LDAP
+            scrat: Scrat Object
+            logger: To print things.
+
+        Returns:
+            Void
+
+        Raises:
+            Scrat error, when appending wont work.
+    """
+    context_uid = 779000000
+    context_name = "AAA"
+    d_get = "auth_get_teams"
+    (h, d_grp_list) = diego._dieget(d_get, {})
+    d_grp_list = list(
+        {
+          "uid": x[0],
+          "name": x[1],
+          "properties": { "has as description": x[3]}
+        } for x in d_grp_list
+    )
+    # For non-existent group : Add-it manually or add the specific feature.
+    # Right to the top of this command.
+    for group in ec_ldap_sid_results['groups']:
+        if user in ec_ldap_sid_results['groups'][group]["mapped-ldap-users"]:
+            # Case : User in the current group. should be changed.
+            if list(x for x in d_grp_list if x["name"] == group):
+                # Case : Group exist in SID, ok for the edit.
+                group_uid = list(x["uid"] for x in d_grp_list if x["name"] == group)[0]
+                new_member = {
+                    "uid": group_uid,
+                    "name": group,
+                    "type": "team",
+                    "context": context_name,
+                    "properties": {
+                        "has as member": user
+                    }
+                }
+                logger.info(f"Try to update {group}...")
+                (scrat_json, scratres) = scrat.scratUpdate(new_member, overwrite_mode=False, line_only=False, Full=True)
+                if str(scratres) != '200':
+                    logger.error(f"Error when trying to add new member '{new_member}' in '{group}':")
+                    logger.error(f"{scrat_json}")
+                else:
+                    logger.info(f"Success !")
+
+
 def sid_update_user(diego, dfqdn, res_rw_user, user, block_to_update, context_uid=666000002, verify=True, error_stop=False):
+    """
+        Update (petjere) : Remove useless error print format to have quick and simple error returned.
+        Also: Block the script if error returned from Scrat (should not happen at all)
+
+        2nd update : Workaround of the input.
+        --> The usage of dict format as value is not stable, use simple string as much as possible !
+    """
 
     ''' delete: need to check the line exist if not 409'''
-    scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify)
+    scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify, group="DIGIT_SNET_PROX")
     try:
+        # logger.info(f"Before {block_to_update}...")
+        # logger.info('\n')
+        block_to_update = reformat_values(block_to_update, logger)
+        logger.info(f"Try to update {block_to_update}...")
         (scrat_json, scratres) = scrat_inst.scratUpdate(block_to_update, overwrite_mode=True, Full=True)
     except Exception as e:
         scratres = '409'
-        scrat_json = e
+        scrat_json = 'Update Failed'
+        raise Exception(e)
 
     if str(scratres) != '200':
-        '''Scrat just add the vlan to the trunked list'''
-        to_print = pformat(block_to_update)
-        for i in list(range(0, int(round(len(to_print) / 250)) + 1)):
-            logger.info('scrat %s update cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
-
-        to_print = pformat(block_to_update)
-        for i in list(range(0, int(round(len(to_print) / 250)) + 1)):
-            logger.error('scrat %s update cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
-            # print('scrat %s update cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
-        to_print = '%s: %s' % (str(scratres), str(scrat_json))
-        for i in list(range(0, int(round(len(to_print) / 250)) + 1)):
-            logger.error('scrat %s update failed: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
-            # print('scrat %s update failed: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
-        if error_stop is True:
-            sys.exit(1)
+        raise Exception(f"{scrat_json}")
     else:
         to_print = pformat(block_to_update)
         for i in list(range(0, int(round(len(to_print) / 250)) + 1)):
             logger.debug('scrat %s update cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
             # print('scrat %s update cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
 
+def reformat_values(scrat_req, logger):
+    """
+        Reformat scrat request to use as much as possible values in string.
+
+        Args:
+            scrat_req: Scrat request about to be reformat.
+
+        Returns:
+            Reformatted scrat request.
+
+        Raises:
+            Format error, if a case is not managed.
+    """
+    new_format = dict()
+    if "properties" not in scrat_req:
+        raise Exception(f"Missing properties on scrat request : '{scrat_req}'")
+    new_format["properties"] = dict()
+
+    for meta_prop in scrat_req:
+        if meta_prop == "properties":
+            continue
+        new_format[meta_prop] = scrat_req[meta_prop]
+
+    for prop in scrat_req["properties"]:
+        if isinstance(scrat_req["properties"][prop], str):
+            if not scrat_req["properties"][prop].strip():
+                continue
+            new_format["properties"][prop] = scrat_req["properties"][prop]
+        elif isinstance(scrat_req["properties"][prop], list):
+            if prop not in new_format["properties"]:
+                new_format["properties"][prop] = list()
+            for elt in scrat_req["properties"][prop]:
+                if isinstance(elt, str):
+                    if not elt.strip():
+                        continue
+                    new_format["properties"][prop].append(elt)
+                elif isinstance(elt, dict):
+                    new_format["properties"][prop].append(elt["name"])
+                else:
+                    raise Exception(f"Unmanaged case, yet: {elt}")
+            # Info : To remove duplicate.
+            new_format["properties"][prop] = list(set(new_format["properties"][prop]))
+        elif isinstance(scrat_req["properties"][prop], dict):
+            new_format["properties"][prop] = scrat_req["properties"][prop]["name"]
+        else:
+            raise Exception(f"Unmanaged case, yet: {scrat_req['properties'][prop]}")
+
+    return new_format
 
 def sid_add_user_to_department(diego, dfqdn, res_rw_user, user, uid, department, context_uid=666000002, verify=True, error_stop=False):
 
@@ -312,11 +412,11 @@ def sid_add_user_to_department(diego, dfqdn, res_rw_user, user, uid, department,
         logger.info('scrat %s update cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
 
     ''' delete: need to check the line exist if not 409'''
-    scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify)
+    scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify, group="DIGIT_SNET_PROX")
     try:
         (scrat_json, scratres) = scrat_inst.scratUpdate(block_to_update, overwrite_mode=False, line_only=False, Full=True)
     except Exception as e:
-        scrat_json = e
+        scrat_json = 'e'
         scratres = '409'
 
     if str(scratres) != '200':
@@ -355,7 +455,7 @@ def sid_update_user_to_resigned(diego, dfqdn, res_rw_user, user, uid, context_ui
         logger.info('scrat %s update cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
 
     ''' delete: need to check the line exist if not 409'''
-    scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify)
+    scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify, group="DIGIT_SNET_PROX")
     try:
         (scrat_json, scratres) = scrat_inst.scratUpdate(block_to_update, overwrite_mode='exclusive', line_only=False, Full=True)
     except Exception as e:
@@ -399,7 +499,7 @@ def sid_update_user_exlude_approver_scheduler_change_management(diego, dfqdn, re
         logger.info('scrat %s update cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
 
     ''' delete: need to check the line exist if not 409'''
-    scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify)
+    scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify, group="DIGIT_SNET_PROX")
     try:
         (scratres) = scrat_inst.deleteLine(block_to_update)
     except Exception as e:
@@ -453,7 +553,7 @@ def sid_create_update_user_approver_scheduler_change_management(diego, dfqdn, re
             logger.info('scrat %s update cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
 
         ''' delete: need to check the line exist if not 409'''
-        scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify)
+        scrat_inst = Scrat(res_rw_user, '', fqdn=dfqdn, version=2, verify=verify, group="DIGIT_SNET_PROX")
         #(scrat_json, scratres) = scrat_inst.scratUpdate(block_to_update,  overwrite_mode=True, line_only=True, Full=True)
         #(scrat_json, scratres) = scrat_inst.scratQuery(block_to_update, Full=True)
         #(scrat_json, scratres) = scrat_inst.scratQuery(scratter, Full=True)
@@ -536,7 +636,7 @@ def main():
         sys.exit(1)
 
     print('Using the SID backend: ' + fqdn)
-    snet_groups = 'com,mgt,net,pm,sd,sec,sup,tda'.split(',')
+    snet_groups = 'com,mgt,net,pm,sd,sec,dev,sys,tda'.split(',')
     official_groups = ['officials']
 
     devnull_del_user = ['systemac']
@@ -551,18 +651,19 @@ def main():
 
     departments = ['DIGIT.C.4', 'DIGIT.C.4.001', 'DIGIT.C.4.002', 'DIGIT.C.4.003', 'DIGIT.C.4.004','DIGIT.C.4.006', 'DIGIT.C.4.007', 'DIGIT.C.4.008']
 
-    approver_scheduler_list = ['fournla', 'chevaju', 'gondago']
+    # Suggestion : Put a dieget instead ?
+    approver_scheduler_list = ['ventufa']
 
     snet_results = dict()
     snet_results = snet_ldap_get()
 
     ec_ldap_sid_results = dict()
-    ec_ldap_sid_results = ec_ldap_get() 
+    ec_ldap_sid_results = ec_ldap_get()
     snet_prox = list()
-    
+
     for group in ec_ldap_sid_results['groups']:
         if group == "DIGIT_SNET_PROX":
-            snet_prox = ec_ldap_sid_results['groups'][group]['mapped-ldap-users']   
+            snet_prox = ec_ldap_sid_results['groups'][group]['mapped-ldap-users']
 
 
     if debug:
@@ -674,16 +775,17 @@ def main():
             ec_results['users'][user]['mail'] = 'proxy user, no email'
             snet_mail_index[ec_results['users'][user]['mail']] = user
             snet_account_index[user] = ec_results['users'][user]['mail']
-            snet_results['users'][user] = dict()    
+            snet_results['users'][user] = dict()
             snet_results['users'][user]['membership'] = list()
-            snet_results['users'][user]['membership'].append('proxy')            
+            snet_results['users'][user]['membership'].append('proxy')
 
     logger.info('Bad User: ' + pformat(bad_user))
     logger.info('Snet User snet_mail_index: ' + pformat(snet_mail_index))
     logger.info('Snet User snet_account_index: ' + pformat(snet_account_index))
 
 
-    diego = Diego(fqdn=fqdn, verify=verify)
+    diego = Diego(fqdn=fqdn, verify=verify, group="DIGIT_SNET_PROX")
+    scrat = Scrat(res_rw_user, '', fqdn=fqdn, version=2, verify=verify, group="DIGIT_SNET_PROX")
     params = {'name': '","'.join(departments)}
     sid_results = diego.diego_run_dieget_by_name('sid_user_check', params)
     params = {'name': '","'.join(departments)}
@@ -1034,7 +1136,7 @@ def main():
                         block_to_update['properties']['has access to easiCAPs feature'].append('Profile Support')
 
             elif mb == 'proxy':
-                #For proxy users, in case more fields are to be added in the future 
+                #For proxy users, in case more fields are to be added in the future
                 if need_to_update is False and need_to_create is True:
                     block_to_update['properties']['belongs to'].append('SNet Prox')
                     block_to_update['properties']['has as role'].append('Proxy User')
@@ -1103,8 +1205,17 @@ def main():
 
         if not dryrun and need_to_create is True:
             sid_create_user(diego, fqdn, res_rw_user, user, block_to_update, verify=verify, error_stop=error_stop)
+
+            # New action : Add any new user into their corresponding EC LDAP group.
+            # Warn : Only impact currently existent group.
+            sid_associate_user_to_group(diego, user, ec_ldap_sid_results, scrat, logger)
+
         elif not dryrun and need_to_update is True:
             sid_update_user(diego, fqdn, res_rw_user, user, block_to_update, verify=verify, error_stop=error_stop)
+
+            # New action : Add any new user into their corresponding EC LDAP group.
+            # Warn : Only impact currently existent group.
+            sid_associate_user_to_group(diego, user, ec_ldap_sid_results, scrat, logger)
         else:
             logger.debug('dryrun')
             to_print = pformat(block_to_update)
-- 
GitLab