gam7 7.4.2__tar.gz → 7.4.4__tar.gz

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.

Files changed (107) hide show
  1. {gam7-7.4.2 → gam7-7.4.4}/PKG-INFO +1 -1
  2. {gam7-7.4.2 → gam7-7.4.4}/src/GamCommands.txt +8 -4
  3. {gam7-7.4.2 → gam7-7.4.4}/src/GamUpdate.txt +19 -0
  4. {gam7-7.4.2 → gam7-7.4.4}/src/gam/__init__.py +75 -33
  5. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glcfg.py +8 -0
  6. {gam7-7.4.2 → gam7-7.4.4}/.github/ISSUE_TEMPLATE/aa-question.md +0 -0
  7. {gam7-7.4.2 → gam7-7.4.4}/.github/ISSUE_TEMPLATE/za-bug-report.md +0 -0
  8. {gam7-7.4.2 → gam7-7.4.4}/.github/ISSUE_TEMPLATE/zz-feature-request.md +0 -0
  9. {gam7-7.4.2 → gam7-7.4.4}/.github/ISSUE_TEMPLATE.txt +0 -0
  10. {gam7-7.4.2 → gam7-7.4.4}/.github/actions/creds.tar.xz.gpg +0 -0
  11. {gam7-7.4.2 → gam7-7.4.4}/.github/actions/decrypt.sh +0 -0
  12. {gam7-7.4.2 → gam7-7.4.4}/.github/actions/entitlements.plist +0 -0
  13. {gam7-7.4.2 → gam7-7.4.4}/.github/actions/package_exclusions.txt +0 -0
  14. {gam7-7.4.2 → gam7-7.4.4}/.github/stale.yml +0 -0
  15. {gam7-7.4.2 → gam7-7.4.4}/.github/workflows/build.yml +0 -0
  16. {gam7-7.4.2 → gam7-7.4.4}/.github/workflows/codeql-analysis.yml +0 -0
  17. {gam7-7.4.2 → gam7-7.4.4}/.github/workflows/get-cacerts.yml +0 -0
  18. {gam7-7.4.2 → gam7-7.4.4}/.github/workflows/pypi.yml +0 -0
  19. {gam7-7.4.2 → gam7-7.4.4}/.pre-commit-config.yaml +0 -0
  20. {gam7-7.4.2 → gam7-7.4.4}/LICENSE +0 -0
  21. {gam7-7.4.2 → gam7-7.4.4}/README.md +0 -0
  22. {gam7-7.4.2 → gam7-7.4.4}/pyproject.toml +0 -0
  23. {gam7-7.4.2 → gam7-7.4.4}/src/.gitignore +0 -0
  24. {gam7-7.4.2 → gam7-7.4.4}/src/LICENSE +0 -0
  25. {gam7-7.4.2 → gam7-7.4.4}/src/cacerts.pem +0 -0
  26. {gam7-7.4.2 → gam7-7.4.4}/src/callgam.py +0 -0
  27. {gam7-7.4.2 → gam7-7.4.4}/src/gam/__main__.py +0 -0
  28. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/__init__.py +0 -0
  29. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/auth.py +0 -0
  30. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/client.py +0 -0
  31. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/core.py +0 -0
  32. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/data.py +0 -0
  33. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/http.py +0 -0
  34. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/http_core.py +0 -0
  35. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/http_interface.py +0 -0
  36. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/mock_http.py +0 -0
  37. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/mock_http_core.py +0 -0
  38. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/mock_service.py +0 -0
  39. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/service.py +0 -0
  40. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/token_store.py +0 -0
  41. {gam7-7.4.2 → gam7-7.4.4}/src/gam/atom/url.py +0 -0
  42. {gam7-7.4.2 → gam7-7.4.4}/src/gam/cacerts.pem +0 -0
  43. {gam7-7.4.2 → gam7-7.4.4}/src/gam/cbcm-v1.1beta1.json +0 -0
  44. {gam7-7.4.2 → gam7-7.4.4}/src/gam/contactdelegation-v1.json +0 -0
  45. {gam7-7.4.2 → gam7-7.4.4}/src/gam/datastudio-v1.json +0 -0
  46. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/__init__.py +0 -0
  47. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glaction.py +0 -0
  48. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glapi.py +0 -0
  49. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glclargs.py +0 -0
  50. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glentity.py +0 -0
  51. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glgapi.py +0 -0
  52. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glgdata.py +0 -0
  53. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glglobals.py +0 -0
  54. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glindent.py +0 -0
  55. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glmsgs.py +0 -0
  56. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glskus.py +0 -0
  57. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/gluprop.py +0 -0
  58. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/glverlibs.py +0 -0
  59. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gamlib/yubikey.py +0 -0
  60. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/__init__.py +0 -0
  61. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/alt/__init__.py +0 -0
  62. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/alt/app_engine.py +0 -0
  63. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/alt/appengine.py +0 -0
  64. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/apps/__init__.py +0 -0
  65. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/apps/audit/__init__.py +0 -0
  66. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/apps/audit/service.py +0 -0
  67. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/apps/contacts/__init__.py +0 -0
  68. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/apps/contacts/service.py +0 -0
  69. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/apps/service.py +0 -0
  70. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/service.py +0 -0
  71. {gam7-7.4.2 → gam7-7.4.4}/src/gam/gdata/urlfetch.py +0 -0
  72. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/__init__.py +0 -0
  73. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/_auth.py +0 -0
  74. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/_helpers.py +0 -0
  75. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/channel.py +0 -0
  76. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/discovery.py +0 -0
  77. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/discovery_cache/__init__.py +0 -0
  78. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/discovery_cache/appengine_memcache.py +0 -0
  79. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/discovery_cache/base.py +0 -0
  80. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/discovery_cache/file_cache.py +0 -0
  81. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/errors.py +0 -0
  82. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/http.py +0 -0
  83. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/mimeparse.py +0 -0
  84. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/model.py +0 -0
  85. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/schema.py +0 -0
  86. {gam7-7.4.2 → gam7-7.4.4}/src/gam/googleapiclient/version.py +0 -0
  87. {gam7-7.4.2 → gam7-7.4.4}/src/gam/iso8601/__init__.py +0 -0
  88. {gam7-7.4.2 → gam7-7.4.4}/src/gam/iso8601/iso8601.py +0 -0
  89. {gam7-7.4.2 → gam7-7.4.4}/src/gam/serviceaccountlookup-v1.json +0 -0
  90. {gam7-7.4.2 → gam7-7.4.4}/src/gam/six.py +0 -0
  91. {gam7-7.4.2 → gam7-7.4.4}/src/gam-install.sh +0 -0
  92. {gam7-7.4.2 → gam7-7.4.4}/src/gam-setup.bat +0 -0
  93. {gam7-7.4.2 → gam7-7.4.4}/src/gam.exe.manifest +0 -0
  94. {gam7-7.4.2 → gam7-7.4.4}/src/gam.py +0 -0
  95. {gam7-7.4.2 → gam7-7.4.4}/src/gam.spec +0 -0
  96. {gam7-7.4.2 → gam7-7.4.4}/src/gam.wxs +0 -0
  97. {gam7-7.4.2 → gam7-7.4.4}/src/license.rtf +0 -0
  98. {gam7-7.4.2 → gam7-7.4.4}/src/project-apis.txt +0 -0
  99. {gam7-7.4.2 → gam7-7.4.4}/src/requirements-dev.txt +0 -0
  100. {gam7-7.4.2 → gam7-7.4.4}/src/requirements.txt +0 -0
  101. {gam7-7.4.2 → gam7-7.4.4}/src/setup.cfg +0 -0
  102. {gam7-7.4.2 → gam7-7.4.4}/src/setup.py +0 -0
  103. {gam7-7.4.2 → gam7-7.4.4}/src/tools/a_atleast_b.py +0 -0
  104. {gam7-7.4.2 → gam7-7.4.4}/src/tools/gen-wix-xml-filelist.py +0 -0
  105. {gam7-7.4.2 → gam7-7.4.4}/src/tools/mkGamRef.py +0 -0
  106. {gam7-7.4.2 → gam7-7.4.4}/src/tools/openssl.props +0 -0
  107. {gam7-7.4.2 → gam7-7.4.4}/src/version_info.txt.in +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gam7
