gam7 7.8.1__py3-none-any.whl → 7.9.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 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.08.01'
28
+ __version__ = '7.09.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
@@ -4785,8 +4785,9 @@ def defaultSvcAcctScopes():
4785
4785
  scopesList = API.getSvcAcctScopesList(GC.Values[GC.USER_SERVICE_ACCOUNT_ACCESS_ONLY], False)
4786
4786
  saScopes = {}
4787
4787
  for scope in scopesList:
4788
- saScopes.setdefault(scope['api'], [])
4789
- saScopes[scope['api']].append(scope['scope'])
4788
+ if not scope.get('offByDefault'):
4789
+ saScopes.setdefault(scope['api'], [])
4790
+ saScopes[scope['api']].append(scope['scope'])
4790
4791
  saScopes[API.DRIVEACTIVITY].append(API.DRIVE_SCOPE)
4791
4792
  saScopes[API.DRIVE2] = saScopes[API.DRIVE3]
4792
4793
  saScopes[API.DRIVETD] = saScopes[API.DRIVE3]
@@ -12232,7 +12233,7 @@ def checkServiceAccount(users):
12232
12233
 
12233
12234
  def authorizeScopes(message):
12234
12235
  long_url = ('https://admin.google.com/ac/owl/domainwidedelegation'
12235
- f'?clientScopeToAdd={",".join(checkScopes)}'
12236
+ f'?clientScopeToAdd={",".join(sorted(checkScopes))}'
12236
12237
  f'&clientIdToAdd={service_account}&overwriteClientId=true')
12237
12238
  if GC.Values[GC.DOMAIN]:
12238
12239
  long_url += f'&dn={GC.Values[GC.DOMAIN]}'
@@ -12244,10 +12245,12 @@ def checkServiceAccount(users):
12244
12245
  allScopes = API.getSvcAcctScopes(GC.Values[GC.USER_SERVICE_ACCOUNT_ACCESS_ONLY], Act.Get() == Act.UPDATE)
12245
12246
  checkScopesSet = set()
12246
12247
  saScopes = {}
12248
+ checkDeprecatedScopes = True
12247
12249
  useColor = False
12248
12250
  while Cmd.ArgumentsRemaining():
12249
12251
  myarg = getArgument()
12250
12252
  if myarg in {'scope', 'scopes'}:
12253
+ checkDeprecatedScopes = False
12251
12254
  for scope in getString(Cmd.OB_API_SCOPE_URL_LIST).lower().replace(',', ' ').split():
12252
12255
  api = API.getSvcAcctScopeAPI(scope)
12253
12256
  if api is not None:
@@ -12264,10 +12267,12 @@ def checkServiceAccount(users):
12264
12267
  testPass = createGreenText('PASS')
12265
12268
  testFail = createRedText('FAIL')
12266
12269
  testWarn = createYellowText('WARN')
12270
+ testDeprecated = createRedText('DEPRECATED')
12267
12271
  else:
12268
12272
  testPass = 'PASS'
12269
12273
  testFail = 'FAIL'
12270
12274
  testWarn = 'WARN'
12275
+ testDeprecated = 'DEPRECATED'
12271
12276
  if Act.Get() == Act.CHECK:
12272
12277
  if not checkScopesSet:
12273
12278
  for scope in iter(GM.Globals[GM.SVCACCT_SCOPES].values()):
@@ -12275,7 +12280,7 @@ def checkServiceAccount(users):
12275
12280
  else:
12276
12281
  if not checkScopesSet:
12277
12282
  scopesList = API.getSvcAcctScopesList(GC.Values[GC.USER_SERVICE_ACCOUNT_ACCESS_ONLY], True)
12278
- selectedScopes = getScopesFromUser(scopesList, False, GM.Globals[GM.SVCACCT_SCOPES])
12283
+ selectedScopes = getScopesFromUser(scopesList, False, GM.Globals[GM.SVCACCT_SCOPES] if GM.Globals[GM.SVCACCT_SCOPES_DEFINED] else None)
12279
12284
  if selectedScopes is None:
12280
12285
  return False
12281
12286
  i = 0
@@ -12337,8 +12342,8 @@ def checkServiceAccount(users):
12337
12342
  if saTokenStatus == testFail:
12338
12343
  invalidOauth2serviceJsonExit(f'Authentication{auth_error}')
