gam7 7.18.4__py3-none-any.whl → 7.18.6__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 +268 -101
- gam/gamlib/glmsgs.py +1 -0
- {gam7-7.18.4.dist-info → gam7-7.18.6.dist-info}/METADATA +1 -1
- {gam7-7.18.4.dist-info → gam7-7.18.6.dist-info}/RECORD +7 -7
- {gam7-7.18.4.dist-info → gam7-7.18.6.dist-info}/WHEEL +0 -0
- {gam7-7.18.4.dist-info → gam7-7.18.6.dist-info}/entry_points.txt +0 -0
- {gam7-7.18.4.dist-info → gam7-7.18.6.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.18.
|
|
28
|
+
__version__ = '7.18.06'
|
|
29
29
|
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
|
30
30
|
|
|
31
31
|
#pylint: disable=wrong-import-position
|
|
@@ -3952,14 +3952,20 @@ def SetGlobalVariables():
|
|
|
3952
3952
|
if checkArgumentPresent(Cmd.SELECT_CMD):
|
|
3953
3953
|
sectionName = _selectSection()
|
|
3954
3954
|
GM.Globals[GM.SECTION] = sectionName # Save section for inner gams
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3955
|
+
# If command line is simply: gam select <SectionName>
|
|
3956
|
+
# assume save
|
|
3957
|
+
if not Cmd.ArgumentsRemaining():
|
|
3958
|
+
GM.Globals[GM.PARSER].set(configparser.DEFAULTSECT, GC.SECTION, sectionName)
|
|
3959
|
+
_writeGamCfgFile(GM.Globals[GM.PARSER], GM.Globals[GM.GAM_CFG_FILE], Act.SAVE)
|
|
3960
|
+
else:
|
|
3961
|
+
while Cmd.ArgumentsRemaining():
|
|
3962
|
+
if checkArgumentPresent('save'):
|
|
3963
|
+
GM.Globals[GM.PARSER].set(configparser.DEFAULTSECT, GC.SECTION, sectionName)
|
|
3964
|
+
_writeGamCfgFile(GM.Globals[GM.PARSER], GM.Globals[GM.GAM_CFG_FILE], Act.SAVE)
|
|
3965
|
+
elif checkArgumentPresent('verify'):
|
|
3966
|
+
_verifyValues(sectionName, inputFilterSectionName, outputFilterSectionName)
|
|
3967
|
+
else:
|
|
3968
|
+
break
|
|
3963
3969
|
GM.Globals[GM.GAM_CFG_SECTION_NAME] = sectionName
|
|
3964
3970
|
# showsections
|
|
3965
3971
|
if checkArgumentPresent(Cmd.SHOWSECTIONS_CMD):
|
|
@@ -11482,13 +11488,14 @@ def _createOauth2serviceJSON(httpObj, projectInfo, svcAcctInfo, create_key=True)
|
|
|
11482
11488
|
iam = getAPIService(API.IAM, httpObj)
|
|
11483
11489
|
try:
|
|
11484
11490
|
service_account = callGAPI(iam.projects().serviceAccounts(), 'create',
|
|
11485
|
-
throwReasons=[GAPI.
|
|
11491
|
+
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.NOT_FOUND,
|
|
11492
|
+
GAPI.PERMISSION_DENIED, GAPI.ALREADY_EXISTS],
|
|
11486
11493
|
name=f'projects/{projectInfo["projectId"]}',
|
|
11487
11494
|
body={'accountId': svcAcctInfo['name'],
|
|
11488
11495
|
'serviceAccount': {'displayName': svcAcctInfo['displayName'],
|
|
11489
11496
|
'description': svcAcctInfo['description']}})
|
|
11490
11497
|
entityActionPerformed([Ent.PROJECT, projectInfo['projectId'], Ent.SVCACCT, service_account['name'].rsplit('/', 1)[-1]])
|
|
11491
|
-
except (GAPI.notFound, GAPI.permissionDenied) as e:
|
|
11498
|
+
except (GAPI.failedPrecondition, GAPI.notFound, GAPI.permissionDenied) as e:
|
|
11492
11499
|
entityActionFailedWarning([Ent.PROJECT, projectInfo['projectId']], str(e))
|
|
11493
11500
|
return False
|
|
11494
11501
|
except GAPI.alreadyExists as e:
|
|
@@ -44894,21 +44901,44 @@ def waitForMailbox(entityList):
|
|
|
44894
44901
|
Ind.Decrement()
|
|
44895
44902
|
|
|
44896
44903
|
def getUserLicenses(lic, user, skus):
|
|
44897
|
-
def _callbackGetLicense(
|
|
44904
|
+
def _callbackGetLicense(request_id, response, exception):
|
|
44898
44905
|
if exception is None:
|
|
44899
44906
|
if response and 'skuId' in response:
|
|
44900
44907
|
licenses.append(response['skuId'])
|
|
44908
|
+
del sku_calls[request_id]
|
|
44909
|
+
else:
|
|
44910
|
+
_, reason, _ = checkGAPIError(exception, softErrors=True)
|
|
44911
|
+
reasons_to_quit = [
|
|
44912
|
+
GAPI.ACCESS_NOT_CONFIGURED, # license API not turned on
|
|
44913
|
+
GAPI.PERMISSION_DENIED, # Admin doesn't have rights to license assignments
|
|
44914
|
+
GAPI.NOT_FOUND # API call succeeded, user does not have this license
|
|
44915
|
+
]
|
|
44916
|
+
if reason in reasons_to_quit:
|
|
44917
|
+
del sku_calls[request_id]
|
|
44901
44918
|
|
|
44902
44919
|
licenses = []
|
|
44903
44920
|
svcargs = dict([('userId', user['primaryEmail']), ('productId', None), ('skuId', None), ('fields', 'skuId')]+GM.Globals[GM.EXTRA_ARGS_LIST])
|
|
44904
44921
|
method = getattr(lic.licenseAssignments(), 'get')
|
|
44905
44922
|
dbatch = lic.new_batch_http_request(callback=_callbackGetLicense)
|
|
44923
|
+
sku_calls = {}
|
|
44906
44924
|
for sku in skus:
|
|
44907
44925
|
svcparms = svcargs.copy()
|
|
44908
44926
|
svcparms['productId'] = sku[0]
|
|
44909
|
-
|
|
44910
|
-
|
|
44911
|
-
|
|
44927
|
+
sku_id = sku[1]
|
|
44928
|
+
svcparms['skuId'] = sku_id
|
|
44929
|
+
sku_calls[sku_id] = method(**svcparms)
|
|
44930
|
+
try_count = 0
|
|
44931
|
+
while sku_calls:
|
|
44932
|
+
try_count += 1
|
|
44933
|
+
dbatch = lic.new_batch_http_request(callback=_callbackGetLicense)
|
|
44934
|
+
for sku_id, sku_call in sku_calls.items():
|
|
44935
|
+
dbatch.add(sku_call, request_id=sku_id)
|
|
44936
|
+
dbatch.execute()
|
|
44937
|
+
if sku_calls:
|
|
44938
|
+
if try_count >= 5:
|
|
44939
|
+
# give up and return what we have
|
|
44940
|
+
return licenses
|
|
44941
|
+
time.sleep(5)
|
|
44912
44942
|
return licenses
|
|
44913
44943
|
|
|
44914
44944
|
USER_NAME_PROPERTY_PRINT_ORDER = [
|
|
@@ -46393,9 +46423,30 @@ def checkCIUserIsInvitable(users):
|
|
|
46393
46423
|
return
|
|
46394
46424
|
csvPF.writeCSVfile('Invitable Users')
|
|
46395
46425
|
|
|
46426
|
+
INBOUNDSSO_INPUT_MODE_CHOICE_MAP = {
|
|
46427
|
+
'saml': 'saml',
|
|
46428
|
+
'samlsso': 'saml',
|
|
46429
|
+
'oidc': 'oidc',
|
|
46430
|
+
'oidcsso': 'oidc',
|
|
46431
|
+
}
|
|
46432
|
+
|
|
46433
|
+
INBOUNDSSO_OUTPUT_MODE_CHOICE_MAP = {
|
|
46434
|
+
'all': 'all',
|
|
46435
|
+
'saml': 'saml',
|
|
46436
|
+
'samlsso': 'saml',
|
|
46437
|
+
'oidc': 'oidc',
|
|
46438
|
+
'oidcsso': 'oidc',
|
|
46439
|
+
}
|
|
46440
|
+
|
|
46441
|
+
INBOUNDSSO_ALL_SAML = {'all', 'saml'}
|
|
46442
|
+
INBOUNDSSO_ALL_OIDC = {'all', 'oidc'}
|
|
46443
|
+
|
|
46396
46444
|
INBOUNDSSO_MODE_CHOICE_MAP = {
|
|
46397
46445
|
'ssooff': 'SSO_OFF',
|
|
46446
|
+
'saml': 'SAML_SSO',
|
|
46398
46447
|
'samlsso': 'SAML_SSO',
|
|
46448
|
+
'oidc': 'OIDC_SSO',
|
|
46449
|
+
'oidcsso': 'OIDC_SSO',
|
|
46399
46450
|
'domainwidesamlifenabled': 'DOMAIN_WIDE_SAML_IF_ENABLED'
|
|
46400
46451
|
}
|
|
46401
46452
|
|
|
@@ -46405,29 +46456,49 @@ def getCIOrgunitID(cd, orgunit):
|
|
|
46405
46456
|
ou_id = ou_id[3:]
|
|
46406
46457
|
return f'orgUnits/{ou_id}'
|
|
46407
46458
|
|
|
46408
|
-
def _getInboundSSOProfiles(ci):
|
|
46459
|
+
def _getInboundSSOProfiles(ci, mode):
|
|
46409
46460
|
customer = normalizeChannelCustomerID(GC.Values[GC.CUSTOMER_ID])
|
|
46410
|
-
|
|
46411
|
-
|
|
46412
|
-
|
|
46413
|
-
|
|
46414
|
-
|
|
46415
|
-
|
|
46416
|
-
|
|
46417
|
-
|
|
46418
|
-
|
|
46419
|
-
|
|
46420
|
-
|
|
46461
|
+
profiles = []
|
|
46462
|
+
if mode in INBOUNDSSO_ALL_SAML:
|
|
46463
|
+
try:
|
|
46464
|
+
profiles.extend(callGAPIpages(ci.inboundSamlSsoProfiles(), 'list', 'inboundSamlSsoProfiles',
|
|
46465
|
+
throwReasons=GAPI.CISSO_LIST_THROW_REASONS,
|
|
46466
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
46467
|
+
bailOnInternalError=True,
|
|
46468
|
+
filter=f'customer=="{customer}"'))
|
|
46469
|
+
except (GAPI.notFound, GAPI.domainNotFound, GAPI.domainCannotUseApis,
|
|
46470
|
+
GAPI.forbidden, GAPI.badRequest, GAPI.invalid,
|
|
46471
|
+
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
|
46472
|
+
entityActionFailedWarning([Ent.INBOUND_SSO_PROFILE, customer], str(e))
|
|
46473
|
+
if mode in INBOUNDSSO_ALL_OIDC:
|
|
46474
|
+
try:
|
|
46475
|
+
profiles.extend(callGAPIpages(ci.inboundOidcSsoProfiles(), 'list', 'inboundOidcSsoProfiles',
|
|
46476
|
+
throwReasons=GAPI.CISSO_LIST_THROW_REASONS,
|
|
46477
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
46478
|
+
bailOnInternalError=True,
|
|
46479
|
+
filter=f'customer=="{customer}"'))
|
|
46480
|
+
except (GAPI.notFound, GAPI.domainNotFound, GAPI.domainCannotUseApis,
|
|
46481
|
+
GAPI.forbidden, GAPI.badRequest, GAPI.invalid,
|
|
46482
|
+
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
|
46483
|
+
entityActionFailedWarning([Ent.INBOUND_SSO_PROFILE, customer], str(e))
|
|
46484
|
+
return profiles
|
|
46421
46485
|
|
|
46422
|
-
def _convertInboundSSOProfileDisplaynameToName(ci
|
|
46486
|
+
def _convertInboundSSOProfileDisplaynameToName(ci, mode, displayName='',
|
|
46487
|
+
entityType=Ent.INBOUND_SSO_PROFILE):
|
|
46423
46488
|
if displayName.lower().startswith('id:') or displayName.lower().startswith('uid:'):
|
|
46424
46489
|
displayName = displayName.split(':', 1)[1]
|
|
46425
|
-
if
|
|
46426
|
-
|
|
46490
|
+
if mode == 'all':
|
|
46491
|
+
if not (displayName.startswith('inboundSamlSsoProfiles/') and
|
|
46492
|
+
displayName.startswith('inboundOidcSsoProfiles/')):
|
|
46493
|
+
displayName = f'inboundSamlSsoProfiles/{displayName}'
|
|
46494
|
+
elif mode == 'saml':
|
|
46495
|
+
if not displayName.startswith('inboundSamlSsoProfiles/'):
|
|
46496
|
+
displayName = f'inboundSamlSsoProfiles/{displayName}'
|
|
46497
|
+
else:
|
|
46498
|
+
if not displayName.startswith('inboundOidcSsoProfiles/'):
|
|
46499
|
+
displayName = f'inboundOidcSsoProfiles/{displayName}'
|
|
46427
46500
|
return displayName
|
|
46428
|
-
|
|
46429
|
-
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
|
46430
|
-
profiles = _getInboundSSOProfiles(ci)
|
|
46501
|
+
profiles = _getInboundSSOProfiles(ci, mode)
|
|
46431
46502
|
matches = []
|
|
46432
46503
|
for profile in profiles:
|
|
46433
46504
|
if displayName.lower() == profile.get('displayName', '').lower():
|
|
@@ -46435,30 +46506,50 @@ def _convertInboundSSOProfileDisplaynameToName(ci=None, displayName=''):
|
|
|
46435
46506
|
if len(matches) == 1:
|
|
46436
46507
|
return matches[0]['name']
|
|
46437
46508
|
if len(matches) == 0:
|
|
46438
|
-
|
|
46439
|
-
|
|
46440
|
-
|
|
46441
|
-
|
|
46442
|
-
|
|
46509
|
+
errMsg = Msg.NO_SSO_PROFILE_MATCHES.format(displayName)
|
|
46510
|
+
else:
|
|
46511
|
+
errMsg = Msg.MULTIPLE_SSO_PROFILES_MATCH.format(displayName)
|
|
46512
|
+
for m in matches:
|
|
46513
|
+
errMsg += f' {m["name"]} {m["displayName"]}\n'
|
|
46514
|
+
entityActionFailedWarning([entityType, None], errMsg)
|
|
46515
|
+
return None
|
|
46443
46516
|
|
|
46444
|
-
def _getInboundSSOProfileArguments(body):
|
|
46517
|
+
def _getInboundSSOProfileArguments(body, mode):
|
|
46445
46518
|
returnNameOnly = False
|
|
46446
|
-
|
|
46447
|
-
|
|
46448
|
-
|
|
46449
|
-
|
|
46450
|
-
|
|
46451
|
-
|
|
46452
|
-
|
|
46453
|
-
|
|
46454
|
-
|
|
46455
|
-
|
|
46456
|
-
|
|
46457
|
-
|
|
46458
|
-
|
|
46459
|
-
|
|
46460
|
-
|
|
46461
|
-
|
|
46519
|
+
if mode == 'saml':
|
|
46520
|
+
while Cmd.ArgumentsRemaining():
|
|
46521
|
+
myarg = getArgument()
|
|
46522
|
+
if myarg == 'name':
|
|
46523
|
+
body['displayName'] = getString(Cmd.OB_STRING)
|
|
46524
|
+
elif myarg == 'entityid':
|
|
46525
|
+
body.setdefault('idpConfig', {})['entityId'] = getString(Cmd.OB_STRING)
|
|
46526
|
+
elif myarg == 'loginurl':
|
|
46527
|
+
body.setdefault('idpConfig', {})['singleSignOnServiceUri'] = getString(Cmd.OB_STRING)
|
|
46528
|
+
elif myarg == 'logouturl':
|
|
46529
|
+
body.setdefault('idpConfig', {})['logoutRedirectUri'] = getString(Cmd.OB_STRING)
|
|
46530
|
+
elif myarg == 'changepasswordurl':
|
|
46531
|
+
body.setdefault('idpConfig', {})['changePasswordUri'] = getString(Cmd.OB_STRING)
|
|
46532
|
+
elif myarg == 'returnnameonly':
|
|
46533
|
+
returnNameOnly = True
|
|
46534
|
+
else:
|
|
46535
|
+
unknownArgumentExit()
|
|
46536
|
+
else:
|
|
46537
|
+
while Cmd.ArgumentsRemaining():
|
|
46538
|
+
myarg = getArgument()
|
|
46539
|
+
if myarg == 'name':
|
|
46540
|
+
body['displayName'] = getString(Cmd.OB_STRING)
|
|
46541
|
+
elif myarg == 'issueruri':
|
|
46542
|
+
body.setdefault('idpConfig', {})['issuerUri'] = getString(Cmd.OB_STRING)
|
|
46543
|
+
elif myarg == 'changepasswordurl':
|
|
46544
|
+
body.setdefault('idpConfig', {})['changePasswordUri'] = getString(Cmd.OB_STRING)
|
|
46545
|
+
elif myarg == 'clientid':
|
|
46546
|
+
body.setdefault('rpConfig', {})['clientId'] = getString(Cmd.OB_STRING)
|
|
46547
|
+
elif myarg == 'clientsecret':
|
|
46548
|
+
body.setdefault('rpConfig', {})['clientSecret'] = getString(Cmd.OB_STRING)
|
|
46549
|
+
elif myarg == 'returnnameonly':
|
|
46550
|
+
returnNameOnly = True
|
|
46551
|
+
else:
|
|
46552
|
+
unknownArgumentExit()
|
|
46462
46553
|
return (returnNameOnly, body)
|
|
46463
46554
|
|
|
46464
46555
|
def _showInboundSSOProfile(profile, FJQC, i=0, count=0):
|
|
@@ -46489,18 +46580,24 @@ def _processInboundSSOProfileResult(result, returnNameOnly, kvlist, function):
|
|
|
46489
46580
|
else:
|
|
46490
46581
|
writeStdout('inProgress\n')
|
|
46491
46582
|
|
|
46492
|
-
|
|
46583
|
+
def _getInboundSSOModeService(ci):
|
|
46584
|
+
mode = getChoice(INBOUNDSSO_INPUT_MODE_CHOICE_MAP, defaultChoice='saml', mapChoice=True)
|
|
46585
|
+
service = ci.inboundSamlSsoProfiles() if mode == 'saml' else ci.inboundOidcSsoProfiles()
|
|
46586
|
+
return (mode, service)
|
|
46587
|
+
|
|
46588
|
+
# gam create inboundssoprofile [saml|oidc] [name <SSOProfileName>]
|
|
46493
46589
|
# [entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
|
|
46494
46590
|
# [returnnameonly]
|
|
46495
46591
|
def doCreateInboundSSOProfile():
|
|
46496
46592
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
|
46593
|
+
mode, service = _getInboundSSOModeService(ci)
|
|
46497
46594
|
body = {'customer': normalizeChannelCustomerID(GC.Values[GC.CUSTOMER_ID]),
|
|
46498
46595
|
'displayName': 'SSO Profile'
|
|
46499
46596
|
}
|
|
46500
|
-
returnNameOnly, body = _getInboundSSOProfileArguments(body)
|
|
46597
|
+
returnNameOnly, body = _getInboundSSOProfileArguments(body, mode)
|
|
46501
46598
|
kvlist = [Ent.INBOUND_SSO_PROFILE, body['displayName']]
|
|
46502
46599
|
try:
|
|
46503
|
-
result = callGAPI(
|
|
46600
|
+
result = callGAPI(service, 'create',
|
|
46504
46601
|
throwReasons=GAPI.CISSO_CREATE_THROW_REASONS,
|
|
46505
46602
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
46506
46603
|
bailOnInternalError=True,
|
|
@@ -46511,16 +46608,19 @@ def doCreateInboundSSOProfile():
|
|
|
46511
46608
|
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
|
46512
46609
|
entityActionFailedWarning(kvlist, str(e))
|
|
46513
46610
|
|
|
46514
|
-
# gam update inboundssoprofile <SSOProfileItem>
|
|
46611
|
+
# gam update inboundssoprofile [saml|oidc] <SSOProfileItem>
|
|
46515
46612
|
# [entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
|
|
46516
46613
|
# [returnnameonly]
|
|
46517
46614
|
def doUpdateInboundSSOProfile():
|
|
46518
46615
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
|
46519
|
-
|
|
46520
|
-
|
|
46616
|
+
mode, service = _getInboundSSOModeService(ci)
|
|
46617
|
+
name = _convertInboundSSOProfileDisplaynameToName(ci, mode, getString(Cmd.OB_STRING))
|
|
46618
|
+
if not name:
|
|
46619
|
+
return
|
|
46620
|
+
returnNameOnly, body = _getInboundSSOProfileArguments({}, mode)
|
|
46521
46621
|
kvlist = [Ent.INBOUND_SSO_PROFILE, name]
|
|
46522
46622
|
try:
|
|
46523
|
-
result = callGAPI(
|
|
46623
|
+
result = callGAPI(service, 'patch',
|
|
46524
46624
|
throwReasons=GAPI.CISSO_UPDATE_THROW_REASONS,
|
|
46525
46625
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
46526
46626
|
bailOnInternalError=True,
|
|
@@ -46533,14 +46633,17 @@ def doUpdateInboundSSOProfile():
|
|
|
46533
46633
|
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
|
46534
46634
|
entityActionFailedWarning(kvlist, str(e))
|
|
46535
46635
|
|
|
46536
|
-
# gam delete inboundssoprofile <SSOProfileItem>
|
|
46636
|
+
# gam delete inboundssoprofile [saml|oidc] <SSOProfileItem>
|
|
46537
46637
|
def doDeleteInboundSSOProfile():
|
|
46538
46638
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
|
46539
|
-
|
|
46639
|
+
mode, service = _getInboundSSOModeService(ci)
|
|
46640
|
+
name = _convertInboundSSOProfileDisplaynameToName(ci, mode, getString(Cmd.OB_STRING))
|
|
46641
|
+
if not name:
|
|
46642
|
+
return
|
|
46540
46643
|
checkForExtraneousArguments()
|
|
46541
46644
|
kvlist = [Ent.INBOUND_SSO_PROFILE, name]
|
|
46542
46645
|
try:
|
|
46543
|
-
result = callGAPI(
|
|
46646
|
+
result = callGAPI(service, 'delete',
|
|
46544
46647
|
throwReasons=GAPI.CISSO_UPDATE_THROW_REASONS,
|
|
46545
46648
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
46546
46649
|
bailOnInternalError=True,
|
|
@@ -46553,33 +46656,54 @@ def doDeleteInboundSSOProfile():
|
|
|
46553
46656
|
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
|
46554
46657
|
entityActionFailedWarning(kvlist, str(e))
|
|
46555
46658
|
|
|
46556
|
-
def
|
|
46659
|
+
def _getInboundSSOProfileByName(ci, mode, name):
|
|
46660
|
+
notFound = False
|
|
46557
46661
|
kvlist = [Ent.INBOUND_SSO_PROFILE, name]
|
|
46558
|
-
|
|
46559
|
-
|
|
46560
|
-
|
|
46561
|
-
|
|
46562
|
-
|
|
46563
|
-
|
|
46564
|
-
|
|
46662
|
+
if mode in INBOUNDSSO_ALL_SAML:
|
|
46663
|
+
try:
|
|
46664
|
+
return callGAPI(ci.inboundSamlSsoProfiles(), 'get',
|
|
46665
|
+
throwReasons=GAPI.CISSO_GET_THROW_REASONS,
|
|
46666
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
46667
|
+
bailOnInternalError=True,
|
|
46668
|
+
name=name)
|
|
46669
|
+
except GAPI.notFound:
|
|
46670
|
+
notFound = True
|
|
46671
|
+
except (GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
|
|
46672
|
+
GAPI.badRequest, GAPI.invalid, GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
|
46673
|
+
entityActionFailedWarning(kvlist, str(e))
|
|
46674
|
+
if mode in INBOUNDSSO_ALL_OIDC:
|
|
46675
|
+
try:
|
|
46676
|
+
return callGAPI(ci.inboundOidcSsoProfiles(), 'get',
|
|
46677
|
+
throwReasons=GAPI.CISSO_GET_THROW_REASONS,
|
|
46678
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
46679
|
+
bailOnInternalError=True,
|
|
46680
|
+
name=name)
|
|
46681
|
+
except GAPI.notFound:
|
|
46682
|
+
notFound = True
|
|
46683
|
+
except (GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
|
|
46684
|
+
GAPI.badRequest, GAPI.invalid, GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
|
46685
|
+
entityActionFailedWarning(kvlist, str(e))
|
|
46686
|
+
if notFound:
|
|
46565
46687
|
entityActionFailedWarning(kvlist, Msg.DOES_NOT_EXIST)
|
|
46566
|
-
except (GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
|
|
46567
|
-
GAPI.badRequest, GAPI.invalid, GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
|
46568
|
-
entityActionFailedWarning(kvlist, str(e))
|
|
46569
46688
|
return None
|
|
46570
46689
|
|
|
46571
|
-
# gam info inboundssoprofile <SSOProfileItem> [formatjson]
|
|
46690
|
+
# gam info inboundssoprofile [all|saml|oidc] <SSOProfileItem> [formatjson]
|
|
46572
46691
|
def doInfoInboundSSOProfile():
|
|
46573
46692
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
|
46574
|
-
|
|
46693
|
+
mode = getChoice(INBOUNDSSO_OUTPUT_MODE_CHOICE_MAP, defaultChoice='all', mapChoice=True)
|
|
46694
|
+
name = getString(Cmd.OB_STRING)
|
|
46575
46695
|
FJQC = FormatJSONQuoteChar(formatJSONOnly=True)
|
|
46576
|
-
|
|
46696
|
+
name = _convertInboundSSOProfileDisplaynameToName(ci, mode, name)
|
|
46697
|
+
if not name:
|
|
46698
|
+
return
|
|
46699
|
+
mode = 'saml' if name.startswith('inboundSamlSsoProfiles/') else 'oidc'
|
|
46700
|
+
profile = _getInboundSSOProfileByName(ci, mode, name)
|
|
46577
46701
|
if profile:
|
|
46578
46702
|
_showInboundSSOProfile(profile, FJQC)
|
|
46579
46703
|
|
|
46580
|
-
# gam show inboundssoprofile
|
|
46704
|
+
# gam show inboundssoprofile [all|saml|oidc]
|
|
46581
46705
|
# [formatjson]
|
|
46582
|
-
# gam print inboundssoprofile [todrive <ToDriveAttribute>*]
|
|
46706
|
+
# gam print inboundssoprofile [all|saml|oidc] [todrive <ToDriveAttribute>*]
|
|
46583
46707
|
# [[formatjson [quotechar <Character>]]
|
|
46584
46708
|
def doPrintShowInboundSSOProfiles():
|
|
46585
46709
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
|
@@ -46587,6 +46711,7 @@ def doPrintShowInboundSSOProfiles():
|
|
|
46587
46711
|
csvPF = CSVPrintFile(['name']) if Act.csvFormat() else None
|
|
46588
46712
|
FJQC = FormatJSONQuoteChar(csvPF)
|
|
46589
46713
|
cfilter = f'customer=="{customer}"'
|
|
46714
|
+
mode = getChoice(INBOUNDSSO_OUTPUT_MODE_CHOICE_MAP, defaultChoice='all', mapChoice=True)
|
|
46590
46715
|
while Cmd.ArgumentsRemaining():
|
|
46591
46716
|
myarg = getArgument()
|
|
46592
46717
|
if csvPF and myarg == 'todrive':
|
|
@@ -46595,7 +46720,7 @@ def doPrintShowInboundSSOProfiles():
|
|
|
46595
46720
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
|
46596
46721
|
if csvPF:
|
|
46597
46722
|
printGettingAllAccountEntities(Ent.INBOUND_SSO_PROFILE, cfilter)
|
|
46598
|
-
profiles = _getInboundSSOProfiles(ci)
|
|
46723
|
+
profiles = _getInboundSSOProfiles(ci, mode)
|
|
46599
46724
|
if not csvPF:
|
|
46600
46725
|
count = len(profiles)
|
|
46601
46726
|
if not FJQC.formatJSON:
|
|
@@ -46665,6 +46790,7 @@ def _processInboundSSOCredentialsResult(result, kvlist, function):
|
|
|
46665
46790
|
# (pemfile <FileName>)|(generatekey [keysize 1024|2048|4096]) [replaceolddest]
|
|
46666
46791
|
def doCreateInboundSSOCredential():
|
|
46667
46792
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
|
46793
|
+
mode = 'saml'
|
|
46668
46794
|
profile = None
|
|
46669
46795
|
generateKey = replaceOldest = False
|
|
46670
46796
|
keySize = 2048
|
|
@@ -46672,7 +46798,11 @@ def doCreateInboundSSOCredential():
|
|
|
46672
46798
|
while Cmd.ArgumentsRemaining():
|
|
46673
46799
|
myarg = getArgument()
|
|
46674
46800
|
if myarg == 'profile':
|
|
46675
|
-
profile = _convertInboundSSOProfileDisplaynameToName(ci,
|
|
46801
|
+
profile = _convertInboundSSOProfileDisplaynameToName(ci, mode,
|
|
46802
|
+
getString(Cmd.OB_STRING),
|
|
46803
|
+
Ent.INBOUND_SSO_CREDENTIALS)
|
|
46804
|
+
if not profile:
|
|
46805
|
+
return
|
|
46676
46806
|
elif myarg == 'pemfile':
|
|
46677
46807
|
pemData = readFile(getString(Cmd.OB_FILE_NAME))
|
|
46678
46808
|
elif myarg == 'generatekey':
|
|
@@ -46776,15 +46906,24 @@ def doPrintShowInboundSSOCredentials():
|
|
|
46776
46906
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
|
46777
46907
|
csvPF = CSVPrintFile(['name']) if Act.csvFormat() else None
|
|
46778
46908
|
FJQC = FormatJSONQuoteChar(csvPF)
|
|
46909
|
+
mode = 'saml'
|
|
46779
46910
|
profiles = []
|
|
46780
46911
|
while Cmd.ArgumentsRemaining():
|
|
46781
46912
|
myarg = getArgument()
|
|
46782
46913
|
if myarg in {'profile', 'profiles'}:
|
|
46783
|
-
|
|
46914
|
+
errors = 0
|
|
46915
|
+
for profile in getEntityList(Cmd.OB_STRING_LIST, shlexSplit=True):
|
|
46916
|
+
name = _convertInboundSSOProfileDisplaynameToName(ci, mode, profile, Ent.INBOUND_SSO_CREDENTIALS)
|
|
46917
|
+
if name:
|
|
46918
|
+
profiles.append(name)
|
|
46919
|
+
else:
|
|
46920
|
+
errors += 1
|
|
46921
|
+
if errors:
|
|
46922
|
+
return
|
|
46784
46923
|
else:
|
|
46785
46924
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
|
46786
46925
|
if not profiles:
|
|
46787
|
-
profiles = [p['name'] for p in _getInboundSSOProfiles(ci)]
|
|
46926
|
+
profiles = [p['name'] for p in _getInboundSSOProfiles(ci, mode)]
|
|
46788
46927
|
count = len(profiles)
|
|
46789
46928
|
i = 0
|
|
46790
46929
|
for profile in profiles:
|
|
@@ -46877,6 +47016,7 @@ def _getInboundSSOAssignmentByTarget(ci, cd, target):
|
|
|
46877
47016
|
usageErrorExit(Msg.NO_SSO_PROFILE_ASSIGNED.format(targetType, target))
|
|
46878
47017
|
|
|
46879
47018
|
def _getInboundSSOAssignmentArguments(ci, cd, body):
|
|
47019
|
+
mode = None
|
|
46880
47020
|
rank = 0
|
|
46881
47021
|
while Cmd.ArgumentsRemaining():
|
|
46882
47022
|
myarg = getArgument()
|
|
@@ -46884,9 +47024,19 @@ def _getInboundSSOAssignmentArguments(ci, cd, body):
|
|
|
46884
47024
|
rank = getInteger(minVal=1)
|
|
46885
47025
|
elif myarg == 'mode':
|
|
46886
47026
|
body['ssoMode'] = getChoice(INBOUNDSSO_MODE_CHOICE_MAP, mapChoice=True)
|
|
46887
|
-
|
|
46888
|
-
|
|
46889
|
-
|
|
47027
|
+
if body['ssoMode'] == 'SAML_SSO':
|
|
47028
|
+
mode = 'saml'
|
|
47029
|
+
profile = 'inboundSamlSsoProfile'
|
|
47030
|
+
elif body['ssoMode'] == 'OIDC_SSO':
|
|
47031
|
+
mode = 'oidc'
|
|
47032
|
+
profile = 'inboundOidcSsoProfile'
|
|
47033
|
+
elif mode and myarg == 'profile':
|
|
47034
|
+
name = _convertInboundSSOProfileDisplaynameToName(ci, mode,
|
|
47035
|
+
getString(Cmd.OB_STRING),
|
|
47036
|
+
Ent.INBOUND_SSO_ASSIGNMENT)
|
|
47037
|
+
if not name:
|
|
47038
|
+
return None
|
|
47039
|
+
body['samlSsoInfo'] = {profile: name}
|
|
46890
47040
|
elif myarg == 'neverredirect':
|
|
46891
47041
|
body['signInBehavior'] = {'redirectCondition': 'NEVER'}
|
|
46892
47042
|
elif myarg == 'group':
|
|
@@ -46897,7 +47047,7 @@ def _getInboundSSOAssignmentArguments(ci, cd, body):
|
|
|
46897
47047
|
unknownArgumentExit()
|
|
46898
47048
|
if 'ssoMode' not in body:
|
|
46899
47049
|
missingArgumentExit('mode')
|
|
46900
|
-
if
|
|
47050
|
+
if mode and 'samlSsoInfo' not in body:
|
|
46901
47051
|
missingArgumentExit('profile')
|
|
46902
47052
|
if 'targetGroup' in body:
|
|
46903
47053
|
if 'targetOrgUnit' in body:
|
|
@@ -46935,13 +47085,17 @@ def _processInboundSSOAssignmentResult(result, kvlist, ci, cd, function):
|
|
|
46935
47085
|
else:
|
|
46936
47086
|
entityActionPerformedMessage(kvlist, Msg.ACTION_IN_PROGRESS.format(f'{function} inboundssoassignment'))
|
|
46937
47087
|
|
|
46938
|
-
# gam create inboundssoassignment
|
|
46939
|
-
# (
|
|
47088
|
+
# gam create inboundssoassignment
|
|
47089
|
+
# (group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)
|
|
47090
|
+
# (mode sso_off)|(mode saml_sso profile <SSOProfileItem>)|(mode oidc_sso profile <SSOProfileName>}|(mode domain_wide_saml_if_enabled)
|
|
47091
|
+
# [neverredirect]
|
|
46940
47092
|
def doCreateInboundSSOAssignment():
|
|
46941
47093
|
cd = buildGAPIObject(API.DIRECTORY)
|
|
46942
47094
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
|
46943
47095
|
body = {'customer': normalizeChannelCustomerID(GC.Values[GC.CUSTOMER_ID])}
|
|
46944
47096
|
body = _getInboundSSOAssignmentArguments(ci, cd, body)
|
|
47097
|
+
if not body:
|
|
47098
|
+
return
|
|
46945
47099
|
kvlist = [Ent.INBOUND_SSO_ASSIGNMENT, body['customer']]
|
|
46946
47100
|
try:
|
|
46947
47101
|
result = callGAPI(ci.inboundSsoAssignments(), 'create',
|
|
@@ -46955,8 +47109,10 @@ def doCreateInboundSSOAssignment():
|
|
|
46955
47109
|
GAPI.systemError, GAPI.permissionDenied, GAPI.internalError, GAPI.serviceNotAvailable) as e:
|
|
46956
47110
|
entityActionFailedWarning(kvlist, str(e))
|
|
46957
47111
|
|
|
46958
|
-
# gam update inboundssoassignment
|
|
46959
|
-
# [(
|
|
47112
|
+
# gam update inboundssoassignment <SSOAssignmentName>
|
|
47113
|
+
# [(group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)]
|
|
47114
|
+
# (mode sso_off)|(mode saml_sso profile <SSOProfileItem>)|(mode oidc_sso profile <SSOProfileName>}|(mode domain_wide_saml_if_enabled)
|
|
47115
|
+
# [neverredirect]
|
|
46960
47116
|
def doUpdateInboundSSOAssignment():
|
|
46961
47117
|
cd = buildGAPIObject(API.DIRECTORY)
|
|
46962
47118
|
ci = buildGAPIObject(API.CLOUDIDENTITY_INBOUND_SSO)
|
|
@@ -47013,14 +47169,20 @@ def doInfoInboundSSOAssignment():
|
|
|
47013
47169
|
return
|
|
47014
47170
|
name = assignment.get('samlSsoInfo', {}).get('inboundSamlSsoProfile')
|
|
47015
47171
|
if name:
|
|
47016
|
-
profile =
|
|
47172
|
+
profile = _getInboundSSOProfileByName(ci, 'saml', name)
|
|
47017
47173
|
if profile:
|
|
47018
47174
|
assignment['samlSsoInfo']['inboundSamlSsoProfile'] = profile
|
|
47175
|
+
else:
|
|
47176
|
+
name = assignment.get('oidcSsoInfo', {}).get('inboundOidcSsoProfile')
|
|
47177
|
+
if name:
|
|
47178
|
+
profile = _getInboundSSOProfileByName(ci, 'oidc', name)
|
|
47179
|
+
if profile:
|
|
47180
|
+
assignment['oidcSsoInfo']['inboundOidcSsoProfile'] = profile
|
|
47019
47181
|
_showInboundSSOAssignment(assignment, FJQC, ci, cd)
|
|
47020
47182
|
|
|
47021
|
-
# gam show
|
|
47183
|
+
# gam show inboundssoassignments
|
|
47022
47184
|
# [formatjson]
|
|
47023
|
-
# gam print
|
|
47185
|
+
# gam print inboundssoassignments [todrive <ToDriveAttribute>*]
|
|
47024
47186
|
# [[formatjson [quotechar <Character>]]
|
|
47025
47187
|
def doPrintShowInboundSSOAssignments():
|
|
47026
47188
|
cd = buildGAPIObject(API.DIRECTORY)
|
|
@@ -71135,7 +71297,7 @@ def _processMessagesThreads(users, entityType):
|
|
|
71135
71297
|
try:
|
|
71136
71298
|
callGAPI(gmail.users().messages(), function,
|
|
71137
71299
|
throwReasons=GAPI.GMAIL_THROW_REASONS+[GAPI.INVALID_MESSAGE_ID, GAPI.INVALID, GAPI.INVALID_ARGUMENT,
|
|
71138
|
-
GAPI.FAILED_PRECONDITION, GAPI.PERMISSION_DENIED],
|
|
71300
|
+
GAPI.FAILED_PRECONDITION, GAPI.PERMISSION_DENIED, GAPI.QUOTA_EXCEEDED],
|
|
71139
71301
|
userId='me', body=body)
|
|
71140
71302
|
for messageId in body['ids']:
|
|
71141
71303
|
mcount += 1
|
|
@@ -71145,7 +71307,7 @@ def _processMessagesThreads(users, entityType):
|
|
|
71145
71307
|
csvPF.WriteRow({'User': user, entityHeader: messageId, 'action': Act.Performed()})
|
|
71146
71308
|
except GAPI.serviceNotAvailable:
|
|
71147
71309
|
mcount += bcount
|
|
71148
|
-
except (GAPI.invalid, GAPI.invalidArgument, GAPI.permissionDenied) as e:
|
|
71310
|
+
except (GAPI.invalid, GAPI.invalidArgument, GAPI.permissionDenied, GAPI.quotaExceeded) as e:
|
|
71149
71311
|
_processMessageFailed(user, idsList, f'{str(e)} ({mcount+1}-{mcount+bcount}/{jcount})')
|
|
71150
71312
|
mcount += bcount
|
|
71151
71313
|
except GAPI.invalidMessageId:
|
|
@@ -71158,7 +71320,8 @@ def _processMessagesThreads(users, entityType):
|
|
|
71158
71320
|
|
|
71159
71321
|
_GMAIL_ERROR_REASON_TO_MESSAGE_MAP = {GAPI.NOT_FOUND: Msg.DOES_NOT_EXIST,
|
|
71160
71322
|
GAPI.INVALID_MESSAGE_ID: Msg.INVALID_MESSAGE_ID,
|
|
71161
|
-
GAPI.FAILED_PRECONDITION: Msg.FAILED_PRECONDITION
|
|
71323
|
+
GAPI.FAILED_PRECONDITION: Msg.FAILED_PRECONDITION,
|
|
71324
|
+
GAPI.QUOTA_EXCEEDED: Msg.QUOTA_EXCEEDED}
|
|
71162
71325
|
|
|
71163
71326
|
def _callbackProcessMessage(request_id, _, exception):
|
|
71164
71327
|
ri = request_id.splitlines()
|
|
@@ -71169,7 +71332,9 @@ def _processMessagesThreads(users, entityType):
|
|
|
71169
71332
|
csvPF.WriteRow({'User': ri[RI_ENTITY], entityHeader: ri[RI_ITEM], 'action': Act.Performed()})
|
|
71170
71333
|
else:
|
|
71171
71334
|
http_status, reason, message = checkGAPIError(exception)
|
|
71172
|
-
_processMessageFailed(ri[RI_ENTITY], ri[RI_ITEM],
|
|
71335
|
+
_processMessageFailed(ri[RI_ENTITY], ri[RI_ITEM],
|
|
71336
|
+
getHTTPError(_GMAIL_ERROR_REASON_TO_MESSAGE_MAP, http_status, reason, message),
|
|
71337
|
+
int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
|
71173
71338
|
|
|
71174
71339
|
def _batchProcessMessagesThreads(service, function, user, jcount, messageIds, **kwargs):
|
|
71175
71340
|
svcargs = dict([('userId', 'me'), ('id', None), ('fields', '')]+list(kwargs.items())+GM.Globals[GM.EXTRA_ARGS_LIST])
|
|
@@ -71267,7 +71432,9 @@ def _processMessagesThreads(users, entityType):
|
|
|
71267
71432
|
continue
|
|
71268
71433
|
if parameters['messageEntity'] is None:
|
|
71269
71434
|
if parameters['maxToProcess'] and jcount > parameters['maxToProcess']:
|
|
71270
|
-
entityNumEntitiesActionNotPerformedWarning([Ent.USER, user], entityType, jcount,
|
|
71435
|
+
entityNumEntitiesActionNotPerformedWarning([Ent.USER, user], entityType, jcount,
|
|
71436
|
+
Msg.COUNT_N_EXCEEDS_MAX_TO_PROCESS_M.format(jcount, Act.ToPerform(), parameters['maxToProcess']),
|
|
71437
|
+
i, count)
|
|
71271
71438
|
continue
|
|
71272
71439
|
if not parameters['doIt']:
|
|
71273
71440
|
entityNumEntitiesActionNotPerformedWarning([Ent.USER, user], entityType, jcount, Msg.USE_DOIT_ARGUMENT_TO_PERFORM_ACTION, i, count)
|
gam/gamlib/glmsgs.py
CHANGED
|
@@ -465,6 +465,7 @@ PROCESSING_ITEM_N = '{0},0,Processing item {1}\n'
|
|
|
465
465
|
PROCESSING_ITEM_N_OF_M = '{0},0,Processing item {1}/{2}\n'
|
|
466
466
|
PROFILE_PHOTO_NOT_FOUND = 'Profile photo not found'
|
|
467
467
|
PROFILE_PHOTO_IS_DEFAULT = 'Profile photo is default'
|
|
468
|
+
QUOTA_EXCEEDED = 'Quota exceeded'
|
|
468
469
|
REASON_ONLY_VALID_WITH_CONTENTRESTRICTIONS_READONLY_TRUE = 'reason only valid with contentrestrictions readonly true'
|
|
469
470
|
REAUTHENTICATION_IS_NEEDED = 'Reauthentication is needed, please run\n\ngam oauth create'
|
|
470
471
|
RECOMMEND_RUNNING_GAM_ROTATE_SAKEY = 'Recommend running "gam rotate sakey" to get a new key\n'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
gam/__init__.py,sha256=
|
|
1
|
+
gam/__init__.py,sha256=E5u75yFxYquGMVAfkhxCDcSpYauMaL2akfztrblZEPo,3584006
|
|
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
|
|
@@ -31,7 +31,7 @@ gam/gamlib/glgapi.py,sha256=pdBbwNtnCwFWxJGaP-_3hdTjSNoOCJF2yo76WdQOi1k,40426
|
|
|
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=
|
|
34
|
+
gam/gamlib/glmsgs.py,sha256=vephDvTNbv55f79QzZWEKDcBTXr8knrwDxvx-1TYM6M,33997
|
|
35
35
|
gam/gamlib/glskus.py,sha256=e1u3zw1MGQjBgAFXqjrGWQl2d7eYpVlMYGpIKNwjskQ,15360
|
|
36
36
|
gam/gamlib/gluprop.py,sha256=IyPLCyvn7-NHTUenM71YPQPXRZXx6CB5q-GtJ-FYd1c,11461
|
|
37
37
|
gam/gamlib/glverlibs.py,sha256=xoQXiwcE_-HVYKv-VYA8O0mazRsc9mN-_ysj1dAlMyc,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.18.
|
|
69
|
-
gam7-7.18.
|
|
70
|
-
gam7-7.18.
|
|
71
|
-
gam7-7.18.
|
|
72
|
-
gam7-7.18.
|
|
68
|
+
gam7-7.18.6.dist-info/METADATA,sha256=0RPFGDNkA24f5tyNH_NHgVcrdkiDKXHU6ZP-6F-cmQE,2940
|
|
69
|
+
gam7-7.18.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
70
|
+
gam7-7.18.6.dist-info/entry_points.txt,sha256=HVUM5J7dA8YwvJfG30jiLefR19ExMs387TWugWd9sf4,42
|
|
71
|
+
gam7-7.18.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
72
|
+
gam7-7.18.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|