3
- Version: 7.4.2
3
+ Version: 7.4.4
4
4
  Summary: CLI tool to manage Google Workspace
5
5
  Project-URL: Homepage, https://github.com/GAM-team/GAM
6
6
  Project-URL: Issues, https://github.com/GAM-team/GAM/issues
@@ -3997,13 +3997,14 @@ gam print cigroups [todrive <ToDriveAttribute>*]
3997
3997
 
3998
3998
  <CIGroupMembersFieldName> ::=
3999
3999
  createtime
4000
+ email|useremail|
4000
4001
  expiretime|
4001
4002
  memberkey|
4002
4003
  name|
4003
4004
  role|
4004
4005
  type|
4005
- updatetime|
4006
- useremail
4006
+ updatetime
4007
+
4007
4008
  <CIGroupMembersFieldNameList> ::= "<CIGroupMembersFieldName>(,<CIGroupMembersFieldName>)*"
4008
4009
 
4009
4010
  gam <UserTypeEntity> info cimember <GroupEntity>
@@ -4017,16 +4018,19 @@ gam print cigroup-members [todrive <ToDriveAttribute>*]
4017
4018
  [types <CIGroupMemberTypeList>]
4018
4019
  [memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
4019
4020
  <CIGroupMembersFieldName>* [fields <CIGroupMembersFieldNameList>]
4020
- [(recursive [noduplicates])includederivedmembership] [nogroupeemail]
4021
+ [minimal|basic|full]
4022
+ [(recursive [noduplicates]) | includederivedmembership] [nogroupemail]
4021
4023
  [formatjson [quotechar <Character>]]
4022
4024
  gam show cigroup-members
4023
4025
  [(cimember|ciowner <UserItem>)|(cigroup <GroupItem>)|(select <GroupEntity>)]
4024
4026
  [showownedby <UserItem>]
4025
4027
  [emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
4026
4028
  [descriptionmatchpattern [not] <RegularExpression>]
4027
- [roles <GroupRoleList>] [members] [managers] [owners] [depth <Number>]
4029
+ [roles <GroupRoleList>] [members] [managers] [owners]
4028
4030
  [types <CIGroupMemberTypeList>]
4029
4031
  [memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
4032
+ [minimal|basic|full]
4033
+ [(depth <Number>) | includederivedmembership]
4030
4034
 
4031
4035
  # Cloud Identity Devices
4032
4036
 
@@ -1,3 +1,22 @@
1
+ 7.04.04
2
+
3
+ Updated `gam print group-members|cigroup-members` to include the `email` column
4
+ when `fields <MembersFieldNameList>` did not include `email`.
5
+
6
+ 7.04.03
7
+
8
+ Added option `minimal|basic|full` to `gam print cigroup-members`:
9
+ * `minimal` - Fields displayed: group, id, role, email
10
+ * `basic` - Fields displayed: group, type, id, role, email
11
+ * `full` - Fields displayed: group, type, id, role, email, createTime, updateTime; this is the default
12
+
13
+ Added option `minimal|basic|full` to `gam show cigroup-members`:
14
+ * `minimal` - Fields displayed: role, email
15
+ * `basic` - Fields displayed: type, role, email
16
+ * `full` - Fields displayed: type, role, email, createTime, updateTime; this is the default
17
+
18
+ Upgraded `gam print cigroup-members ... recursive` to display sub-group email addresses rather than IDs.
19
+
1
20
  7.04.02
2
21
 
3
22
  Improved output formatting for the following commands:
@@ -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.04.02'
28
+ __version__ = '7.04.04'
29
29
  __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
30
30
 
31
31
  #pylint: disable=wrong-import-position
@@ -5981,6 +5981,8 @@ def getCIGroupTransitiveMemberRoleFixType(groupName, tmember):
5981
5981
  member['type'] = Ent.TYPE_USER if not tid.endswith('.iam.gserviceaccount.com') else Ent.TYPE_SERVICE_ACCOUNT
5982
5982
  elif ttype == 'groups':
5983
5983
  member['type'] = Ent.TYPE_GROUP
5984
+ elif tid.startswith('cbcm-browser.'):
5985
+ member['type'] = Ent.TYPE_CBCM_BROWSER
5984
5986
  else:
5985
5987
  member['type'] = Ent.TYPE_OTHER
5986
5988
  else:
@@ -7322,12 +7324,6 @@ def _getRawFields(requiredField=None):
7322
7324
  return rawFields
7323
7325
  return f'{requiredField},{rawFields}'
7324
7326
 
7325
- def _addInitialField(fieldsList, initialField):
7326
- if isinstance(initialField, list):
7327
- fieldsList.extend(initialField)
7328
- else:
7329
- fieldsList.append(initialField)
7330
-
7331
7327
  def CheckInputRowFilterHeaders(titlesList, rowFilter, rowDropFilter):
7332
7328
  status = True
7333
7329
  for filterVal in rowFilter:
@@ -7742,6 +7738,12 @@ def RowFilterMatch(row, titlesList, rowFilter, rowFilterModeAll, rowDropFilter,
7742
7738
  # }
7743
7739
  # fieldsList is the list of API fields
7744
7740
  def getFieldsList(myarg, fieldsChoiceMap, fieldsList, initialField=None, fieldsArg='fields', onlyFieldsArg=False):
7741
+ def addInitialField():
7742
+ if isinstance(initialField, list):
7743
+ fieldsList.extend(initialField)
7744
+ else:
7745
+ fieldsList.append(initialField)
7746
+
7745
7747
  def addMappedFields(mappedFields):
7746
7748
  if isinstance(mappedFields, list):
7747
7749
  fieldsList.extend(mappedFields)
@@ -7750,11 +7752,11 @@ def getFieldsList(myarg, fieldsChoiceMap, fieldsList, initialField=None, fieldsA
7750
7752
 
7751
7753
  if not onlyFieldsArg and myarg in fieldsChoiceMap:
7752
7754
  if not fieldsList and initialField is not None:
7753
- _addInitialField(fieldsList, initialField)
7755
+ addInitialField()
7754
7756
  addMappedFields(fieldsChoiceMap[myarg])
7755
7757
  elif myarg == fieldsArg:
7756
7758
  if not fieldsList and initialField is not None:
7757
- _addInitialField(fieldsList, initialField)
7759
+ addInitialField()
7758
7760
  for field in _getFieldsList():
7759
7761
  if field in fieldsChoiceMap:
7760
7762
  addMappedFields(fieldsChoiceMap[field])
@@ -7931,14 +7933,21 @@ class CSVPrintFile():
7931
7933
  fieldsList.append(fields)
7932
7934
  self.AddTitles(fields.replace('.', GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]))
7933
7935
 
7936
+ def addInitialField(self, initialField, fieldsChoiceMap, fieldsList):
7937
+ if isinstance(initialField, list):
7938
+ for field in initialField:
7939
+ self.AddField(field, fieldsChoiceMap, fieldsList)
7940
+ else:
7941
+ self.AddField(initialField, fieldsChoiceMap, fieldsList)
7942
+
7934
7943
  def GetFieldsListTitles(self, fieldName, fieldsChoiceMap, fieldsList, initialField=None):
7935
7944
  if fieldName in fieldsChoiceMap:
7936
7945
  if not fieldsList and initialField is not None:
7937
- _addInitialField(fieldsList, initialField)
7946
+ self.addInitialField(initialField, fieldsChoiceMap, fieldsList)
7938
7947
  self.AddField(fieldName, fieldsChoiceMap, fieldsList)
7939
7948
  elif fieldName == 'fields':
7940
7949
  if not fieldsList and initialField is not None:
7941
- _addInitialField(fieldsList, initialField)
7950
+ self.addInitialField(initialField, fieldsChoiceMap, fieldsList)
7942
7951
  for field in _getFieldsList():
7943
7952
  if field in fieldsChoiceMap:
7944
7953
  self.AddField(field, fieldsChoiceMap, fieldsList)
@@ -33959,6 +33968,8 @@ def infoGroupMembers(entityList, ciGroupsAPI=False):
33959
33968
  printKeyValueList(['type', result['type']])
33960
33969
  for field in ['createTime', 'updateTime']:
33961
33970
  printKeyValueList([field, formatLocalTime(result[field])])
33971
+ if 'deliverySetting' in result:
33972
+ printKeyValueList(['deliverySetting', result['deliverySetting']])
33962
33973
  Ind.Decrement()
33963
33974
  except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden) as e:
33964
33975
  entityActionFailedWarning([entityType, groupKey], str(e), j, jcount)
@@ -34202,7 +34213,7 @@ def doPrintGroupMembers():
34202
34213
  pass
34203
34214
  elif getMemberMatchOptions(myarg, memberOptions):
34204
34215
  pass
34205
- elif csvPF.GetFieldsListTitles(myarg, GROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList):
34216
+ elif csvPF.GetFieldsListTitles(myarg, GROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList, initialField='email'):
34206
34217
  pass
34207
34218
  elif myarg == 'membernames':
34208
34219
  memberOptions[MEMBEROPTION_MEMBERNAMES] = True
@@ -36121,8 +36132,9 @@ def getCIGroupTransitiveMembers(ci, groupName, membersList, i, count):
36121
36132
  return True
36122
36133
 
36123
36134
  def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, count,
36124
- memberOptions, memberDisplayOptions, level, typesSet):
36125
- printGettingAllEntityItemsForWhom(memberRoles if memberRoles else Ent.ROLE_MANAGER_MEMBER_OWNER, groupName, i, count)
36135
+ memberOptions, memberDisplayOptions, level, typesSet, groupEmail, kwargs):
36136
+ nameToPrint = groupEmail if groupEmail else groupName
36137
+ printGettingAllEntityItemsForWhom(memberRoles if memberRoles else Ent.ROLE_MANAGER_MEMBER_OWNER, nameToPrint, i, count)
36126
36138
  validRoles = _getCIRoleVerification(memberRoles)
36127
36139
  if memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP]:
36128
36140
  groupMembers = []
@@ -36137,12 +36149,11 @@ def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, co
36137
36149
  groupMembers = callGAPIpages(ci.groups().memberships(), 'list', 'memberships',
36138
36150
  pageMessage=getPageMessageForWhom(),
36139
36151
  throwReasons=GAPI.CIGROUP_LIST_THROW_REASONS, retryReasons=GAPI.CIGROUP_RETRY_REASONS,
36140
- parent=groupName, view='FULL',
36141
- fields='nextPageToken,memberships(*)', pageSize=GC.Values[GC.MEMBER_MAX_RESULTS])
36152
+ parent=groupName, **kwargs)
36142
36153
  except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis,
36143
36154
  GAPI.forbidden, GAPI.badRequest, GAPI.invalid, GAPI.invalidArgument, GAPI.systemError,
36144
36155
  GAPI.permissionDenied, GAPI.serviceNotAvailable):
36145
- entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, groupName, i, count)
36156
+ entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, nameToPrint, i, count)
36146
36157
  return
36147
36158
  checkCategory = memberDisplayOptions['showCategory']
36148
36159
  if not memberOptions[MEMBEROPTION_RECURSIVE]:
@@ -36176,7 +36187,7 @@ def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, co
36176
36187
  memberName not in membersSet):