12339
12344
  _getSvcAcctData() # needed to read in GM.OAUTH2SERVICE_JSON_DATA
12340
- if GM.Globals[GM.SVCACCT_SCOPES_DEFINED] and API.IAM not in GM.Globals[GM.SVCACCT_SCOPES]:
12341
- GM.Globals[GM.SVCACCT_SCOPES][API.IAM] = [API.CLOUD_PLATFORM_SCOPE]
12345
+ if API.IAM not in GM.Globals[GM.SVCACCT_SCOPES]:
12346
+ GM.Globals[GM.SVCACCT_SCOPES][API.IAM] = [API.IAM_SCOPE]
12342
12347
  key_type = GM.Globals[GM.OAUTH2SERVICE_JSON_DATA].get('key_type', 'default')
12343
12348
  if key_type == 'default':
12344
12349
  printMessage(Msg.SERVICE_ACCOUNT_CHECK_PRIVATE_KEY_AGE)
@@ -12399,6 +12404,38 @@ def checkServiceAccount(users):
12399
12404
  allScopesPass = False
12400
12405
  printPassFail(scope, f'{scopeStatus}{currentCount(j, jcount)}')
12401
12406
  Ind.Decrement()
12407
+ if checkDeprecatedScopes:
12408
+ deprecatedScopes = sorted(API.DEPRECATED_SCOPES)
12409
+ jcount = len(deprecatedScopes)
12410
+ printKeyValueListWithCount([Msg.DEPRECATED_SCOPES, '',
12411
+ Ent.Singular(Ent.USER), user,
12412
+ Ent.Choose(Ent.SCOPE, jcount), jcount],
12413
+ i, count)
12414
+ Ind.Increment()
12415
+ j = 0
12416
+ for scope in deprecatedScopes:
12417
+ j += 1
12418
+ # try with and without email scope
12419
+ for scopes in [[scope, API.USERINFO_EMAIL_SCOPE], [scope]]:
12420
+ try:
12421
+ credentials = getSvcAcctCredentials(scopes, user)
12422
+ credentials.refresh(request)
12423
+ break
12424
+ except (httplib2.HttpLib2Error, google.auth.exceptions.TransportError, RuntimeError) as e:
12425
+ handleServerError(e)
12426
+ except google.auth.exceptions.RefreshError:
12427
+ continue
12428
+ if credentials.token:
12429
+ token_info = callGAPI(oa2, 'tokeninfo', access_token=credentials.token)
12430
+ if scope in token_info.get('scope', '').split(' ') and user == token_info.get('email', user).lower():
12431
+ scopeStatus = testDeprecated
12432
+ allScopesPass = False
12433
+ else:
12434
+ scopeStatus = testPass
12435
+ else:
12436
+ scopeStatus = testPass
12437
+ printPassFail(scope, f'{scopeStatus}{currentCount(j, jcount)}')
12438
+ Ind.Decrement()
12402
12439
  service_account = GM.Globals[GM.OAUTH2SERVICE_JSON_DATA]['client_id']
12403
12440
  if allScopesPass:
12404
12441
  if Act.Get() == Act.CHECK:
@@ -58716,7 +58753,7 @@ def initCopyMoveOptions(copyCmd):
58716
58753
  'showPermissionMessages': False,
58717
58754
  'sendEmailIfRequired': False,
58718
58755
  'useDomainAdminAccess': False,
58719
- 'enforceExpansiveAccess': False,
58756
+ 'enforceExpansiveAccess': GC.Values[GC.ENFORCE_EXPANSIVE_ACCESS],
58720
58757
  'copiedShortcutsPointToCopiedFiles': True,
58721
58758
  'createShortcutsForNonmovableFiles': False,
58722
58759
  'duplicateFiles': DUPLICATE_FILE_OVERWRITE_OLDER,
@@ -62096,7 +62133,8 @@ def transferDrive(users):
62096
62133
  targetUserFolderPattern = '#user# old files'
62097
62134
  targetUserOrphansFolderPattern = '#user# orphaned files'
62098
62135
  targetIds = [None, None]
62099
- createShortcutsForNonmovableFiles = enforceExpansiveAccess = False
62136
+ createShortcutsForNonmovableFiles = False
62137
+ enforceExpansiveAccess = GC.Values[GC.ENFORCE_EXPANSIVE_ACCESS]
62100
62138
  mergeWithTarget = False
