gam7 7.21.2__py3-none-any.whl → 7.22.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of gam7 might be problematic. Click here for more details.
- gam/__init__.py +193 -162
- gam/gamlib/glclargs.py +285 -5
- gam/gamlib/glentity.py +7 -3
- {gam7-7.21.2.dist-info → gam7-7.22.0.dist-info}/METADATA +6 -1
- {gam7-7.21.2.dist-info → gam7-7.22.0.dist-info}/RECORD +8 -8
- {gam7-7.21.2.dist-info → gam7-7.22.0.dist-info}/WHEEL +0 -0
- {gam7-7.21.2.dist-info → gam7-7.22.0.dist-info}/entry_points.txt +0 -0
- {gam7-7.21.2.dist-info → gam7-7.22.0.dist-info}/licenses/LICENSE +0 -0
gam/__init__.py
CHANGED
|
@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
|
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
27
|
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
|
|
28
|
-
__version__ = '7.
|
|
28
|
+
__version__ = '7.22.00'
|
|
29
29
|
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
|
30
30
|
|
|
31
31
|
#pylint: disable=wrong-import-position
|
|
@@ -969,14 +969,14 @@ SUSPENDED_CHOICE_MAP = {'notsuspended': False, 'suspended': True}
|
|
|
969
969
|
def _getIsSuspended(myarg):
|
|
970
970
|
if myarg in SUSPENDED_CHOICE_MAP:
|
|
971
971
|
return SUSPENDED_CHOICE_MAP[myarg]
|
|
972
|
-
return getBoolean()
|
|
972
|
+
return getBoolean() #issuspended
|
|
973
973
|
|
|
974
974
|
ARCHIVED_ARGUMENTS = {'notarchived', 'archived', 'isarchived'}
|
|
975
975
|
ARCHIVED_CHOICE_MAP = {'notarchived': False, 'archived': True}
|
|
976
976
|
def _getIsArchived(myarg):
|
|
977
977
|
if myarg in ARCHIVED_CHOICE_MAP:
|
|
978
978
|
return ARCHIVED_CHOICE_MAP[myarg]
|
|
979
|
-
return getBoolean()
|
|
979
|
+
return getBoolean() #isarchived
|
|
980
980
|
|
|
981
981
|
def _getOptionalIsSuspendedIsArchived():
|
|
982
982
|
isSuspended = isArchived = None
|
|
@@ -1549,10 +1549,12 @@ def getOrderBySortOrder(choiceMap, defaultSortOrderChoice='ASCENDING', mapSortOr
|
|
|
1549
1549
|
return (getChoice(choiceMap, mapChoice=True),
|
|
1550
1550
|
getChoice(SORTORDER_CHOICE_MAP, defaultChoice=defaultSortOrderChoice, mapChoice=mapSortOrderChoice))
|
|
1551
1551
|
|
|
1552
|
-
def orgUnitPathQuery(path, isSuspended):
|
|
1552
|
+
def orgUnitPathQuery(path, isSuspended, isArchived):
|
|
1553
1553
|
query = "orgUnitPath='{0}'".format(path.replace("'", "\\'")) if path != '/' else ''
|
|
1554
1554
|
if isSuspended is not None:
|
|
1555
1555
|
query += f' isSuspended={isSuspended}'
|
|
1556
|
+
if isArchived is not None:
|
|
1557
|
+
query += f' isArchived={isArchived}'
|
|
1556
1558
|
return query
|
|
1557
1559
|
|
|
1558
1560
|
def makeOrgUnitPathAbsolute(path):
|
|
@@ -6247,63 +6249,77 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|
|
6247
6249
|
_showInvalidEntity(Ent.USER, user)
|
|
6248
6250
|
if GC.Values[GC.USER_SERVICE_ACCOUNT_ACCESS_ONLY]:
|
|
6249
6251
|
return entityList
|
|
6250
|
-
elif entityType in
|
|
6252
|
+
elif entityType in Cmd.ALL_USER_ENTITY_TYPES:
|
|
6251
6253
|
cd = buildGAPIObject(API.DIRECTORY)
|
|
6252
|
-
if entityType == Cmd.ENTITY_ALL_USERS and isSuspended is not None:
|
|
6253
|
-
|
|
6254
|
+
if entityType == Cmd.ENTITY_ALL_USERS and ((isSuspended is not None) or (isArchived is not None)):
|
|
6255
|
+
if isSuspended is not None:
|
|
6256
|
+
query = f'isSuspended={isSuspended}'
|
|
6257
|
+
if isArchived is not None:
|
|
6258
|
+
query += f' isArchived={isArchived}'
|
|
6259
|
+
else:
|
|
6260
|
+
query = f'isArchived={isArchived}'
|
|
6254
6261
|
else:
|
|
6255
6262
|
query = Cmd.ALL_USERS_QUERY_MAP[entityType]
|
|
6256
|
-
printGettingAllAccountEntities(Ent.USER)
|
|
6263
|
+
printGettingAllAccountEntities(Ent.USER, query=query)
|
|
6257
6264
|
try:
|
|
6258
6265
|
result = callGAPIpages(cd.users(), 'list', 'users',
|
|
6259
6266
|
pageMessage=getPageMessage(),
|
|
6260
6267
|
throwReasons=[GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN],
|
|
6261
6268
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
6262
|
-
customer=GC.Values[GC.CUSTOMER_ID],
|
|
6263
|
-
|
|
6269
|
+
customer=GC.Values[GC.CUSTOMER_ID], query=query, orderBy='email',
|
|
6270
|
+
fields='nextPageToken,users(primaryEmail)',
|
|
6264
6271
|
maxResults=GC.Values[GC.USER_MAX_RESULTS])
|
|
6265
6272
|
except (GAPI.badRequest, GAPI.resourceNotFound, GAPI.forbidden):
|
|
6266
6273
|
accessErrorExit(cd)
|
|
6267
|
-
entityList = [user['primaryEmail'] for user in result
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
query
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6274
|
+
entityList = [user['primaryEmail'] for user in result]
|
|
6275
|
+
elif entityType == Cmd.ENTITY_ALL_USERS_ARCH_OR_SUSP:
|
|
6276
|
+
cd = buildGAPIObject(API.DIRECTORY)
|
|
6277
|
+
for query in ['isSuspended=True', 'isArchived=True']:
|
|
6278
|
+
printGettingAllAccountEntities(Ent.USER, query)
|
|
6279
|
+
try:
|
|
6280
|
+
result = callGAPIpages(cd.users(), 'list', 'users',
|
|
6281
|
+
pageMessage=getPageMessage(),
|
|
6282
|
+
throwReasons=[GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN],
|
|
6283
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
6284
|
+
customer=GC.Values[GC.CUSTOMER_ID], query=query, orderBy='email',
|
|
6285
|
+
fields='nextPageToken,users(primaryEmail)',
|
|
6286
|
+
maxResults=GC.Values[GC.USER_MAX_RESULTS])
|
|
6287
|
+
except (GAPI.badRequest, GAPI.resourceNotFound, GAPI.forbidden):
|
|
6288
|
+
accessErrorExit(cd)
|
|
6289
|
+
entitySet |= {user['primaryEmail'] for user in result}
|
|
6290
|
+
entityList = sorted(list(entitySet))
|
|
6291
|
+
elif entityType in Cmd.DOMAIN_ENTITY_TYPES:
|
|
6292
|
+
if entityType == Cmd.ENTITY_DOMAINS and ((isSuspended is not None) or (isArchived is not None)):
|
|
6293
|
+
if isSuspended is not None:
|
|
6294
|
+
query = f'isSuspended={isSuspended}'
|
|
6295
|
+
if isArchived is not None:
|
|
6296
|
+
query += f' isArchived={isArchived}'
|
|
6297
|
+
else:
|
|
6298
|
+
query = f'isArchived={isArchived}'
|
|
6276
6299
|
else:
|
|
6277
|
-
query =
|
|
6300
|
+
query = Cmd.DOMAINS_QUERY_MAP[entityType]
|
|
6278
6301
|
cd = buildGAPIObject(API.DIRECTORY)
|
|
6279
6302
|
domains = convertEntityToList(entity)
|
|
6280
6303
|
for domain in domains:
|
|
6281
|
-
printGettingAllEntityItemsForWhom(Ent.USER, domain, entityType=Ent.DOMAIN)
|
|
6304
|
+
printGettingAllEntityItemsForWhom(Ent.USER, domain, query=query, entityType=Ent.DOMAIN)
|
|
6282
6305
|
try:
|
|
6283
6306
|
result = callGAPIpages(cd.users(), 'list', 'users',
|
|
6284
6307
|
pageMessage=getPageMessageForWhom(),
|
|
6285
6308
|
throwReasons=[GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.DOMAIN_NOT_FOUND, GAPI.FORBIDDEN],
|
|
6286
6309
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
6287
|
-
domain=domain,
|
|
6288
|
-
|
|
6310
|
+
domain=domain, query=query, orderBy='email',
|
|
6311
|
+
fields='nextPageToken,users(primaryEmail)',
|
|
6289
6312
|
maxResults=GC.Values[GC.USER_MAX_RESULTS])
|
|
6290
6313
|
except (GAPI.badRequest, GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.forbidden):
|
|
6291
6314
|
checkEntityDNEorAccessErrorExit(cd, Ent.DOMAIN, domain)
|
|
6292
6315
|
_incrEntityDoesNotExist(Ent.DOMAIN)
|
|
6293
6316
|
continue
|
|
6294
|
-
entityList
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
Cmd.ENTITY_GROUP_NS, Cmd.ENTITY_GROUPS_NS,
|
|
6298
|
-
Cmd.ENTITY_GROUP_SUSP, Cmd.ENTITY_GROUPS_SUSP,
|
|
6299
|
-
Cmd.ENTITY_GROUP_INDE, Cmd.ENTITY_GROUPS_INDE}:
|
|
6300
|
-
if entityType in {Cmd.ENTITY_GROUP_NS, Cmd.ENTITY_GROUPS_NS}:
|
|
6301
|
-
isSuspended = False
|
|
6302
|
-
elif entityType in {Cmd.ENTITY_GROUP_SUSP, Cmd.ENTITY_GROUPS_SUSP}:
|
|
6303
|
-
isSuspended = True
|
|
6317
|
+
entityList.extend([user['primaryEmail'] for user in result])
|
|
6318
|
+
elif entityType in Cmd.GROUP_ENTITY_TYPES or entityType in Cmd.GROUPS_ENTITY_TYPES:
|
|
6319
|
+
isArchived, isSuspended = Cmd.GROUPS_QUERY_MAP.get(entityType, (isArchived, isSuspended))
|
|
6304
6320
|
includeDerivedMembership = entityType in {Cmd.ENTITY_GROUP_INDE, Cmd.ENTITY_GROUPS_INDE}
|
|
6305
6321
|
cd = buildGAPIObject(API.DIRECTORY)
|
|
6306
|
-
groups = convertEntityToList(entity, nonListEntityType=entityType in
|
|
6322
|
+
groups = convertEntityToList(entity, nonListEntityType=entityType in Cmd.GROUP_ENTITY_TYPES)
|
|
6307
6323
|
for group in groups:
|
|
6308
6324
|
if validateEmailAddressOrUID(group, checkPeople=False):
|
|
6309
6325
|
group = normalizeEmailAddressOrUID(group)
|
|
@@ -6329,11 +6345,8 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|
|
6329
6345
|
entityList.append(email)
|
|
6330
6346
|
else:
|
|
6331
6347
|
_showInvalidEntity(Ent.GROUP, group)
|
|
6332
|
-
elif entityType in
|
|
6333
|
-
|
|
6334
|
-
isSuspended = False
|
|
6335
|
-
elif entityType == Cmd.ENTITY_GROUP_USERS_SUSP:
|
|
6336
|
-
isSuspended = True
|
|
6348
|
+
elif entityType in Cmd.GROUP_USERS_ENTITY_TYPES:
|
|
6349
|
+
isArchived, isSuspended = Cmd.GROUP_USERS_QUERY_MAP.get(entityType, (isArchived, isSuspended))
|
|
6337
6350
|
cd = buildGAPIObject(API.DIRECTORY)
|
|
6338
6351
|
groups = convertEntityToList(entity)
|
|
6339
6352
|
includeDerivedMembership = False
|
|
@@ -6424,21 +6437,13 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|
|
6424
6437
|
_addCIGroupUsersToUsers(name, groupEmail, recursive)
|
|
6425
6438
|
else:
|
|
6426
6439
|
_showInvalidEntity(Ent.GROUP, group)
|
|
6427
|
-
elif entityType in
|
|
6428
|
-
|
|
6429
|
-
Cmd.ENTITY_OU_SUSP, Cmd.ENTITY_OUS_SUSP, Cmd.ENTITY_OU_AND_CHILDREN_SUSP, Cmd.ENTITY_OUS_AND_CHILDREN_SUSP}:
|
|
6430
|
-
if entityType in {Cmd.ENTITY_OU_NS, Cmd.ENTITY_OUS_NS, Cmd.ENTITY_OU_AND_CHILDREN_NS, Cmd.ENTITY_OUS_AND_CHILDREN_NS}:
|
|
6431
|
-
isSuspended = False
|
|
6432
|
-
elif entityType in {Cmd.ENTITY_OU_SUSP, Cmd.ENTITY_OUS_SUSP, Cmd.ENTITY_OU_AND_CHILDREN_SUSP, Cmd.ENTITY_OUS_AND_CHILDREN_SUSP}:
|
|
6433
|
-
isSuspended = True
|
|
6440
|
+
elif entityType in Cmd.OU_ENTITY_TYPES or entityType in Cmd.OUS_ENTITY_TYPES:
|
|
6441
|
+
isArchived, isSuspended = Cmd.OU_QUERY_MAP.get(entityType, (isArchived, isSuspended))
|
|
6434
6442
|
cd = buildGAPIObject(API.DIRECTORY)
|
|
6435
|
-
ous = convertEntityToList(entity, shlexSplit=True, nonListEntityType=entityType in
|
|
6436
|
-
|
|
6437
|
-
Cmd.ENTITY_OU_SUSP, Cmd.ENTITY_OU_AND_CHILDREN_SUSP})
|
|
6438
|
-
directlyInOU = entityType in {Cmd.ENTITY_OU, Cmd.ENTITY_OUS, Cmd.ENTITY_OU_NS, Cmd.ENTITY_OUS_NS, Cmd.ENTITY_OU_SUSP, Cmd.ENTITY_OUS_SUSP}
|
|
6443
|
+
ous = convertEntityToList(entity, shlexSplit=True, nonListEntityType=entityType in Cmd.OU_ENTITY_TYPES)
|
|
6444
|
+
directlyInOU = entityType in Cmd.OU_DIRECT_ENTITY_TYPES
|
|
6439
6445
|
qualifier = Msg.DIRECTLY_IN_THE.format(Ent.Singular(Ent.ORGANIZATIONAL_UNIT)) if directlyInOU else Msg.IN_THE.format(Ent.Singular(Ent.ORGANIZATIONAL_UNIT))
|
|
6440
|
-
fields = 'nextPageToken,users(primaryEmail,orgUnitPath
|
|
6441
|
-
prevLen = 0
|
|
6446
|
+
fields = 'nextPageToken,users(primaryEmail,orgUnitPath)' if directlyInOU else 'nextPageToken,users(primaryEmail)'
|
|
6442
6447
|
for ou in ous:
|
|
6443
6448
|
ou = makeOrgUnitPathAbsolute(ou)
|
|
6444
6449
|
if ou.startswith('id:'):
|
|
@@ -6463,22 +6468,17 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|
|
6463
6468
|
throwReasons=[GAPI.INVALID_ORGUNIT, GAPI.ORGUNIT_NOT_FOUND,
|
|
6464
6469
|
GAPI.INVALID_INPUT, GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN],
|
|
6465
6470
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
6466
|
-
customer=GC.Values[GC.CUSTOMER_ID], query=orgUnitPathQuery(ou, isSuspended), orderBy='email',
|
|
6471
|
+
customer=GC.Values[GC.CUSTOMER_ID], query=orgUnitPathQuery(ou, isSuspended, isArchived), orderBy='email',
|
|
6467
6472
|
fields=fields, maxResults=GC.Values[GC.USER_MAX_RESULTS])
|
|
6468
6473
|
for users in feed:
|
|
6469
6474
|
if directlyInOU:
|
|
6470
6475
|
for user in users:
|
|
6471
|
-
if ouLower == user.get('orgUnitPath', '').lower()
|
|
6476
|
+
if ouLower == user.get('orgUnitPath', '').lower():
|
|
6472
6477
|
usersInOU += 1
|
|
6473
6478
|
entityList.append(user['primaryEmail'])
|
|
6474
|
-
|
|
6479
|
+
else:
|
|
6475
6480
|
entityList.extend([user['primaryEmail'] for user in users])
|
|
6476
6481
|
usersInOU += len(users)
|
|
6477
|
-
else:
|
|
6478
|
-
for user in users:
|
|
6479
|
-
if isArchived == user['archived']:
|
|
6480
|
-
usersInOU += 1
|
|
6481
|
-
entityList.append(user['primaryEmail'])
|
|
6482
6482
|
setGettingAllEntityItemsForWhom(Ent.USER, ou, qualifier=qualifier)
|
|
6483
6483
|
printGotEntityItemsForWhom(usersInOU)
|
|
6484
6484
|
except (GAPI.invalidInput, GAPI.invalidOrgunit, GAPI.orgunitNotFound, GAPI.backendError, GAPI.badRequest,
|
|
@@ -6488,7 +6488,6 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|
|
6488
6488
|
elif entityType in {Cmd.ENTITY_QUERY, Cmd.ENTITY_QUERIES}:
|
|
6489
6489
|
cd = buildGAPIObject(API.DIRECTORY)
|
|
6490
6490
|
queries = convertEntityToList(entity, shlexSplit=True, nonListEntityType=entityType == Cmd.ENTITY_QUERY)
|
|
6491
|
-
prevLen = 0
|
|
6492
6491
|
for query in queries:
|
|
6493
6492
|
printGettingAllAccountEntities(Ent.USER, query)
|
|
6494
6493
|
try:
|
|
@@ -6512,9 +6511,6 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|
|
6512
6511
|
email not in entitySet):
|
|
6513
6512
|
entitySet.add(email)
|
|
6514
6513
|
entityList.append(email)
|
|
6515
|
-
totalLen = len(entityList)
|
|
6516
|
-
printGotAccountEntities(totalLen-prevLen)
|
|
6517
|
-
prevLen = totalLen
|
|
6518
6514
|
elif entityType == Cmd.ENTITY_LICENSES:
|
|
6519
6515
|
skusList = []
|
|
6520
6516
|
for item in entity.split(','):
|
|
@@ -6573,8 +6569,7 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|
|
6573
6569
|
ClientAPIAccessDeniedExit(str(e))
|
|
6574
6570
|
elif entityType == Cmd.ENTITY_CROS:
|
|
6575
6571
|
buildGAPIObject(API.DIRECTORY)
|
|
6576
|
-
|
|
6577
|
-
for deviceId in result:
|
|
6572
|
+
for deviceId in convertEntityToList(entity):
|
|
6578
6573
|
if deviceId not in entitySet:
|
|
6579
6574
|
entitySet.add(deviceId)
|
|
6580
6575
|
entityList.append(deviceId)
|
|
@@ -6598,7 +6593,6 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|
|
6598
6593
|
nonListEntityType=entityType == Cmd.ENTITY_CROS_QUERY)
|
|
6599
6594
|
if entityType == Cmd.ENTITY_CROS_SN:
|
|
6600
6595
|
queries = [f'id:{query}' for query in queries]
|
|
6601
|
-
prevLen = 0
|
|
6602
6596
|
for query in queries:
|
|
6603
6597
|
printGettingAllAccountEntities(Ent.CROS_DEVICE, query)
|
|
6604
6598
|
try:
|
|
@@ -6619,25 +6613,15 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|
|
6619
6613
|
if deviceId not in entitySet:
|
|
6620
6614
|
entitySet.add(deviceId)
|
|
6621
6615
|
entityList.append(deviceId)
|
|
6622
|
-
|
|
6623
|
-
printGotAccountEntities(totalLen-prevLen)
|
|
6624
|
-
prevLen = totalLen
|
|
6625
|
-
elif entityType in {Cmd.ENTITY_CROS_OU, Cmd.ENTITY_CROS_OU_AND_CHILDREN, Cmd.ENTITY_CROS_OUS, Cmd.ENTITY_CROS_OUS_AND_CHILDREN,
|
|
6626
|
-
Cmd.ENTITY_CROS_OU_QUERY, Cmd.ENTITY_CROS_OU_AND_CHILDREN_QUERY, Cmd.ENTITY_CROS_OUS_QUERY, Cmd.ENTITY_CROS_OUS_AND_CHILDREN_QUERY,
|
|
6627
|
-
Cmd.ENTITY_CROS_OU_QUERIES, Cmd.ENTITY_CROS_OU_AND_CHILDREN_QUERIES, Cmd.ENTITY_CROS_OUS_QUERIES, Cmd.ENTITY_CROS_OUS_AND_CHILDREN_QUERIES}:
|
|
6616
|
+
elif entityType in Cmd.CROS_OU_ENTITY_TYPES or entityType in Cmd.CROS_OUS_ENTITY_TYPES:
|
|
6628
6617
|
cd = buildGAPIObject(API.DIRECTORY)
|
|
6629
|
-
ous = convertEntityToList(entity, shlexSplit=True,
|
|
6630
|
-
nonListEntityType=entityType in {Cmd.ENTITY_CROS_OU, Cmd.ENTITY_CROS_OU_AND_CHILDREN,
|
|
6631
|
-
Cmd.ENTITY_CROS_OU_QUERY, Cmd.ENTITY_CROS_OU_AND_CHILDREN_QUERY,
|
|
6632
|
-
Cmd.ENTITY_CROS_OU_QUERIES, Cmd.ENTITY_CROS_OU_AND_CHILDREN_QUERIES})
|
|
6618
|
+
ous = convertEntityToList(entity, shlexSplit=True, nonListEntityType=entityType in Cmd.CROS_OU_ENTITY_TYPES)
|
|
6633
6619
|
numOus = len(ous)
|
|
6634
|
-
includeChildOrgunits = entityType in
|
|
6635
|
-
Cmd.ENTITY_CROS_OU_AND_CHILDREN_QUERY, Cmd.ENTITY_CROS_OUS_AND_CHILDREN_QUERY,
|
|
6636
|
-
Cmd.ENTITY_CROS_OU_AND_CHILDREN_QUERIES, Cmd.ENTITY_CROS_OUS_AND_CHILDREN_QUERIES}
|
|
6620
|
+
includeChildOrgunits = entityType in Cmd.CROS_OU_CHILDREN_ENTITY_TYPES
|
|
6637
6621
|
allQualifier = Msg.DIRECTLY_IN_THE.format(Ent.Choose(Ent.ORGANIZATIONAL_UNIT, numOus)) if not includeChildOrgunits else Msg.IN_THE.format(Ent.Choose(Ent.ORGANIZATIONAL_UNIT, numOus))
|
|
6638
|
-
if entityType in
|
|
6622
|
+
if entityType in Cmd.CROS_OU_QUERY_ENTITY_TYPES:
|
|
6639
6623
|
queries = getQueries('query')
|
|
6640
|
-
elif entityType in
|
|
6624
|
+
elif entityType in Cmd.CROS_OU_QUERIES_ENTITY_TYPES:
|
|
6641
6625
|
queries = getQueries('queries')
|
|
6642
6626
|
else:
|
|
6643
6627
|
queries = [None]
|
|
@@ -6710,7 +6694,6 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|
|
6710
6694
|
customerId = _getCustomerIdNoC()
|
|
6711
6695
|
queries = convertEntityToList(entity, shlexSplit=entityType == Cmd.ENTITY_BROWSER_QUERIES,
|
|
6712
6696
|
nonListEntityType=entityType == Cmd.ENTITY_BROWSER_QUERY)
|
|
6713
|
-
prevLen = 0
|
|
6714
6697
|
for query in queries:
|
|
6715
6698
|
printGettingAllAccountEntities(Ent.CHROME_BROWSER, query)
|
|
6716
6699
|
try:
|
|
@@ -6730,9 +6713,6 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|
|
6730
6713
|
if deviceId not in entitySet:
|
|
6731
6714
|
entitySet.add(deviceId)
|
|
6732
6715
|
entityList.append(deviceId)
|
|
6733
|
-
totalLen = len(entityList)
|
|
6734
|
-
printGotAccountEntities(totalLen-prevLen)
|
|
6735
|
-
prevLen = totalLen
|
|
6736
6716
|
else:
|
|
6737
6717
|
systemErrorExit(UNKNOWN_ERROR_RC, 'getItemsToModify coding error')
|
|
6738
6718
|
for errorType in [ENTITY_ERROR_DNE, ENTITY_ERROR_INVALID]:
|
|
@@ -7045,10 +7025,7 @@ def getEntityToModify(defaultEntityType=None, browserAllowed=False, crosAllowed=
|
|
|
7045
7025
|
choices += Cmd.CROS_ENTITY_SELECTOR_DATAFILE_CSVKMD_SUBTYPES
|
|
7046
7026
|
entityType = mapEntityType(getChoice(choices), typeMap)
|
|
7047
7027
|
return (Cmd.ENTITY_USERS if entityType not in Cmd.CROS_ENTITY_SELECTOR_DATAFILE_CSVKMD_SUBTYPES else Cmd.ENTITY_CROS,
|
|
7048
|
-
getItemsToModify(entityType, getEntitiesFromFile(shlexSplit=entityType in
|
|
7049
|
-
Cmd.ENTITY_OUS_NS, Cmd.ENTITY_OUS_AND_CHILDREN_NS,
|
|
7050
|
-
Cmd.ENTITY_OUS_SUSP, Cmd.ENTITY_OUS_AND_CHILDREN_SUSP,
|
|
7051
|
-
Cmd.ENTITY_CROS_OUS, Cmd.ENTITY_CROS_OUS_AND_CHILDREN])))
|
|
7028
|
+
getItemsToModify(entityType, getEntitiesFromFile(shlexSplit=entityType in Cmd.OUS_ENTITY_TYPES | {Cmd.ENTITY_CROS_OUS, Cmd.ENTITY_CROS_OUS_AND_CHILDREN})))
|
|
7052
7029
|
if entitySelector == Cmd.ENTITY_SELECTOR_CSVDATAFILE:
|
|
7053
7030
|
if userAllowed:
|
|
7054
7031
|
choices += Cmd.USER_ENTITY_SELECTOR_DATAFILE_CSVKMD_SUBTYPES if not GC.Values[GC.USER_SERVICE_ACCOUNT_ACCESS_ONLY] else [Cmd.ENTITY_USERS]
|
|
@@ -7056,10 +7033,7 @@ def getEntityToModify(defaultEntityType=None, browserAllowed=False, crosAllowed=
|
|
|
7056
7033
|
choices += Cmd.CROS_ENTITY_SELECTOR_DATAFILE_CSVKMD_SUBTYPES
|
|
7057
7034
|
entityType = mapEntityType(getChoice(choices), typeMap)
|
|
7058
7035
|
return (Cmd.ENTITY_USERS if entityType not in Cmd.CROS_ENTITY_SELECTOR_DATAFILE_CSVKMD_SUBTYPES else Cmd.ENTITY_CROS,
|
|
7059
|
-
getItemsToModify(entityType, getEntitiesFromCSVFile(shlexSplit=entityType in
|
|
7060
|
-
Cmd.ENTITY_OUS_NS, Cmd.ENTITY_OUS_AND_CHILDREN_NS,
|
|
7061
|
-
Cmd.ENTITY_OUS_SUSP, Cmd.ENTITY_OUS_AND_CHILDREN_SUSP,
|
|
7062
|
-
Cmd.ENTITY_CROS_OUS, Cmd.ENTITY_CROS_OUS_AND_CHILDREN])))
|
|
7036
|
+
getItemsToModify(entityType, getEntitiesFromCSVFile(shlexSplit=entityType in Cmd.OUS_ENTITY_TYPES | {Cmd.ENTITY_CROS_OUS, Cmd.ENTITY_CROS_OUS_AND_CHILDREN})))
|
|
7063
7037
|
if entitySelector == Cmd.ENTITY_SELECTOR_CSVKMD:
|
|
7064
7038
|
if userAllowed:
|
|
7065
7039
|
choices += Cmd.USER_ENTITY_SELECTOR_DATAFILE_CSVKMD_SUBTYPES if not GC.Values[GC.USER_SERVICE_ACCOUNT_ACCESS_ONLY] else [Cmd.ENTITY_USERS]
|
|
@@ -7102,10 +7076,7 @@ def getEntityToModify(defaultEntityType=None, browserAllowed=False, crosAllowed=
|
|
|
7102
7076
|
if not GC.Values[GC.USER_SERVICE_ACCOUNT_ACCESS_ONLY]:
|
|
7103
7077
|
buildGAPIObject(API.DIRECTORY)
|
|
7104
7078
|
if entityClass == Cmd.ENTITY_USERS:
|
|
7105
|
-
if entityType in
|
|
7106
|
-
Cmd.ENTITY_GROUP_USERS_NS, Cmd.ENTITY_GROUP_USERS_SUSP,
|
|
7107
|
-
Cmd.ENTITY_GROUP_USERS_SELECT,
|
|
7108
|
-
Cmd.ENTITY_CIGROUP_USERS]:
|
|
7079
|
+
if entityType in Cmd.GROUP_USERS_ENTITY_TYPES | {Cmd.ENTITY_CIGROUP_USERS}:
|
|
7109
7080
|
# Skip over sub-arguments
|
|
7110
7081
|
while Cmd.ArgumentsRemaining():
|
|
7111
7082
|
myarg = getArgument()
|
|
@@ -10149,8 +10120,8 @@ def threadBatchWorker(showCmds=False, numItems=0):
|
|
|
10149
10120
|
batchWriteStderr(f'{currentISOformatTimeStamp()},{pid}/{numItems},Error,{str(e)},{logCmd}\n')
|
|
10150
10121
|
GM.Globals[GM.TBATCH_QUEUE].task_done()
|
|
10151
10122
|
|
|
10152
|
-
BATCH_COMMANDS = [Cmd.GAM_CMD, Cmd.COMMIT_BATCH_CMD, Cmd.PRINT_CMD, Cmd.SLEEP_CMD]
|
|
10153
|
-
TBATCH_COMMANDS = [Cmd.GAM_CMD, Cmd.COMMIT_BATCH_CMD, Cmd.EXECUTE_CMD, Cmd.PRINT_CMD, Cmd.SLEEP_CMD]
|
|
10123
|
+
BATCH_COMMANDS = [Cmd.GAM_CMD, Cmd.COMMIT_BATCH_CMD, Cmd.PRINT_CMD, Cmd.SLEEP_CMD, Cmd.DATETIME_CMD, Cmd.SET_CMD, Cmd.CLEAR_CMD]
|
|
10124
|
+
TBATCH_COMMANDS = [Cmd.GAM_CMD, Cmd.COMMIT_BATCH_CMD, Cmd.EXECUTE_CMD, Cmd.PRINT_CMD, Cmd.SLEEP_CMD, Cmd.DATETIME_CMD, Cmd.SET_CMD, Cmd.CLEAR_CMD]
|
|
10154
10125
|
|
|
10155
10126
|
def ThreadBatchGAMCommands(items, showCmds):
|
|
10156
10127
|
if not items:
|
|
@@ -10262,6 +10233,14 @@ def doBatch(threadBatch=False):
|
|
|
10262
10233
|
continue
|
|
10263
10234
|
if argv:
|
|
10264
10235
|
cmd = argv[0].strip().lower()
|
|
10236
|
+
if cmd == Cmd.DATETIME_CMD:
|
|
10237
|
+
if len(argv) == 2:
|
|
10238
|
+
kwValues['datetime'] = todaysTime().strftime(argv[1])
|
|
10239
|
+
else:
|
|
10240
|
+
writeStderr(f'Command: >>>{Cmd.QuotedArgumentList([argv[0]])}<<< {Cmd.QuotedArgumentList(argv[1:])}\n')
|
|
10241
|
+
writeStderr(f'{ERROR_PREFIX}{Cmd.ARGUMENT_ERROR_NAMES[Cmd.ARGUMENT_INVALID][1]}: {Msg.EXPECTED} <{Cmd.DATETIME_CMD} DateTimeFormat>)>\n')
|
|
10242
|
+
errors += 1
|
|
10243
|
+
continue
|
|
10265
10244
|
if cmd == Cmd.SET_CMD:
|
|
10266
10245
|
if len(argv) == 3:
|
|
10267
10246
|
kwValues[argv[1]] = argv[2]
|
|
@@ -13353,7 +13332,7 @@ def getUserOrgUnits(cd, orgUnit, orgUnitId):
|
|
|
13353
13332
|
throwReasons=[GAPI.INVALID_ORGUNIT, GAPI.ORGUNIT_NOT_FOUND,
|
|
13354
13333
|
GAPI.INVALID_INPUT, GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN],
|
|
13355
13334
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
13356
|
-
customer=GC.Values[GC.CUSTOMER_ID], query=orgUnitPathQuery(orgUnit, None), orderBy='email',
|
|
13335
|
+
customer=GC.Values[GC.CUSTOMER_ID], query=orgUnitPathQuery(orgUnit, None, None), orderBy='email',
|
|
13357
13336
|
fields='nextPageToken,users(primaryEmail,orgUnitPath)', maxResults=GC.Values[GC.USER_MAX_RESULTS])
|
|
13358
13337
|
userOrgUnits = {}
|
|
13359
13338
|
for user in result:
|
|
@@ -17848,10 +17827,29 @@ ORG_FIELD_INFO_ORDER = ['orgUnitId', 'name', 'description', 'parentOrgUnitPath',
|
|
|
17848
17827
|
ORG_FIELDS_WITH_CRS_NLS = {'description'}
|
|
17849
17828
|
|
|
17850
17829
|
def _doInfoOrgs(entityList):
|
|
17830
|
+
def _printUsers(entityType, orgUnitPath, isSuspended, isArchived):
|
|
17831
|
+
users = callGAPIpages(cd.users(), 'list', 'users',
|
|
17832
|
+
throwReasons=[GAPI.BAD_REQUEST, GAPI.INVALID_INPUT, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN],
|
|
17833
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
17834
|
+
customer=GC.Values[GC.CUSTOMER_ID], query=orgUnitPathQuery(orgUnitPath, isSuspended, isArchived), orderBy='email',
|
|
17835
|
+
fields='nextPageToken,users(primaryEmail,orgUnitPath)', maxResults=GC.Values[GC.USER_MAX_RESULTS])
|
|
17836
|
+
printEntitiesCount(entityType, None)
|
|
17837
|
+
usersInOU = 0
|
|
17838
|
+
Ind.Increment()
|
|
17839
|
+
orgUnitPath = orgUnitPath.lower()
|
|
17840
|
+
for user in users:
|
|
17841
|
+
if orgUnitPath == user['orgUnitPath'].lower():
|
|
17842
|
+
printKeyValueList([user['primaryEmail']])
|
|
17843
|
+
usersInOU += 1
|
|
17844
|
+
elif showChildren:
|
|
17845
|
+
printKeyValueList([f'{user["primaryEmail"]} (child)'])
|
|
17846
|
+
usersInOU += 1
|
|
17847
|
+
Ind.Decrement()
|
|
17848
|
+
printKeyValueList([Msg.TOTAL_ITEMS_IN_ENTITY.format(Ent.Plural(entityType), Ent.Singular(Ent.ORGANIZATIONAL_UNIT)), usersInOU])
|
|
17849
|
+
|
|
17851
17850
|
cd = buildGAPIObject(API.DIRECTORY)
|
|
17852
17851
|
getUsers = True
|
|
17853
|
-
isSuspended = None
|
|
17854
|
-
entityType = Ent.USER
|
|
17852
|
+
isSuspended = isArchived = None
|
|
17855
17853
|
showChildren = False
|
|
17856
17854
|
while Cmd.ArgumentsRemaining():
|
|
17857
17855
|
myarg = getArgument()
|
|
@@ -17859,7 +17857,8 @@ def _doInfoOrgs(entityList):
|
|
|
17859
17857
|
getUsers = False
|
|
17860
17858
|
elif myarg in SUSPENDED_ARGUMENTS:
|
|
17861
17859
|
isSuspended = _getIsSuspended(myarg)
|
|
17862
|
-
|
|
17860
|
+
elif myarg in ARCHIVED_ARGUMENTS:
|
|
17861
|
+
isArchived = _getIsArchived(myarg)
|
|
17863
17862
|
elif myarg in {'children', 'child'}:
|
|
17864
17863
|
showChildren = True
|
|
17865
17864
|
else:
|
|
@@ -17890,38 +17889,29 @@ def _doInfoOrgs(entityList):
|
|
|
17890
17889
|
printKeyValueWithCRsNLs(field, value)
|
|
17891
17890
|
if getUsers:
|
|
17892
17891
|
orgUnitPath = result['orgUnitPath']
|
|
17893
|
-
|
|
17894
|
-
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17898
|
-
|
|
17899
|
-
|
|
17900
|
-
Ind.Increment()
|
|
17901
|
-
orgUnitPath = orgUnitPath.lower()
|
|
17902
|
-
for user in users:
|
|
17903
|
-
if orgUnitPath == user['orgUnitPath'].lower():
|
|
17904
|
-
printKeyValueList([user['primaryEmail']])
|
|
17905
|
-
usersInOU += 1
|
|
17906
|
-
elif showChildren:
|
|
17907
|
-
printKeyValueList([f'{user["primaryEmail"]} (child)'])
|
|
17908
|
-
usersInOU += 1
|
|
17909
|
-
Ind.Decrement()
|
|
17910
|
-
printKeyValueList([Msg.TOTAL_ITEMS_IN_ENTITY.format(Ent.Plural(entityType), Ent.Singular(Ent.ORGANIZATIONAL_UNIT)), usersInOU])
|
|
17892
|
+
if isArchived is None and isSuspended is None:
|
|
17893
|
+
_printUsers(Ent.USER, orgUnitPath, None, None)
|
|
17894
|
+
else:
|
|
17895
|
+
if isArchived is not None:
|
|
17896
|
+
_printUsers(Ent.USER_ARCHIVED if isArchived else Ent.USER_NOT_ARCHIVED, orgUnitPath, None, isArchived)
|
|
17897
|
+
if isSuspended is not None:
|
|
17898
|
+
_printUsers(Ent.USER_SUSPENDED if isSuspended else Ent.USER_NOT_SUSPENDED, orgUnitPath, isSuspended, None)
|
|
17911
17899
|
Ind.Decrement()
|
|
17912
17900
|
except (GAPI.invalidInput, GAPI.invalidOrgunit, GAPI.orgunitNotFound, GAPI.backendError):
|
|
17913
17901
|
entityActionFailedWarning([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], Msg.DOES_NOT_EXIST, i, count)
|
|
17914
17902
|
except (GAPI.badRequest, GAPI.invalidCustomerId, GAPI.loginRequired, GAPI.resourceNotFound, GAPI.forbidden):
|
|
17915
17903
|
checkEntityAFDNEorAccessErrorExit(cd, Ent.ORGANIZATIONAL_UNIT, orgUnitPath)
|
|
17916
17904
|
|
|
17917
|
-
# gam info
|
|
17918
|
-
|
|
17919
|
-
_doInfoOrgs(getEntityList(Cmd.OB_ORGUNIT_ENTITY, shlexSplit=True))
|
|
17920
|
-
|
|
17921
|
-
# gam info org|ou <OrgUnitItem> [nousers|notsuspended|suspended] [children|child]
|
|
17905
|
+
# gam info org|ou <OrgUnitItem>
|
|
17906
|
+
# [nousers | ([notarchived|archived] [notsuspended|suspended])] [children|child]
|
|
17922
17907
|
def doInfoOrg():
|
|
17923
17908
|
_doInfoOrgs([getOrgUnitItem()])
|
|
17924
17909
|
|
|
17910
|
+
# gam info orgs|ous <OrgUnitEntity>
|
|
17911
|
+
# [nousers | ([notarchived|archived] [notsuspended|suspended])] [children|child]
|
|
17912
|
+
def doInfoOrgs():
|
|
17913
|
+
_doInfoOrgs(getEntityList(Cmd.OB_ORGUNIT_ENTITY, shlexSplit=True))
|
|
17914
|
+
|
|
17925
17915
|
ORG_ARGUMENT_TO_FIELD_MAP = {
|
|
17926
17916
|
'blockinheritance': 'blockInheritance',
|
|
17927
17917
|
'inheritanceblocked': 'blockInheritance',
|
|
@@ -18151,7 +18141,7 @@ def doPrintOrgs():
|
|
|
18151
18141
|
return
|
|
18152
18142
|
if showUserCounts:
|
|
18153
18143
|
for orgUnit in orgUnits:
|
|
18154
|
-
userCounts[orgUnit['orgUnitPath']] = [0, 0]
|
|
18144
|
+
userCounts[orgUnit['orgUnitPath']] = {'suspended': [0, 0], 'archived': [0, 0], 'total': 0}
|
|
18155
18145
|
qualifier = Msg.IN_THE.format(Ent.Singular(Ent.ORGANIZATIONAL_UNIT))
|
|
18156
18146
|
printGettingAllEntityItemsForWhom(Ent.USER, orgUnitPath, qualifier=qualifier, entityType=Ent.ORGANIZATIONAL_UNIT)
|
|
18157
18147
|
pageMessage = getPageMessageForWhom()
|
|
@@ -18161,12 +18151,14 @@ def doPrintOrgs():
|
|
|
18161
18151
|
throwReasons=[GAPI.INVALID_ORGUNIT, GAPI.ORGUNIT_NOT_FOUND,
|
|
18162
18152
|
GAPI.INVALID_INPUT, GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN],
|
|
18163
18153
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
18164
|
-
customer=GC.Values[GC.CUSTOMER_ID], query=orgUnitPathQuery(orgUnitPath, None), orderBy='email',
|
|
18165
|
-
fields='nextPageToken,users(orgUnitPath,suspended)', maxResults=GC.Values[GC.USER_MAX_RESULTS])
|
|
18154
|
+
customer=GC.Values[GC.CUSTOMER_ID], query=orgUnitPathQuery(orgUnitPath, None, None), orderBy='email',
|
|
18155
|
+
fields='nextPageToken,users(orgUnitPath,suspended,archived)', maxResults=GC.Values[GC.USER_MAX_RESULTS])
|
|
18166
18156
|
for users in feed:
|
|
18167
18157
|
for user in users:
|
|
18168
18158
|
if user['orgUnitPath'] in userCounts:
|
|
18169
|
-
userCounts[user['orgUnitPath']][user['suspended']] += 1
|
|
18159
|
+
userCounts[user['orgUnitPath']]['suspended'][user['suspended']] += 1
|
|
18160
|
+
userCounts[user['orgUnitPath']]['archived'][user['archived']] += 1
|
|
18161
|
+
userCounts[user['orgUnitPath']]['total'] += 1
|
|
18170
18162
|
except (GAPI.invalidOrgunit, GAPI.orgunitNotFound, GAPI.invalidInput, GAPI.badRequest, GAPI.backendError,
|
|
18171
18163
|
GAPI.invalidCustomerId, GAPI.loginRequired, GAPI.resourceNotFound, GAPI.forbidden):
|
|
18172
18164
|
checkEntityDNEorAccessErrorExit(cd, Ent.ORGANIZATIONAL_UNIT, orgUnitPath)
|
|
@@ -18233,15 +18225,34 @@ def doPrintOrgs():
|
|
|
18233
18225
|
(maxCrOSCounts != -1 and total > maxCrOSCounts)):
|
|
18234
18226
|
continue
|
|
18235
18227
|
if showUserCounts:
|
|
18236
|
-
row[f'Users{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}
|
|
18237
|
-
row[f'Users{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}
|
|
18238
|
-
row[f'Users{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}
|
|
18228
|
+
row[f'Users{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}NotArchived'] = userCounts[orgUnitPath]['archived'][0]
|
|
18229
|
+
row[f'Users{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}Archived'] = userCounts[orgUnitPath]['archived'][1]
|
|
18230
|
+
row[f'Users{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}NotSuspended'] = userCounts[orgUnitPath]['suspended'][0]
|
|
18231
|
+
row[f'Users{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}Suspended'] = userCounts[orgUnitPath]['suspended'][1]
|
|
18232
|
+
row[f'Users{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}Total'] = total = userCounts[orgUnitPath]['total']
|
|
18239
18233
|
if ((minUserCounts != -1 and total < minUserCounts) or
|
|
18240
18234
|
(maxUserCounts != -1 and total > maxUserCounts)):
|
|
18241
18235
|
continue
|
|
18242
18236
|
csvPF.WriteRowTitles(row)
|
|
18243
18237
|
else:
|
|
18244
18238
|
csvPF.WriteRow(row)
|
|
18239
|
+
if showCrOSCounts or showUserCounts:
|
|
18240
|
+
crosTitles = []
|
|
18241
|
+
userTitles = []
|
|
18242
|
+
allTitles = csvPF.titlesList[:]
|
|
18243
|
+
for title in allTitles:
|
|
18244
|
+
if showCrOSCounts and title.startswith(f'CrOS{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}'):
|
|
18245
|
+
crosTitles.append(title)
|
|
18246
|
+
csvPF.RemoveTitles(title)
|
|
18247
|
+
if showUserCounts and title.startswith(f'Users{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}'):
|
|
18248
|
+
userTitles.append(title)
|
|
18249
|
+
csvPF.RemoveTitles(title)
|
|
18250
|
+
if showCrOSCounts:
|
|
18251
|
+
csvPF.AddTitles(sorted(crosTitles))
|
|
18252
|
+
if showUserCounts:
|
|
18253
|
+
for title in ['NotArchived', 'Archived', 'NotSuspended', 'Suspended', 'Total']:
|
|
18254
|
+
csvPF.AddTitles(f'Users{GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]}{title}')
|
|
18255
|
+
csvPF.SetSortTitles([])
|
|
18245
18256
|
csvPF.writeCSVfile('Orgs')
|
|
18246
18257
|
|
|
18247
18258
|
# gam show orgtree [fromparent <OrgUnitItem>] [batchsuborgs [Boolean>]]
|
|
@@ -18451,7 +18462,7 @@ def doCheckOrgUnit():
|
|
|
18451
18462
|
throwReasons=[GAPI.INVALID_ORGUNIT, GAPI.ORGUNIT_NOT_FOUND,
|
|
18452
18463
|
GAPI.INVALID_INPUT, GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN],
|
|
18453
18464
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
18454
|
-
customer=GC.Values[GC.CUSTOMER_ID], query=orgUnitPathQuery(orgUnitPath, None),
|
|
18465
|
+
customer=GC.Values[GC.CUSTOMER_ID], query=orgUnitPathQuery(orgUnitPath, None, None),
|
|
18455
18466
|
fields='nextPageToken,users(orgUnitPath)', maxResults=GC.Values[GC.USER_MAX_RESULTS])
|
|
18456
18467
|
for users in feed:
|
|
18457
18468
|
for user in users:
|
|
@@ -18872,7 +18883,7 @@ def makeUserGroupDomainQueryFilters(kwargsDict):
|
|
|
18872
18883
|
kwargsQueries.append((kwargs, query))
|
|
18873
18884
|
return kwargsQueries
|
|
18874
18885
|
|
|
18875
|
-
def userFilters(kwargs, query, orgUnitPath, isSuspended):
|
|
18886
|
+
def userFilters(kwargs, query, orgUnitPath, isSuspended, isArchived):
|
|
18876
18887
|
queryTitle = ''
|
|
18877
18888
|
if kwargs.get('domain'):
|
|
18878
18889
|
queryTitle += f'domain={kwargs["domain"]}, '
|
|
@@ -18891,6 +18902,12 @@ def userFilters(kwargs, query, orgUnitPath, isSuspended):
|
|
|
18891
18902
|
else:
|
|
18892
18903
|
query += ' '
|
|
18893
18904
|
query += f'isSuspended={isSuspended}'
|
|
18905
|
+
if isArchived is not None:
|
|
18906
|
+
if query is None:
|
|
18907
|
+
query = ''
|
|
18908
|
+
else:
|
|
18909
|
+
query += ' '
|
|
18910
|
+
query += f'isArchived={isArchived}'
|
|
18894
18911
|
if query is not None:
|
|
18895
18912
|
queryTitle += f'query="{query}", '
|
|
18896
18913
|
if queryTitle:
|
|
@@ -18902,7 +18919,7 @@ def userFilters(kwargs, query, orgUnitPath, isSuspended):
|
|
|
18902
18919
|
# [limittoou <OrgUnitItem>])
|
|
18903
18920
|
# [user|users <EmailAddressList>] [group|groups <EmailAddressList>]
|
|
18904
18921
|
# [select <UserTypeEntity>]
|
|
18905
|
-
# [issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
|
18922
|
+
# [issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
|
18906
18923
|
# [shownoneditable] [nogroups] [nousers]
|
|
18907
18924
|
# [onerowpertarget] [delimiter <Character>]
|
|
18908
18925
|
# [suppressnoaliasrows]
|
|
@@ -18948,7 +18965,7 @@ def doPrintAliases():
|
|
|
18948
18965
|
groups = []
|
|
18949
18966
|
users = []
|
|
18950
18967
|
aliasMatchPattern = re.compile(r'^.*$')
|
|
18951
|
-
isSuspended = orgUnitPath = None
|
|
18968
|
+
isArchived = isSuspended = orgUnitPath = None
|
|
18952
18969
|
addCSVData = {}
|
|
18953
18970
|
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
|
|
18954
18971
|
while Cmd.ArgumentsRemaining():
|
|
@@ -18972,8 +18989,10 @@ def doPrintAliases():
|
|
|
18972
18989
|
pass
|
|
18973
18990
|
elif myarg == 'select':
|
|
18974
18991
|
_, users = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
|
|
18975
|
-
elif myarg
|
|
18976
|
-
isSuspended =
|
|
18992
|
+
elif myarg in SUSPENDED_ARGUMENTS:
|
|
18993
|
+
isSuspended = _getIsSuspended(myarg)
|
|
18994
|
+
elif myarg in ARCHIVED_ARGUMENTS:
|
|
18995
|
+
isArchived = _getIsArchived(myarg)
|
|
18977
18996
|
elif myarg in {'user','users'}:
|
|
18978
18997
|
users.extend(convertEntityToList(getString(Cmd.OB_EMAIL_ADDRESS_LIST, minLen=0)))
|
|
18979
18998
|
elif myarg in {'group', 'groups'}:
|
|
@@ -19008,7 +19027,7 @@ def doPrintAliases():
|
|
|
19008
19027
|
for kwargsQuery in makeUserGroupDomainQueryFilters(kwargsDict):
|
|
19009
19028
|
kwargs = kwargsQuery[0]
|
|
19010
19029
|
query = kwargsQuery[1]
|
|
19011
|
-
query, pquery = userFilters(kwargs, query, orgUnitPath, isSuspended)
|
|
19030
|
+
query, pquery = userFilters(kwargs, query, orgUnitPath, isSuspended, isArchived)
|
|
19012
19031
|
printGettingAllAccountEntities(Ent.USER, pquery)
|
|
19013
19032
|
try:
|
|
19014
19033
|
entityList = callGAPIpages(cd.users(), 'list', 'users',
|
|
@@ -43947,6 +43966,7 @@ def getUserAttributes(cd, updateCmd, noUid=False):
|
|
|
43947
43966
|
invalidArgumentExit(Cmd.OB_SCHEMA_NAME_FIELD_NAME)
|
|
43948
43967
|
|
|
43949
43968
|
parameters = {
|
|
43969
|
+
'notifyRecoveryEmail': False,
|
|
43950
43970
|
'verifyNotInvitable': False,
|
|
43951
43971
|
'createIfNotFound': False,
|
|
43952
43972
|
'noActionIfAlias': False,
|
|
@@ -43963,7 +43983,7 @@ def getUserAttributes(cd, updateCmd, noUid=False):
|
|
|
43963
43983
|
body = {'name': {'givenName': UNKNOWN, 'familyName': UNKNOWN}}
|
|
43964
43984
|
body['primaryEmail'] = getEmailAddress(noUid=noUid)
|
|
43965
43985
|
notFoundBody = {}
|
|
43966
|
-
notify = {'subject': '', 'message': '', 'html': False, 'charset': UTF8, 'password': ''}
|
|
43986
|
+
notify = {'recipients': [], 'subject': '', 'message': '', 'html': False, 'charset': UTF8, 'password': ''}
|
|
43967
43987
|
primary = {}
|
|
43968
43988
|
updatePrimaryEmail = {}
|
|
43969
43989
|
groupOrgUnitMap = None
|
|
@@ -43975,7 +43995,9 @@ def getUserAttributes(cd, updateCmd, noUid=False):
|
|
|
43975
43995
|
while Cmd.ArgumentsRemaining():
|
|
43976
43996
|
myarg = getArgument()
|
|
43977
43997
|
if myarg == 'notify':
|
|
43978
|
-
notify['recipients']
|
|
43998
|
+
notify['recipients'].extend(getNormalizedEmailAddressEntity(shlexSplit=True, noLower=True))
|
|
43999
|
+
elif myarg == 'notifyrecoveryemail':
|
|
44000
|
+
parameters['notifyRecoveryEmail'] = True
|
|
43979
44001
|
elif myarg == 'subject':
|
|
43980
44002
|
notify['subject'] = getString(Cmd.OB_STRING)
|
|
43981
44003
|
elif myarg in SORF_MSG_FILE_ARGUMENTS:
|
|
@@ -44391,7 +44413,7 @@ def createUserAddAliases(cd, user, aliasList, i, count):
|
|
|
44391
44413
|
# (groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
|
|
44392
44414
|
# [alias|aliases <EmailAddressList>]
|
|
44393
44415
|
# [license <SKUID> [product|productid <ProductID>]]
|
|
44394
|
-
# [notify <EmailAddressList>
|
|
44416
|
+
# [[notify <EmailAddressList>] [notifyrecoveryemail]
|
|
44395
44417
|
# [subject <String>]
|
|
44396
44418
|
# [notifypassword <String>]
|
|
44397
44419
|
# [from <EmailAaddress>]
|
|
@@ -44409,7 +44431,7 @@ def doCreateUser():
|
|
|
44409
44431
|
suffix = 0
|
|
44410
44432
|
originalEmail = body['primaryEmail']
|
|
44411
44433
|
atLoc = originalEmail.find('@')
|
|
44412
|
-
fields = '*' if tagReplacements['subs'] else 'primaryEmail,name'
|
|
44434
|
+
fields = '*' if tagReplacements['subs'] else 'primaryEmail,name,recoveryEmail'
|
|
44413
44435
|
while True:
|
|
44414
44436
|
user = body['primaryEmail']
|
|
44415
44437
|
if parameters['verifyNotInvitable']:
|
|
@@ -44450,7 +44472,9 @@ def doCreateUser():
|
|
|
44450
44472
|
createUserAddToGroups(cd, result['primaryEmail'], addGroups, 0, 0)
|
|
44451
44473
|
if addAliases:
|
|
44452
44474
|
createUserAddAliases(cd, result['primaryEmail'], addAliases, 0, 0)
|
|
44453
|
-
if notify.get('recipients'):
|
|
44475
|
+
if (notify.get('recipients') or (parameters['notifyRecoveryEmail'] and result.get('recoveryEmail'))):
|
|
44476
|
+
if parameters['notifyRecoveryEmail'] and result.get('recoveryEmail'):
|
|
44477
|
+
notify['recipients'].append(result['recoveryEmail'])
|
|
44454
44478
|
sendCreateUpdateUserNotification(result, notify, tagReplacements)
|
|
44455
44479
|
for productSku in parameters[LICENSE_PRODUCT_SKUIDS]:
|
|
44456
44480
|
productId = productSku[0]
|
|
@@ -44493,7 +44517,7 @@ def verifyUserPrimaryEmail(cd, user, createIfNotFound, i, count):
|
|
|
44493
44517
|
# [createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
|
|
44494
44518
|
# (groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
|
|
44495
44519
|
# [alias|aliases <EmailAddressList>]
|
|
44496
|
-
# [notify <EmailAddressList>
|
|
44520
|
+
# [[notify <EmailAddressList>] [notifyrecoveryemail]
|
|
44497
44521
|
# [subject <String>]
|
|
44498
44522
|
# [notifypassword <String>]
|
|
44499
44523
|
# [from <EmailAaddress>]
|
|
@@ -44522,7 +44546,7 @@ def updateUsers(entityList):
|
|
|
44522
44546
|
else:
|
|
44523
44547
|
checkImmutableOUs = False
|
|
44524
44548
|
i, count, entityList = getEntityArgument(entityList)
|
|
44525
|
-
fields = '*' if tagReplacements['subs'] else 'primaryEmail,name'
|
|
44549
|
+
fields = '*' if tagReplacements['subs'] else 'primaryEmail,name,recoveryEmail'
|
|
44526
44550
|
for user in entityList:
|
|
44527
44551
|
i += 1
|
|
44528
44552
|
user = userKey = normalizeEmailAddressOrUID(user)
|
|
@@ -44598,7 +44622,10 @@ def updateUsers(entityList):
|
|
|
44598
44622
|
entityActionPerformed([Ent.USER, user], i, count)
|
|
44599
44623
|
if PwdOpts.filename and PwdOpts.password:
|
|
44600
44624
|
writeFile(PwdOpts.filename, f'{userKey},{PwdOpts.password}\n', mode='a', continueOnError=True)
|
|
44601
|
-
if parameters['notifyOnUpdate'] and notify
|
|
44625
|
+
if (parameters['notifyOnUpdate'] and notify['password'] and
|
|
44626
|
+
(notify.get('recipients') or (parameters['notifyRecoveryEmail'] and result.get('recoveryEmail')))):
|
|
44627
|
+
if parameters['notifyRecoveryEmail'] and result.get('recoveryEmail'):
|
|
44628
|
+
notify['recipients'].append(result['recoveryEmail'])
|
|
44602
44629
|
sendCreateUpdateUserNotification(result, notify, tagReplacements, i, count, createMessage=False)
|
|
44603
44630
|
break
|
|
44604
44631
|
except GAPI.conditionNotMet as e:
|
|
@@ -44632,8 +44659,10 @@ def updateUsers(entityList):
|
|
|
44632
44659
|
createUserAddToGroups(cd, result['primaryEmail'], addGroups, i, count)
|
|
44633
44660
|
if addAliases:
|
|
44634
44661
|
createUserAddAliases(cd, result['primaryEmail'], addAliases, i, count)
|
|
44635
|
-
if notify.get('recipients'):
|
|
44662
|
+
if (notify.get('recipients') or (parameters['notifyRecoveryEmail'] and result.get('recoveryEmail'))):
|
|
44636
44663
|
notify['password'] = notify['notFoundPassword']
|
|
44664
|
+
if parameters['notifyRecoveryEmail'] and result.get('recoveryEmail'):
|
|
44665
|
+
notify['recipients'].append(result['recoveryEmail'])
|
|
44637
44666
|
sendCreateUpdateUserNotification(result, notify, tagReplacements, i, count)
|
|
44638
44667
|
except GAPI.duplicate:
|
|
44639
44668
|
duplicateAliasGroupUserWarning(cd, [Ent.USER, body['primaryEmail']], i, count)
|
|
@@ -45680,7 +45709,7 @@ USERS_INDEXED_TITLES = ['addresses', 'aliases', 'nonEditableAliases', 'emails',
|
|
|
45680
45709
|
# [userview] [basic|full|allfields | <UserFieldName>* | fields <UserFieldNameList>]
|
|
45681
45710
|
# [delimiter <Character>] [sortheaders] [formatjson [quotechar <Character>]] [quoteplusphonenumbers]
|
|
45682
45711
|
# [convertcrnl]
|
|
45683
|
-
# [issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
|
45712
|
+
# [issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
|
45684
45713
|
# [showitemcountonly]
|
|
45685
45714
|
# [showvalidcolumn] (addcsvdata <FieldName> <String>)*
|
|
45686
45715
|
#
|
|
@@ -45693,7 +45722,7 @@ USERS_INDEXED_TITLES = ['addresses', 'aliases', 'nonEditableAliases', 'emails',
|
|
|
45693
45722
|
# [userview] [basic|full|allfields | <UserFieldName>* | fields <UserFieldNameList>]
|
|
45694
45723
|
# [delimiter <Character>] [sortheaders] [formatjson [quotechar <Character>]] [quoteplusphonenumbers]
|
|
45695
45724
|
# [convertcrnl]
|
|
45696
|
-
# [issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
|
45725
|
+
# [issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
|
45697
45726
|
# [showitemcountonly]
|
|
45698
45727
|
# [showvalidcolumn] (addcsvdata <FieldName> <String>)*
|
|
45699
45728
|
#
|
|
@@ -45701,13 +45730,13 @@ USERS_INDEXED_TITLES = ['addresses', 'aliases', 'nonEditableAliases', 'emails',
|
|
|
45701
45730
|
# ([domain <DomainName>] [(query <QueryUser>)|(queries <QueryUserList>)]
|
|
45702
45731
|
# [limittoou <OrgUnitItem>] [deleted_only|only_deleted])|[select <UserTypeEntity>]
|
|
45703
45732
|
# [formatjson [quotechar <Character>]] [countonly]
|
|
45704
|
-
# [issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
|
45733
|
+
# [issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
|
45705
45734
|
# [showitemcountonly]
|
|
45706
45735
|
# [showvalidcolumn] (addcsvdata <FieldName> <String>)*
|
|
45707
45736
|
#
|
|
45708
45737
|
# gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
|
|
45709
45738
|
# [formatjson [quotechar <Character>]] [countonly]
|
|
45710
|
-
# [issuspended <Boolean>]
|
|
45739
|
+
# [issuspended <Boolean>] [isarchived <Boolean>]
|
|
45711
45740
|
# [showitemcountonly]
|
|
45712
45741
|
def doPrintUsers(entityList=None):
|
|
45713
45742
|
def _writeUserEntity(userEntity):
|
|
@@ -45863,7 +45892,7 @@ def doPrintUsers(entityList=None):
|
|
|
45863
45892
|
schemaParms = _initSchemaParms('basic')
|
|
45864
45893
|
projectionSet = False
|
|
45865
45894
|
oneLicensePerRow = quotePlusPhoneNumbers = showDeleted = False
|
|
45866
|
-
aliasMatchPattern = isSuspended = orgUnitPath = orgUnitPathLower = orderBy = sortOrder = None
|
|
45895
|
+
aliasMatchPattern = isArchived = isSuspended = orgUnitPath = orgUnitPathLower = orderBy = sortOrder = None
|
|
45867
45896
|
viewType = 'admin_view'
|
|
45868
45897
|
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
|
|
45869
45898
|
showValidColumn = ''
|
|
@@ -45882,8 +45911,10 @@ def doPrintUsers(entityList=None):
|
|
|
45882
45911
|
showDeleted = True
|
|
45883
45912
|
elif entityList is None and myarg == 'select':
|
|
45884
45913
|
_, entityList = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
|
|
45885
|
-
elif myarg
|
|
45886
|
-
isSuspended =
|
|
45914
|
+
elif myarg in SUSPENDED_ARGUMENTS:
|
|
45915
|
+
isSuspended = _getIsSuspended(myarg)
|
|
45916
|
+
elif myarg in ARCHIVED_ARGUMENTS:
|
|
45917
|
+
isArchived = _getIsArchived(myarg)
|
|
45887
45918
|
elif myarg == 'orderby':
|
|
45888
45919
|
orderBy, sortOrder = getOrderBySortOrder(USERS_ORDERBY_CHOICE_MAP)
|
|
45889
45920
|
elif myarg == 'userview':
|
|
@@ -45996,7 +46027,7 @@ def doPrintUsers(entityList=None):
|
|
|
45996
46027
|
for kwargsQuery in makeUserGroupDomainQueryFilters(kwargsDict):
|
|
45997
46028
|
kwargs = kwargsQuery[0]
|
|
45998
46029
|
query = kwargsQuery[1]
|
|
45999
|
-
query, pquery = userFilters(kwargs, query, orgUnitPath, isSuspended)
|
|
46030
|
+
query, pquery = userFilters(kwargs, query, orgUnitPath, isSuspended, isArchived)
|
|
46000
46031
|
printGettingAllAccountEntities(Ent.USER, pquery)
|
|
46001
46032
|
pageMessage = getPageMessage(showFirstLastItems=True)
|
|
46002
46033
|
try:
|
|
@@ -46006,9 +46037,9 @@ def doPrintUsers(entityList=None):
|
|
|
46006
46037
|
GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN,
|
|
46007
46038
|
GAPI.UNKNOWN_ERROR, GAPI.FAILED_PRECONDITION],
|
|
46008
46039
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS+[GAPI.UNKNOWN_ERROR, GAPI.FAILED_PRECONDITION],
|
|
46009
|
-
query=query, fields=fields,
|
|
46010
46040
|
showDeleted=showDeleted, orderBy=orderBy, sortOrder=sortOrder, viewType=viewType,
|
|
46011
46041
|
projection=schemaParms['projection'], customFieldMask=schemaParms['customFieldMask'],
|
|
46042
|
+
query=query, fields=fields,
|
|
46012
46043
|
maxResults=maxResults, **kwargs)
|
|
46013
46044
|
for users in feed:
|
|
46014
46045
|
if orgUnitPath is None:
|
|
@@ -54960,7 +54991,7 @@ def getDriveFileAttribute(myarg, body, parameters, updateCmd):
|
|
|
54960
54991
|
elif myarg == 'timestamp':
|
|
54961
54992
|
parameters[DFA_TIMESTAMP] = getBoolean()
|
|
54962
54993
|
elif myarg == 'timeformat':
|
|
54963
|
-
parameters[DFA_TIMEFORMAT] = getString(Cmd.
|
|
54994
|
+
parameters[DFA_TIMEFORMAT] = getString(Cmd.OB_DATETIME_FORMAT, minLen=0)
|
|
54964
54995
|
elif getDriveFileCopyAttribute(myarg, body, parameters):
|
|
54965
54996
|
pass
|
|
54966
54997
|
else:
|
|
@@ -59547,7 +59578,7 @@ createReturnItemMap = {
|
|
|
59547
59578
|
# [(localfile <FileName>|-)|(url <URL>)]
|
|
59548
59579
|
# [(drivefilename|newfilename <DriveFileName>) | (replacefilename <REMatchPattern> <RESubstitution>)*]
|
|
59549
59580
|
# [stripnameprefix <String>]
|
|
59550
|
-
# [timestamp <Boolean>]] [timeformat <
|
|
59581
|
+
# [timestamp <Boolean>]] [timeformat <DateTimeFormat>]
|
|
59551
59582
|
# <DriveFileCreateAttribute>* [noduplicate]
|
|
59552
59583
|
# [(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*)) |
|
|
59553
59584
|
# (returnidonly|returnlinkonly|returneditlinkonly|showdetails)]
|
|
@@ -60074,7 +60105,7 @@ def checkDriveFileShortcut(users):
|
|
|
60074
60105
|
# [(localfile <FileName>|-)|(url <URL>)]
|
|
60075
60106
|
# [retainname | (newfilename <DriveFileName>) | (replacefilename <REMatchPattern> <RESubstitution>)*]
|
|
60076
60107
|
# [stripnameprefix <String>]
|
|
60077
|
-
# [timestamp <Boolean>]] [timeformat <
|
|
60108
|
+
# [timestamp <Boolean>]] [timeformat <DateTimeFormat>]
|
|
60078
60109
|
# <DriveFileUpdateAttribute>*
|
|
60079
60110
|
# [(gsheet|csvsheet <SheetEntity> [clearfilter])|(addsheet <String>)]
|
|
60080
60111
|
# [charset <String>] [columndelimiter <Character>]
|