36177
36188
  membersSet.add(memberName)
36178
36189
  member['level'] = level
36179
- member['subgroup'] = groupName
36190
+ member['subgroup'] = nameToPrint
36180
36191
  membersList.append(member)
36181
36192
  else:
36182
36193
  if memberName not in membersSet:
@@ -36185,37 +36196,41 @@ def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, co
36185
36196
  checkCIMemberMatch(member, memberOptions) and
36186
36197
  (not checkCategory or _checkCIMemberCategory(member, memberDisplayOptions))):
36187
36198
  member['level'] = level
36188
- member['subgroup'] = groupName
36199
+ member['subgroup'] = nameToPrint
36189
36200
  membersList.append(member)
36190
36201
  _, gname = member['name'].rsplit('/', 1)
36191
- groupMemberList.append(f'groups/{gname}')
36202
+ groupMemberList.append((f'groups/{gname}', memberName))
36192
36203
  for member in groupMemberList:
36193
- getCIGroupMembers(ci, member, memberRoles, membersList, membersSet, i, count,
36194
- memberOptions, memberDisplayOptions, level+1, typesSet)
36204
+ getCIGroupMembers(ci, member[0], memberRoles, membersList, membersSet, i, count,
36205
+ memberOptions, memberDisplayOptions, level+1, typesSet, member[1], kwargs)
36195
36206
  else:
36196
36207
  for member in groupMembers:
36197
36208
  getCIGroupMemberRoleFixType(member)
36209
+ memberName = member.get('preferredMemberKey', {}).get('id', '')
36198
36210
  if member['type'] != Ent.TYPE_GROUP:
36199
36211
  if (member['type'] in typesSet and
36200
36212
  checkCIMemberMatch(member, memberOptions) and
36201
36213
  _checkMemberRole(member, validRoles) and
36202
36214
  (not checkCategory or _checkCIMemberCategory(member, memberDisplayOptions))):
36203
36215
  member['level'] = level
36204
- member['subgroup'] = groupName
36216
+ member['subgroup'] = nameToPrint
36205
36217
  membersList.append(member)
36206
36218
  else:
36207
36219
  if (member['type'] in typesSet and
36208
36220
  checkCIMemberMatch(member, memberOptions) and
36209
36221
  (not checkCategory or _checkCIMemberCategory(member, memberDisplayOptions))):
36210
36222
  member['level'] = level
36211
- member['subgroup'] = groupName
36223
+ member['subgroup'] = nameToPrint
36212
36224
  membersList.append(member)
36213
36225
  _, gname = member['name'].rsplit('/', 1)
36214
36226
  getCIGroupMembers(ci, f'groups/{gname}', memberRoles, membersList, membersSet, i, count,
36215
- memberOptions, memberDisplayOptions, level+1, typesSet)
36227
+ memberOptions, memberDisplayOptions, level+1, typesSet, memberName, kwargs)
36216
36228
 