62101
62139
  thirdPartyOwners = {}
62102
62140
  skipFileIdEntity = initDriveFileEntity()
@@ -62402,7 +62440,8 @@ def transferOwnership(users):
62402
62440
  body = {}
62403
62441
  newOwner = getEmailAddress()
62404
62442
  OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
62405
- changeParents = enforceExpansiveAccess = filepath = includeTrashed = noRecursion = False
62443
+ changeParents = filepath = includeTrashed = noRecursion = False
62444
+ enforceExpansiveAccess = GC.Values[GC.ENFORCE_EXPANSIVE_ACCESS]
62406
62445
  pathDelimiter = '/'
62407
62446
  csvPF = fileTree = None
62408
62447
  addParents = ''
@@ -62728,7 +62767,8 @@ def claimOwnership(users):
62728
62767
  onlyOwners = set()
62729
62768
  skipOwners = set()
62730
62769
  subdomains = []
62731
- enforceExpansiveAccess = filepath = includeTrashed = False
62770
+ filepath = includeTrashed = False
62771
+ enforceExpansiveAccess = GC.Values[GC.ENFORCE_EXPANSIVE_ACCESS]
62732
62772
  pathDelimiter = '/'
62733
62773
  addParents = ''
62734
62774
  parentBody = {}
@@ -63503,7 +63543,7 @@ def doCreateDriveFileACL():
63503
63543
  def updateDriveFileACLs(users, useDomainAdminAccess=False):
63504
63544
  fileIdEntity = getDriveFileEntity()
63505
63545
  isEmail, permissionId = getPermissionId()
63506
- enforceExpansiveAccess = None
63546
+ enforceExpansiveAccess = GC.Values[GC.ENFORCE_EXPANSIVE_ACCESS]
63507
63547
  removeExpiration = showTitles = updateSheetProtectedRanges = False
63508
63548
  showDetails = True
63509
63549
  csvPF = None
@@ -63541,9 +63581,6 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
63541
63581
  _checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
63542
63582
  if 'role' not in body:
63543
63583
  missingArgumentExit(f'role {formatChoiceList(DRIVEFILE_ACL_ROLES_MAP)}')
63544
- updateKwargs = {'useDomainAdminAccess': useDomainAdminAccess}
63545
- if enforceExpansiveAccess is not None:
63546
- updateKwargs['enforceExpansiveAccess'] = enforceExpansiveAccess
63547
63584
  printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects()
63548
63585
  if csvPF and showTitles:
63549
63586
  csvPF.AddTitles(fileNameTitle)
@@ -63581,7 +63618,7 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
63581
63618
  permission = callGAPI(drive.permissions(), 'update',
63582
63619
  bailOnInternalError=True,
63583
63620
  throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_UPDATE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
63584
- **updateKwargs,
63621
+ useDomainAdminAccess=useDomainAdminAccess, enforceExpansiveAccess=enforceExpansiveAccess,
63585
63622
  fileId=fileId, permissionId=permissionId, removeExpiration=removeExpiration,
63586
63623
  transferOwnership=body.get('role', '') == 'owner', body=body, fields='*', supportsAllDrives=True)
63587
63624
  if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
@@ -63832,7 +63869,7 @@ def doCreatePermissions():
63832
63869
  def deleteDriveFileACLs(users, useDomainAdminAccess=False):
63833
63870
  fileIdEntity = getDriveFileEntity()
63834
63871
  isEmail, permissionId = getPermissionId()
63835
- enforceExpansiveAccess = None
63872
+ enforceExpansiveAccess = GC.Values[GC.ENFORCE_EXPANSIVE_ACCESS]
63836
63873
  showTitles = updateSheetProtectedRanges = False
63837
63874
  while Cmd.ArgumentsRemaining():
63838
63875
  myarg = getArgument()
@@ -63847,9 +63884,6 @@ def deleteDriveFileACLs(users, useDomainAdminAccess=False):
63847
63884
  else:
63848
63885
  unknownArgumentExit()
63849
63886
  _checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
63850
- deleteKwargs = {'useDomainAdminAccess': useDomainAdminAccess}
63851
- if enforceExpansiveAccess is not None:
63852
- deleteKwargs['enforceExpansiveAccess'] = enforceExpansiveAccess
63853
63887
  i, count, users = getEntityArgument(users)
