@@ -101,7 +101,13 @@ export async function getOrgInfo({
101101              name : x . name , 
102102              username : x . username , 
103103              title : x . title , 
104-             } )  as  {  name : string ;  username : string ;  title : string  |  undefined  } , 
104+               nonVotingMember : x . nonVotingMember  ||  false , 
105+             } )  as  { 
106+               name : string ; 
107+               username : string ; 
108+               title : string  |  undefined ; 
109+               nonVotingMember : boolean ; 
110+             } , 
105111        ) ; 
106112      response  =  {  ...response ,  leads : unmarshalledLeads  } ; 
107113    } 
@@ -525,42 +531,106 @@ export const removeLead = async ({
525531} ; 
526532
527533/** 
528-  * Returns the Microsoft 365 Dynamic User query to return  all members of all lead groups . 
529-  * Currently used  to setup the Exec member list . 
534+  * Returns all voting org leads across  all organizations . 
535+  * Uses consistent reads  to avoid eventual consistency issues . 
530536 * @param  dynamoClient A DynamoDB client. 
531-  * @param  includeGroupIds Used to ensure that a specific group ID is included (Scan could be eventually consistent.)  
537+  * @param  logger A logger instance.  
532538 */ 
533- export  async  function  getLeadsM365DynamicQuery ( { 
539+ export  async  function  getAllVotingLeads ( { 
534540  dynamoClient, 
535-   includeGroupIds , 
541+   logger , 
536542} : { 
537543  dynamoClient : DynamoDBClient ; 
538-   includeGroupIds ?: string [ ] ; 
539- } ) : Promise < string  |  null >  { 
540-   const  command  =  new  ScanCommand ( { 
541-     TableName : genericConfig . SigInfoTableName , 
542-     IndexName : "LeadsGroupIdIndex" , 
544+   logger : ValidLoggers ; 
545+ } ) : Promise < 
546+   Array < {  username : string ;  org : string ;  name : string ;  title : string  } > 
547+ >  { 
548+   // Query all organizations in parallel for better performance 
549+   const  queryPromises  =  AllOrganizationNameList . map ( async  ( orgName )  =>  { 
550+     const  leadsQuery  =  new  QueryCommand ( { 
551+       TableName : genericConfig . SigInfoTableName , 
552+       KeyConditionExpression : "primaryKey = :leadName" , 
553+       ExpressionAttributeValues : { 
554+         ":leadName" : {  S : `LEAD#${ orgName }   } , 
555+       } , 
556+       ConsistentRead : true , 
557+     } ) ; 
558+ 
559+     try  { 
560+       const  responseMarshall  =  await  dynamoClient . send ( leadsQuery ) ; 
561+       if  ( responseMarshall . Items )  { 
562+         return  responseMarshall . Items . map ( ( x )  =>  unmarshall ( x ) ) 
563+           . filter ( ( x )  =>  x . username  &&  ! x . nonVotingMember ) 
564+           . map ( ( x )  =>  ( { 
565+             username : x . username  as  string , 
566+             org : orgName , 
567+             name : x . name  as  string , 
568+             title : x . title  as  string , 
569+           } ) ) ; 
570+       } 
571+       return  [ ] ; 
572+     }  catch  ( e )  { 
573+       if  ( e  instanceof  BaseError )  { 
574+         throw  e ; 
575+       } 
576+       logger . error ( e ) ; 
577+       throw  new  DatabaseFetchError ( { 
578+         message : `Failed to get leads for org ${ orgName }  , 
579+       } ) ; 
580+     } 
543581  } ) ; 
544-   const  results  =  await  dynamoClient . send ( command ) ; 
545-   if  ( ! results  ||  ! results . Items  ||  results . Items . length  ===  0 )  { 
546-     return  null ; 
547-   } 
548-   const  entries  =  results . Items . map ( ( x )  =>  unmarshall ( x ) )  as  { 
549-     primaryKey : string ; 
550-     leadsEntraGroupId : string ; 
551-   } [ ] ; 
552-   const  groupIds  =  entries 
553-     . filter ( ( x )  =>  x . primaryKey . startsWith ( "DEFINE#" ) ) 
554-     . map ( ( x )  =>  x . leadsEntraGroupId ) ; 
555- 
556-   if  ( groupIds . length  ===  0 )  { 
557-     return  null ; 
582+ 
583+   const  results  =  await  Promise . all ( queryPromises ) ; 
584+   return  results . flat ( ) ; 
585+ } 
586+ 
587+ /** 
588+  * Checks if a user should remain in exec council by verifying they are a voting lead of at least one org. 
589+  * Uses consistent reads to avoid eventual consistency issues. 
590+  * @param  username The username to check. 
591+  * @param  dynamoClient A DynamoDB client. 
592+  * @param  logger A logger instance. 
593+  */ 
594+ export  async  function  shouldBeInExecCouncil ( { 
595+   username, 
596+   dynamoClient, 
597+   logger, 
598+ } : { 
599+   username : string ; 
600+   dynamoClient : DynamoDBClient ; 
601+   logger : ValidLoggers ; 
602+ } ) : Promise < boolean >  { 
603+   // Query all orgs to see if this user is a voting lead of any org 
604+   for  ( const  orgName  of  AllOrganizationNameList )  { 
605+     const  leadsQuery  =  new  QueryCommand ( { 
606+       TableName : genericConfig . SigInfoTableName , 
607+       KeyConditionExpression : "primaryKey = :leadName AND entryId = :username" , 
608+       ExpressionAttributeValues : { 
609+         ":leadName" : {  S : `LEAD#${ orgName }   } , 
610+         ":username" : {  S : username  } , 
611+       } , 
612+       ConsistentRead : true , 
613+     } ) ; 
614+ 
615+     try  { 
616+       const  responseMarshall  =  await  dynamoClient . send ( leadsQuery ) ; 
617+       if  ( responseMarshall . Items  &&  responseMarshall . Items . length  >  0 )  { 
618+         const  lead  =  unmarshall ( responseMarshall . Items [ 0 ] ) ; 
619+         // If they're a lead and not a non-voting member, they should be in exec 
620+         if  ( ! lead . nonVotingMember )  { 
621+           return  true ; 
622+         } 
623+       } 
624+     }  catch  ( e )  { 
625+       if  ( e  instanceof  BaseError )  { 
626+         throw  e ; 
627+       } 
628+       logger . error ( e ) ; 
629+       throw  new  DatabaseFetchError ( { 
630+         message : `Failed to check lead status for ${ username } ${ orgName }  , 
631+       } ) ; 
632+     } 
558633  } 
559634
560-   const  formattedGroupIds  =  [ 
561-     ...new  Set ( [ ...( includeGroupIds  ||  [ ] ) ,  ...groupIds ] ) , 
562-   ] 
563-     . map ( ( id )  =>  `'${ id }  ) 
564-     . join ( ", " ) ; 
565-   return  `user.memberOf -any (group.objectId -in [${ formattedGroupIds }  ; 
635+   return  false ; 
566636} 
0 commit comments