36217
36229
  CIGROUPMEMBERS_FIELDS_CHOICE_MAP = {
36218
36230
  'createtime': 'createTime',
36231
+ 'delivery': 'deliverySetting',
36232
+ 'deliverysettings': 'deliverySetting',
36233
+ 'email': 'preferredMemberKey',
36219
36234
  'expiretime': 'expireTime',
36220
36235
  'id': 'name',
36221
36236
  'memberkey': 'preferredMemberKey',
@@ -36236,6 +36251,16 @@ CIGROUPMEMBERS_SORT_FIELDS = [
36236
36251
  ]
36237
36252
  CIGROUPMEMBERS_TIME_OBJECTS = {'createTime', 'updateTime', 'expireTime'}
36238
36253
 
36254
+ def _getCIListGroupMembersArgs(listView):
36255
+ if listView == 'full':
36256
+ return {'view': 'FULL', 'pageSize': GC.Values[GC.MEMBER_MAX_RESULTS_CI_FULL],
36257
+ 'fields': 'nextPageToken,memberships(*)'}
36258
+ if listView == 'basic':
36259
+ return {'view': 'FULL', 'pageSize': GC.Values[GC.MEMBER_MAX_RESULTS_CI_FULL],
36260
+ 'fields': 'nextPageToken,memberships(name,preferredMemberKey,roles,type)'}
36261
+ return {'view': 'BASIC', 'pageSize': GC.Values[GC.MEMBER_MAX_RESULTS_CI_BASIC],
36262
+ 'fields': 'nextPageToken,memberships(*)'}
36263
+
36239
36264
  # gam print cigroup-members [todrive <ToDriveAttribute>*]
36240
36265
  # [(cimember|ciowner <UserItem>)|(cigroup <GroupItem>)|(select <GroupEntity>)]
36241
36266
  # [showownedby <UserItem>]
@@ -36245,6 +36270,7 @@ CIGROUPMEMBERS_TIME_OBJECTS = {'createTime', 'updateTime', 'expireTime'}
36245
36270
  # [types <CIGroupMemberTypeList>]
36246
36271
  # [memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
36247
36272
  # <CIGroupMembersFieldName>* [fields <CIGroupMembersFieldNameList>]
36273
+ # [minimal|basic|full]
36248
36274
  # [(recursive [noduplicates])|includederivedmembership] [nogroupeemail]
36249
36275
  # [formatjson [quotechar <Character>]]
36250
36276
  def doPrintCIGroupMembers():
@@ -36262,6 +36288,7 @@ def doPrintCIGroupMembers():
36262
36288
  rolesSet = set()
36263
36289
  typesSet = set()
36264
36290
  matchPatterns = {}
36291
+ listView = 'full'
36265
36292
  while Cmd.ArgumentsRemaining():
36266
36293
  myarg = getArgument()
36267
36294
  if myarg == 'todrive':
@@ -36290,7 +36317,7 @@ def doPrintCIGroupMembers():
36290
36317
  pass
36291
36318
  elif getMemberMatchOptions(myarg, memberOptions):
36292
36319
  pass
36293
- elif getFieldsList(myarg, CIGROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList):
36320
+ elif getFieldsList(myarg, CIGROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList, initialField='preferredMemberKey'):
36294
36321
  pass
36295
36322
  elif myarg == 'noduplicates':
36296
36323
  memberOptions[MEMBEROPTION_NODUPLICATES] = True
@@ -36302,8 +36329,12 @@ def doPrintCIGroupMembers():
36302
36329
  memberOptions[MEMBEROPTION_RECURSIVE] = False
36303
36330
  elif myarg == 'nogroupemail':
36304
36331
  groupColumn = False
36332
+ elif myarg in {'minimal', 'basic', 'full'}:
36333
+ listView = myarg
36305
36334
  else:
36306
36335
  FJQC.GetFormatJSONQuoteChar(myarg, False)
36336
+ if listView == 'minimal' and memberOptions[MEMBEROPTION_RECURSIVE]:
36337
+ usageErrorExit(Msg.ARE_MUTUALLY_EXCLUSIVE.format('minimal', 'recursive'))
36307
36338
  if not typesSet:
36308
36339
  typesSet = {Ent.TYPE_USER} if memberOptions[MEMBEROPTION_RECURSIVE] else ALL_CIGROUP_MEMBER_TYPES
36309
36340
  fields = ','.join(set(groupFieldsLists['ci']))
@@ -36330,6 +36361,7 @@ def doPrintCIGroupMembers():
36330
36361
  if showOwnedBy:
36331
36362
  getRolesSet.add(Ent.ROLE_OWNER)
36332
36363
  getRoles = ','.join(sorted(getRolesSet))
36364
+ kwargs = _getCIListGroupMembersArgs(listView)
36333
36365
  level = 0
36334
36366
  i = 0
36335
36367
  count = len(entityList)
@@ -36356,7 +36388,7 @@ def doPrintCIGroupMembers():
36356
36388
  membersList = []
36357
36389
  membersSet = set()
36358
36390
  getCIGroupMembers(ci, groupEntity['name'], getRoles, membersList, membersSet, i, count,
36359
- memberOptions, memberDisplayOptions, level, typesSet)
36391
+ memberOptions, memberDisplayOptions, level, typesSet, groupEmail, kwargs)
36360
36392
  if showOwnedBy and not checkCIGroupShowOwnedBy(showOwnedBy, membersList):