63854
63888
  for user in users:
63855
63889
  i += 1
@@ -63882,7 +63916,7 @@ def deleteDriveFileACLs(users, useDomainAdminAccess=False):
63882
63916
  break
63883
63917
  callGAPI(drive.permissions(), 'delete',
63884
63918
  throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
63885
- **deleteKwargs,
63919
+ useDomainAdminAccess=useDomainAdminAccess, enforceExpansiveAccess=enforceExpansiveAccess,
63886
63920
  fileId=fileId, permissionId=permissionId, supportsAllDrives=True)
63887
63921
  entityActionPerformed([Ent.USER, user, entityType, fileName, Ent.PERMISSION_ID, permissionId], j, jcount)
63888
63922
  if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
@@ -63961,7 +63995,7 @@ def deletePermissions(users, useDomainAdminAccess=False):
63961
63995
  jsonData = getJSON([])
63962
63996
  PM = PermissionMatch()
63963
63997
  PM.SetDefaultMatch(False, {'role': 'owner'})
63964
- enforceExpansiveAccess = False
63998
+ enforceExpansiveAccess = GC.Values[GC.ENFORCE_EXPANSIVE_ACCESS]
63965
63999
  while Cmd.ArgumentsRemaining():
63966
64000
  myarg = getArgument()
63967
64001
  if myarg in ADMIN_ACCESS_OPTIONS:
@@ -66071,8 +66105,8 @@ def printSharedDriveOrganizers(users, useDomainAdminAccess=False):
66071
66105
  showNoOrganizerDrives = SHOW_NO_PERMISSIONS_DRIVES_CHOICE_MAP['false']
66072
66106
  fieldsList = ['role', 'type', 'emailAddress']
66073
66107
  cd = entityList = orgUnitId = query = matchPattern = None
66074
- domainList = []
66075
- oneOrganizer = False
66108
+ domainList = [GC.Values[GC.DOMAIN]]
66109
+ oneOrganizer = True
66076
66110
  while Cmd.ArgumentsRemaining():
66077
66111
  myarg = getArgument()
66078
66112
  if csvPF and myarg == 'todrive':
@@ -66104,7 +66138,7 @@ def printSharedDriveOrganizers(users, useDomainAdminAccess=False):
66104
66138
  elif myarg in ADMIN_ACCESS_OPTIONS:
66105
66139
  useDomainAdminAccess = True
66106
66140
  elif myarg == 'domainlist':
66107
- domainList = set(getString(Cmd.OB_DOMAIN_NAME_LIST).replace(',', ' ').lower().split())
66141
+ domainList = set(getString(Cmd.OB_DOMAIN_NAME_LIST, minLen=0).replace(',', ' ').lower().split())
66108
66142
  elif myarg == 'includetypes':
66109
66143
  for itype in getString(Cmd.OB_ORGANIZER_TYPE_LIST).lower().replace(',', ' ').split():
66110
66144
  if itype in PRINT_ORGANIZER_TYPES:
@@ -66133,7 +66167,7 @@ def printSharedDriveOrganizers(users, useDomainAdminAccess=False):
66133
66167
  usageErrorExit(Msg.ONLY_ADMINISTRATORS_CAN_SPECIFY_SHARED_DRIVE_ORGUNIT)
66134
66168
  csvPF.AddTitles(['orgUnit', 'orgUnitId'])
66135
66169
  if not includeTypes:
66136
- includeTypes = PRINT_ORGANIZER_TYPES
66170
+ includeTypes = set(['user'])
66137
66171
  fields = getItemFieldsFromFieldsList('permissions', fieldsList, True)
66138
66172
  i, count, users = getEntityArgument(users)
66139
66173
  for user in users:
@@ -66200,7 +66234,7 @@ def printSharedDriveOrganizers(users, useDomainAdminAccess=False):
66200
66234
  useDomainAdminAccess=useDomainAdminAccess,
66201
66235
  fileId=shareddrive['id'], fields=fields, supportsAllDrives=True)
66202
66236
  for permission in permissions:
66203
- if permission['type'] in includeTypes and permission['role'] in roles:
66237
+ if permission['type'] in includeTypes and permission['role'] in roles and permission.get('emailAddress', ''):
66204
66238
  if domainList:
66205
66239
  _, domain = permission['emailAddress'].lower().split('@', 1)
66206
66240
  if domain not in domainList:
gam/gamlib/glapi.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Copyright (C) 2024 Ross Scroggs All Rights Reserved.
3
+ # Copyright (C) 2025 Ross Scroggs All Rights Reserved.
4
4
  #
5
5
  # All Rights Reserved.
6
6
  #
@@ -118,6 +118,7 @@ JWT_APIS = {
118
118
  ACCESSCONTEXTMANAGER: [CLOUD_PLATFORM_SCOPE],
119
119
  CHAT: ['https://www.googleapis.com/auth/chat.bot'],
120
120
  CLOUDRESOURCEMANAGER: [CLOUD_PLATFORM_SCOPE],
121
+ IAM: [IAM_SCOPE],
121
122
  ORGPOLICY: [CLOUD_PLATFORM_SCOPE],
122
123
  }
123
124
  #
@@ -131,6 +132,12 @@ APIS_NEEDING_ACCESS_TOKEN = {
131
132
  CBCM: ['https://www.googleapis.com/auth/admin.directory.device.chromebrowsers']
132
133
  }
133
134
  #
135
+ DEPRECATED_SCOPES = {
136
+ 'https://www.googleapis.com/auth/cloud-identity',
137
+ 'https://www.googleapis.com/auth/cloud-platform',
138
+ 'https://www.googleapis.com/auth/iam',
139
+ }
140
+ #
134
141
  REFRESH_PERM_ERRORS = [
135
142
  'invalid_grant: reauth related error (rapt_required)', # no way to reauth today
136
143
  'invalid_grant: Token has been expired or revoked',
@@ -596,7 +603,7 @@ _SVCACCT_SCOPES = [
596
603
  {'name': 'Cloud Identity Devices API',
597
604
  'api': CLOUDIDENTITY_DEVICES,
598
605
  'subscopes': READONLY,
599
- 'scope': 'https://www.googleapis.com/auth/cloud-identity'},
606
+ 'scope': 'https://www.googleapis.com/auth/cloud-identity.devices'},
600
607
  # {'name': 'Cloud Identity User Invitations API',
601
608
  # 'api': CLOUDIDENTITY_USERINVITATIONS,
602
609
  # 'subscopes': READONLY,
@@ -645,10 +652,11 @@ _SVCACCT_SCOPES = [
645
652
  'api': GMAIL,
646
653
  'subscopes': [],
647
654
  'scope': 'https://www.googleapis.com/auth/gmail.settings.sharing'},
648
- {'name': 'Identity and Access Management API',
649
- 'api': IAM,
650
- 'subscopes': [],
651
- 'scope': CLOUD_PLATFORM_SCOPE},
655
+ # {'name': 'Identity and Access Management API',
656
+ # 'api': IAM,
657
+ # 'offByDefault': True,
658
+ # 'subscopes': [],
659
+ # 'scope': CLOUD_PLATFORM_SCOPE},
652
660
  {'name': 'Keep API',
653
661
  'api': KEEP,
654
662
  'subscopes': READONLY,
gam/gamlib/glcfg.py CHANGED
@@ -163,6 +163,8 @@ EMAIL_BATCH_SIZE = 'email_batch_size'
163
163
  ENABLE_DASA = 'enable_dasa'
164
164
  # Enable Cloud Session Reauthentication by borrowing a RAPT token from gcloud command
165
165
  ENABLE_GCLOUD_REAUTH = 'enable_gcloud_reauth'
166
+ # Value for enforceExpansiveAccess for commands that delete or update drive file ACLs/permissions.
167
+ ENFORCE_EXPANSIVE_ACCESS = 'enforce_expansive_access'
166
168
  # When retrieving lists of calendar events from API, how many should be retrieved in each chunk
167
169
  EVENT_MAX_RESULTS = 'event_max_results'
168
170
  # Path to extra_args.txt
@@ -377,6 +379,7 @@ Defaults = {
377
379
  DEVICE_MAX_RESULTS: '200',
378
380
  DOMAIN: '',
379
381
  DRIVE_DIR: '',
382
+ ENFORCE_EXPANSIVE_ACCESS: FALSE,
380
383
  DRIVE_MAX_RESULTS: '1000',
381
384
  DRIVE_V3_BETA: FALSE,
382
385
  DRIVE_V3_NATIVE_NAMES: TRUE,
@@ -545,6 +548,7 @@ VAR_INFO = {
545
548
  DEVICE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 200)},
546
549
  DOMAIN: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GA_DOMAIN', VAR_LIMITS: (0, None)},
547
550
  DRIVE_DIR: {VAR_TYPE: TYPE_DIRECTORY, VAR_ENVVAR: 'GAMDRIVEDIR'},
551
+ ENFORCE_EXPANSIVE_ACCESS: {VAR_TYPE: TYPE_BOOLEAN},
548
552
  DRIVE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
549
553
  DRIVE_V3_BETA: {VAR_TYPE: TYPE_BOOLEAN},
550
554
  DRIVE_V3_NATIVE_NAMES: {VAR_TYPE: TYPE_BOOLEAN},
gam/gamlib/glmsgs.py CHANGED
@@ -140,12 +140,13 @@ SERVICE_ACCOUNT_PRIVATE_KEY_AGE = 'Service Account Private Key age: {0} days'
140
140
  SERVICE_ACCOUNT_SKIPPING_KEY_AGE_CHECK = 'Skipping Private Key age check: {0} rotation not necessary'
141
141
  UPDATE_PROJECT_TO_VIEW_MANAGE_SAKEYS = 'Please run "gam update project" to view/manage service account keys'
142
142
  DOMAIN_WIDE_DELEGATION_AUTHENTICATION = 'Domain-wide Delegation authentication'
143
+ DEPRECATED_SCOPES = 'Deprecated scopes that GAM should NEVER have DwD access to'
143
144
  SCOPE_AUTHORIZATION_PASSED = '''All scopes PASSED!
144
145
 
145
146
  Service Account Client name: {0} is fully authorized.
146
147
  '''
147
148
  SCOPE_AUTHORIZATION_UPDATE_PASSED = '''All scopes PASSED!
148
- To authorize them (in case some scopes were unselected), please go to the following link in your browser:
149
+ To update authorization (in case some scopes were unselected), please go to the following link in your browser:
149
150
  {0}
150
151
  {1}
151
152
 
@@ -156,8 +157,8 @@ Click AUTHORIZE
156
157
  When the box closes you're done
157
158
  After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
158
159
  '''
159
- SCOPE_AUTHORIZATION_FAILED = '''Some scopes FAILED!
160
- To authorize them, please go to the following link in your browser:
160
+ SCOPE_AUTHORIZATION_FAILED = '''Some scopes FAILED or should be DISABLED!
161
+ To update authorization, please go to the following link in your browser:
161
162
  {0}
162
163
  {1}
163
164
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gam7
3
- Version: 7.8.1
3
+ Version: 7.9.0
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
@@ -1,4 +1,4 @@
1
- gam/__init__.py,sha256=lAyeM6G9tA4Gb2Lvl865y6ErSDDYtGY_laDZsG--SmE,3513774
1
+ gam/__init__.py,sha256=9lZJAb1VOh7DXESSPZj1YJ-yenkZ1vAec5fNgvhwlLE,3515488
2
2
  gam/__main__.py,sha256=amz0-959ph6zkZKqjaar4n60yho-T37w6qWI36qx0CA,1049
3
3
  gam/cacerts.pem,sha256=82Ak7btW_2XvocLUvAwPmpx8Chi0oqtZUG1gseLK_t4,50235
4
4
  gam/cbcm-v1.1beta1.json,sha256=xO5XloCQQULmPbFBx5bckdqmbLFQ7sJ2TImhE1ysDIY,19439
@@ -23,15 +23,15 @@ gam/atom/token_store.py,sha256=7E6Ecvxa86WCvl1pJAhv78jg9OxQv8pMtIUcPhZCq04,3803
23
23
  gam/atom/url.py,sha256=pxO1TlORxyKQTQ1bkBE1unFzjnv9c8LjJkm-UEORShY,4276
24
24
  gam/gamlib/__init__.py,sha256=z5mF-y0j8pm-YNFBaiuxB4M_GAUPG-cXWwrhYwrVReM,679
25
25
  gam/gamlib/glaction.py,sha256=1Il_HrChVnPkzZwiZs5au4mFQVtq4K1Z42uIuR6qdnI,9419
26
- gam/gamlib/glapi.py,sha256=85YwZ5LhBoVd9kU3m-gwLRq8FwTWCaRIwARuQvH8Mjc,34022
27
- gam/gamlib/glcfg.py,sha256=eJCVb_OJ6cIsPuv-0IfIjHaTh5lM9juh4HOMLDblJmE,28055
26
+ gam/gamlib/glapi.py,sha256=7epQ2Hk9SK4Q6SImdJfvGvT5txftyfb5_jrF5K9cMpk,34253
27
+ gam/gamlib/glcfg.py,sha256=moWpsBv5iaASEvI1VfiQiI85jUjX6tYXa1uD1Oz3Y5M,28297
28
28
  gam/gamlib/glclargs.py,sha256=zB6GMmDR_y5IRj7LuoM6-Bk_ETfNQ6sTqCNB6RdPfyg,42350
29
29
  gam/gamlib/glentity.py,sha256=fqWUlxQqPKlfFrkuPjCK2lZhhFBIZboCuO0qCxuEwqA,33691
30
30
  gam/gamlib/glgapi.py,sha256=cGtvFvvBU3XQJLgtLCjs_V5VBUem_k0b5uUrK21VmeA,39491
31
31
  gam/gamlib/glgdata.py,sha256=weRppttWm6uRyqtBoGPKoHiNZ2h28nhfUV4J_mbCszY,2707
32
32
  gam/gamlib/glglobals.py,sha256=J0xcHggVrUBzHJ5GruenKV-qV1zPKcK2qWgAgN3i5Jw,9608
33
33
  gam/gamlib/glindent.py,sha256=RfBa2LDfLIqPLL5vMfC689TCVmqn8xf-qulSzkiatrc,1228
34
- gam/gamlib/glmsgs.py,sha256=iHRQFm008jh2ZzuYCq3sLkxFtEupo9DLh1gzq_6Y41A,33562
34
+ gam/gamlib/glmsgs.py,sha256=jiu6jRSspnbF25IbaTOV1NzvtCZlE-5ltfntitH2V5k,33677
35
35
  gam/gamlib/glskus.py,sha256=xJ1E2BZ_CGHN6I19c9i8DApb5bT5VT-hGyMEmQ5hSRY,15241
36
36
  gam/gamlib/gluprop.py,sha256=IyPLCyvn7-NHTUenM71YPQPXRZXx6CB5q-GtJ-FYd1c,11461
37
37
  gam/gamlib/glverlibs.py,sha256=A8rvegBF2nD6etbBRb8hsv-oZyjpD4VcUQ8PffW-bqU,992
@@ -65,8 +65,8 @@ gam/googleapiclient/discovery_cache/base.py,sha256=yCDPtxnbNN-p5_9fzBacC6P3wcUPl
65
65
  gam/googleapiclient/discovery_cache/file_cache.py,sha256=sim3Mg4HgRYo3vX75jvcKy_aV568EvIrtBfvfbw-044,4774
66
66
  gam/iso8601/__init__.py,sha256=Z2PsYbXgAH5a5xzUvgczCboPzqWpm65kRcIngCnhViU,1218
67
67
  gam/iso8601/iso8601.py,sha256=Li2FHZ4sBTWuthuQhyCvmvj0j6At8JbGzkSv2fc2RHU,4384
68
- gam7-7.8.1.dist-info/METADATA,sha256=hROgYCJUA2X_WKqgJKVV5jwf3q58_oAD8-6nw9gYwiA,2977
69
- gam7-7.8.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
70
- gam7-7.8.1.dist-info/entry_points.txt,sha256=HVUM5J7dA8YwvJfG30jiLefR19ExMs387TWugWd9sf4,42
71
- gam7-7.8.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
72
- gam7-7.8.1.dist-info/RECORD,,
68
+ gam7-7.9.0.dist-info/METADATA,sha256=oJvqu8C_6f7KNMBhg1z0LAhjR5HS-ccmNgHucvMaplU,2977
69
+ gam7-7.9.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
70
+ gam7-7.9.0.dist-info/entry_points.txt,sha256=HVUM5J7dA8YwvJfG30jiLefR19ExMs387TWugWd9sf4,42
71
+ gam7-7.9.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
72
+ gam7-7.9.0.dist-info/RECORD,,
File without changes