36361
36393
  continue
36362
36394
  for member in membersList:
@@ -36374,6 +36406,8 @@ def doPrintCIGroupMembers():
36374
36406
  row['subgroup'] = member['subgroup']
36375
36407
  if memberDisplayOptions['showCategory']:
36376
36408
  row['category'] = member['category']
36409
+ if listView == 'minimal':
36410
+ dmember.pop('type', None)
36377
36411
  mapCIGroupMemberFieldNames(dmember)
36378
36412
  if not FJQC.formatJSON:
36379
36413
  csvPF.WriteRowTitles(flattenJSON(dmember, flattened=row, timeObjects=CIGROUPMEMBERS_TIME_OBJECTS))
@@ -36403,17 +36437,19 @@ def doPrintCIGroupMembers():
36403
36437
  # [showownedby <UserItem>]
36404
36438
  # [emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
36405
36439
  # [descriptionmatchpattern [not] <RegularExpression>]
36406
- # [roles <GroupRoleList>] [members] [managers] [owners] [depth <Number>]
36440
+ # [roles <GroupRoleList>] [members] [managers] [owners]
36407
36441
  # [internal] [internaldomains <DomainList>] [external]
36408
36442
  # [types <CIGroupMemberTypeList>]
36409
36443
  # [memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
36410
- # [includederivedmembership]
36444
+ # [minimal|basic|full]
36445
+ # [(depth <Number>) | includederivedmembership]
36411
36446
  def doShowCIGroupMembers():
36412
36447
  def _roleOrder(key):
36413
36448
  return {Ent.ROLE_OWNER: 0, Ent.ROLE_MANAGER: 1, Ent.ROLE_MEMBER: 2}.get(key, 3)
36414
36449
 
36415
36450
  def _typeOrder(key):
36416
- return {Ent.TYPE_CUSTOMER: 0, Ent.TYPE_USER: 1, Ent.TYPE_GROUP: 2, Ent.TYPE_EXTERNAL: 3}.get(key, 4)
36451
+ return {Ent.TYPE_CUSTOMER: 0, Ent.TYPE_USER: 1, Ent.TYPE_GROUP: 2,
36452
+ Ent.TYPE_CBCM_BROWSER: 3, Ent.TYPE_OTHER: 4, Ent.TYPE_EXTERNAL: 5}.get(key, 6)
36417
36453
 
36418
36454
  def _showGroup(groupName, groupEmail, depth):
36419
36455
  if includeDerivedMembership:
@@ -36424,8 +36460,7 @@ def doShowCIGroupMembers():
36424
36460
  try:
36425
36461
  membersList = callGAPIpages(ci.groups().memberships(), 'list', 'memberships',
36426
36462
  throwReasons=GAPI.CIGROUP_LIST_THROW_REASONS, retryReasons=GAPI.CIGROUP_RETRY_REASONS,
36427
- parent=groupName, view='FULL',
36428
- fields='nextPageToken,memberships(*)', pageSize=GC.Values[GC.MEMBER_MAX_RESULTS])
36463
+ parent=groupName, **kwargs)
36429
36464
  for member in membersList:
36430
36465
  getCIGroupMemberRoleFixType(member)
36431
36466
  except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis,
@@ -36446,7 +36481,10 @@ def doShowCIGroupMembers():
36446
36481
  if (_checkMemberRole(member, rolesSet) and
36447
36482
  member['type'] in typesSet and
36448
36483
  checkCIMemberMatch(member, memberOptions)):
36449
- memberDetails = f'{member.get("role", Ent.ROLE_MEMBER)}, {member["type"]}, {member["preferredMemberKey"]["id"]}'
36484
+ if listView != 'minimal':
36485
+ memberDetails = f'{member.get("role", Ent.ROLE_MEMBER)}, {member["type"]}, {member["preferredMemberKey"]["id"]}'
36486
+ else:
36487
+ memberDetails = f'{member.get("role", Ent.ROLE_MEMBER)}, {member["preferredMemberKey"]["id"]}'
36450
36488
  if checkCategory:
36451
36489
  memberDetails += f', {member["category"]}'
36452
36490
  for field in ['createTime', 'updateTime', 'expireTime']:
@@ -36471,6 +36509,7 @@ def doShowCIGroupMembers():
36471
36509
  matchPatterns = {}
36472
36510
  maxdepth = -1
36473
36511
  includeDerivedMembership = False
36512
+ listView = 'full'
36474
36513
  while Cmd.ArgumentsRemaining():
36475
36514
  myarg = getArgument()
36476
36515
  if myarg == 'showownedby':
@@ -36501,6 +36540,8 @@ def doShowCIGroupMembers():
36501
36540
  maxdepth = getInteger(minVal=-1)
36502
36541
  elif myarg == 'includederivedmembership':
36503
36542
  includeDerivedMembership = True
36543
+ elif myarg in {'minimal', 'basic', 'full'}:
36544
+ listView = myarg
36504
36545
  else:
36505
36546
  unknownArgumentExit()
36506
36547
  if not rolesSet:
@@ -36510,6 +36551,7 @@ def doShowCIGroupMembers():
36510
36551
  checkCategory = memberDisplayOptions['showCategory']
36511
36552
  fields = ','.join(set(groupFieldsLists['ci']))
36512
36553
  entityList = getCIGroupMembersEntityList(ci, entityList, query, subTitle, matchPatterns, groupFieldsLists['ci'], None)
36554
+ kwargs = _getCIListGroupMembersArgs(listView)
36513
36555
  i = 0
36514
36556
  count = len(entityList)
36515
36557
  for group in entityList:
@@ -179,6 +179,10 @@ LICENSE_MAX_RESULTS = 'license_max_results'
179
179
  LICENSE_SKUS = 'license_skus'
180
180
  # When retrieving lists of Google Group members from API, how many should be retrieved in each chunk
181
181
  MEMBER_MAX_RESULTS = 'member_max_results'
182
+ # CI API Group members max page size when view=BASIC
183
+ MEMBER_MAX_RESULTS_CI_BASIC = 'member_max_results_ci_basic'
184
+ # CI API Group members max page size when view=FULL
185
+ MEMBER_MAX_RESULTS_CI_FULL = 'member_max_results_ci_full'
182
186
  # When deleting or modifying Gmail messages, how many should be processed in each batch
183
187
  MESSAGE_BATCH_SIZE = 'message_batch_size'
184
188
  # When retrieving lists of Gmail messages from API, how many should be retrieved in each chunk
@@ -385,6 +389,8 @@ Defaults = {
385
389
  LICENSE_MAX_RESULTS: '100',
386
390
  LICENSE_SKUS: '',
387
391
  MEMBER_MAX_RESULTS: '200',
392
+ MEMBER_MAX_RESULTS_CI_BASIC: '1000',
393
+ MEMBER_MAX_RESULTS_CI_FULL: '500',
388
394
  MESSAGE_BATCH_SIZE: '50',
389
395
  MESSAGE_MAX_RESULTS: '500',
390
396
  MOBILE_MAX_RESULTS: '100',
@@ -550,6 +556,8 @@ VAR_INFO = {
550
556
  LICENSE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 1000)},
551
557
  LICENSE_SKUS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
552
558
  MEMBER_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 200)},
559
+ MEMBER_MAX_RESULTS_CI_BASIC: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
560
+ MEMBER_MAX_RESULTS_CI_FULL: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 500)},
553
561
  MESSAGE_BATCH_SIZE: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
554
562
  MESSAGE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 10000)},
555
563
  MOBILE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 100)},
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes