Cleaned up problems with some of the new Chat API asadmin commands.

This commit is contained in:
Ross Scroggs
2024-06-22 10:20:44 -07:00
parent 6964f10aa3
commit 793f230c30
7 changed files with 54 additions and 52 deletions

View File

@@ -317,7 +317,8 @@ gam create project [admin <EmailAddress>] [project <ProjectID>]
[sadescription <ServiceAccountDescription>]
[(algorithm KEY_ALG_RSA_1024|KEY_ALG_RSA_2048)|
(localkeysize 1024|2048|4096 [validityhours <Number>])|
(yubikey yubikey_pin yubikey_slot AUTHENTICATION|SIGNATURE yubikey_serialnumber <Number>)]
(yubikey yubikey_pin yubikey_slot AUTHENTICATION|SIGNATURE yubikey_serialnumber <Number>)|
nokey}
```
* `admin <EmailAddress>` - Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
* `appname <String>` - Application name, defaults to `GAM`
@@ -331,6 +332,8 @@ gam create project [admin <EmailAddress>] [project <ProjectID>]
You can optionally specify the type of service account key with `algorithm|localkeysize|yubikey`: [Manage Service Account keys](#manage-service-account-keys)
Use `nokey` if you do not want a service account key created for the project.
## Use an existing project for GAM authorization
Use an existing project to create and download two files: `client_secrets.json` for the Client and `oauth2service.json` for the Service Account.

View File

@@ -10,6 +10,11 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads) for Windows or other options, including manual installation
### 6.77.02
Cleaned up problems with some of the new Chat API asadmin commands.
Some remaining problems may require a Google fix.
### 6.77.01
Thanks to Jay, added column `verificationCodesCount` to `gam <UserTypeEntity> print backupcodes`

View File

@@ -335,7 +335,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin/bin/gamadv-xtd3$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAMADV-XTD3 6.77.01 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.77.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64
@@ -1009,7 +1009,7 @@ writes the credentials into the file oauth2.txt.
C:\GAMADV-XTD3>del C:\GAMConfig\oauth2.txt
C:\GAMADV-XTD3>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAMADV-XTD3 6.77.01 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.77.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final
Windows-10-10.0.17134 AMD64

View File

@@ -31,8 +31,10 @@ Exit Status of 0 indicates no errors, and backup codes are sent to stdout.
Exit status of 60 indicates no errors, and that no backup codes are available for this user.
```
gam <UserTypeEntity> print backupcodes|verificationcodes [todrive <ToDriveAttributes>*] [delimiter <Character>]
gam <UserTypeEntity> print backupcodes|verificationcodes [todrive <ToDriveAttributes>*]
[delimiter <Character>] [countsonly]
```
Gam displays the information in CSV form.
GAM displays the information in CSV form.
* `delimiter <Character>` - Separate `verificationCodes` entries with `<Character>`; the default value is `csv_output_field_delimiter` from `gam.cfg`.
* `countsonly` - Display only the number of available backup codes but not the codes themselves.

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details
```
gam version
GAMADV-XTD3 6.77.01 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.77.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64
@@ -15,7 +15,7 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information
```
gam version timeoffset
GAMADV-XTD3 6.77.01 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.77.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64
@@ -27,7 +27,7 @@ Your system time differs from www.googleapis.com by less than 1 second
Print the current version of Gam with extended details and SSL information
```
gam version extended
GAMADV-XTD3 6.77.01 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
GAMADV-XTD3 6.77.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64
@@ -64,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3
Version Check:
Current: 5.35.08
Latest: 6.77.01
Latest: 6.77.02
echo $?
1
```
@@ -72,7 +72,7 @@ echo $?
Print the current version number without details
```
gam version simple
6.77.01
6.77.02
```
In Linux/MacOS you can do:
```
@@ -82,7 +82,7 @@ echo $VER
Print the current version of Gam and address of this Wiki
```
gam help
GAM 6.77.01 - https://github.com/taers232c/GAMADV-XTD3
GAM 6.77.02 - https://github.com/taers232c/GAMADV-XTD3
Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64

View File

@@ -2,6 +2,11 @@
Merged GAM-Team version
6.77.02
Cleaned up problems with some of the new Chat API asadmin commands.
Some remaining problems may require a Google fix.
6.77.01
Thanks to Jay, added column `verificationCodesCount` to `gam <UserTypeEntity> print backupcodes`

View File

@@ -25169,8 +25169,8 @@ def exitIfChatNotConfigured(chat, kvList, errMsg, i, count):
def _getChatAdminAccess(adminAPI, userAPI):
if checkArgumentPresent(ADMIN_ACCESS_OPTIONS) or GC.Values[GC.USE_CHAT_ADMIN_ACCESS]:
return (True, adminAPI)
return (False, userAPI)
return (True, adminAPI, {'useAdminAccess': True})
return (False, userAPI, {})
def _chkChatAdminAccess(count):
if count != 1:
@@ -25395,7 +25395,7 @@ CHAT_UPDATE_SPACE_TYPE_MAP = {
# [formatjson]
def updateChatSpace(users):
FJQC = FormatJSONQuoteChar()
useAdminAccess, api = _getChatAdminAccess(API.CHAT_SPACES_ADMIN, API.CHAT_SPACES)
useAdminAccess, api, kwargsUAA = _getChatAdminAccess(API.CHAT_SPACES_ADMIN, API.CHAT_SPACES)
name = None
body = {}
updateMask = set()
@@ -25424,8 +25424,7 @@ def updateChatSpace(users):
try:
space = callGAPI(chat.spaces(), 'patch',
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
useAdminAccess=useAdminAccess,
name=name, updateMask=','.join(updateMask), body=body)
name=name, updateMask=','.join(updateMask), body=body, **kwargsUAA)
if not FJQC.formatJSON:
entityActionPerformed(kvList, i, count)
Ind.Increment()
@@ -25438,7 +25437,7 @@ def updateChatSpace(users):
# gam <UserItem> delete chatspace asadmin <ChatSpace>
def deleteChatSpace(users):
name = None
useAdminAccess, api = _getChatAdminAccess(API.CHAT_SPACES_DELETE_ADMIN, API.CHAT_SPACES_DELETE)
useAdminAccess, api, kwargsUAA = _getChatAdminAccess(API.CHAT_SPACES_DELETE_ADMIN, API.CHAT_SPACES_DELETE)
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'space' or myarg.startswith('spaces/') or myarg.startswith('space/'):
@@ -25457,9 +25456,8 @@ def deleteChatSpace(users):
continue
try:
callGAPI(chat.spaces(), 'delete',
useAdminAccess=useAdminAccess,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
name=name)
name=name, **kwargsUAA)
entityActionPerformed(kvList, i, count)
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
@@ -25494,13 +25492,12 @@ def infoChatSpace(users, name=None):
FJQC = FormatJSONQuoteChar()
if name is None:
function = 'get'
useAdminAccess, api = _getChatAdminAccess(API.CHAT_SPACES_ADMIN, API.CHAT_SPACES)
kwargs = {'useAdminAccess': True}
useAdminAccess, api, kwargsUAA = _getChatAdminAccess(API.CHAT_SPACES_ADMIN, API.CHAT_SPACES)
else:
function = 'findDirectMessage'
useAdminAccess = None
kwargsUAA = {}
api = API.CHAT_SPACES
kwargs = {}
fieldsList = []
while Cmd.ArgumentsRemaining():
myarg = getArgument()
@@ -25524,7 +25521,7 @@ def infoChatSpace(users, name=None):
try:
space = callGAPI(chat.spaces(), function,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
name=name, fields=fields, **kwargs)
name=name, fields=fields, **kwargsUAA)
if not FJQC.formatJSON:
entityPerformAction(kvList, i, count)
Ind.Increment()
@@ -25605,7 +25602,7 @@ def printShowChatSpaces(users):
csvPF = CSVPrintFile(['User', 'name'] if not isinstance(users, list) else ['name']) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF)
OBY = OrderBy(CHAT_SPACES_ADMIN_ORDERBY_CHOICE_MAP)
useAdminAccess, api = _getChatAdminAccess(API.CHAT_SPACES_ADMIN, API.CHAT_SPACES)
useAdminAccess, api, kwargs = _getChatAdminAccess(API.CHAT_SPACES_ADMIN, API.CHAT_SPACES)
fieldsList = []
queries = []
queryTimes = {}
@@ -25613,7 +25610,6 @@ def printShowChatSpaces(users):
kwargs = {}
if useAdminAccess:
function = 'search'
kwargs['useAdminAccess'] = True
queries = ['customer = "customers/my_customer" AND spaceType = "SPACE"']
else:
function = 'list'
@@ -25708,14 +25704,12 @@ def createChatMember(users):
member = callGAPI(chat.spaces().members(), 'create',
bailOnInternalError=True,
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.NOT_FOUND, GAPI.INVALID, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.INTERNAL_ERROR],
useAdminAccess=useAdminAccess,
parent=parent, body=body)
parent=parent, body=body, **kwargsUAA)
if role != 'ROLE_MEMBER' and entityType == Ent.CHAT_MANAGER_USER:
member = callGAPI(chat.spaces().members(), 'patch',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.INTERNAL_ERROR],
useAdminAccess=useAdminAccess,
name=member['name'], updateMask='role', body={'role': role})
name=member['name'], updateMask='role', body={'role': role}, **kwargsUAA)
if not returnIdOnly:
kvList[-1] = member['name']
_getChatMemberEmail(cd, member)
@@ -25738,7 +25732,7 @@ def createChatMember(users):
userList = []
groupList = []
returnIdOnly = False
useAdminAccess, api = _getChatAdminAccess(API.CHAT_MEMBERSHIPS_ADMIN, API.CHAT_MEMBERSHIPS)
useAdminAccess, api, kwargsUAA = _getChatAdminAccess(API.CHAT_MEMBERSHIPS_ADMIN, API.CHAT_MEMBERSHIPS)
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'space' or myarg.startswith('spaces/') or myarg.startswith('space/'):
@@ -25788,17 +25782,16 @@ def createChatMember(users):
addMembers(groupMembers, 'groupMember', Ent.CHAT_MEMBER_GROUP, i, count)
Ind.Decrement()
def _deleteChatMembers(chat, kvList, jcount, memberNames, i, count, useAdminAccess=None):
def _deleteChatMembers(chat, kvList, jcount, memberNames, i, count, kwargsUAA):
j = 0
for name in memberNames:
j += 1
kvList[-1] = name
try:
callGAPI(chat.spaces().members(), 'delete',
useAdminAccess=useAdminAccess,
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.INTERNAL_ERROR],
name=name)
name=name, **kwargsUAA)
entityActionPerformed(kvList, j, jcount)
except GAPI.notFound as e:
entityActionFailedWarning(kvList, str(e), j, jcount)
@@ -25836,7 +25829,7 @@ def deleteUpdateChatMember(users):
body = {}
memberNames = []
userGroupList = []
useAdminAccess, api = _getChatAdminAccess(API.CHAT_MEMBERSHIPS_ADMIN, API.CHAT_MEMBERSHIPS)
useAdminAccess, api, kwargsUAA = _getChatAdminAccess(API.CHAT_MEMBERSHIPS_ADMIN, API.CHAT_MEMBERSHIPS)
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if action in {Act.UPDATE, Act.MODIFY} and myarg == 'role':
@@ -25887,7 +25880,7 @@ def deleteUpdateChatMember(users):
kvList.extend([Ent.CHAT_MEMBER, ''])
Ind.Increment()
if deleteMode:
_deleteChatMembers(chat, kvList, jcount, memberNames, i, count, useAdminAccess=useAdminAccess)
_deleteChatMembers(chat, kvList, jcount, memberNames, i, count, kwargsUAA)
else:
j = 0
for name in memberNames:
@@ -25897,8 +25890,7 @@ def deleteUpdateChatMember(users):
member = callGAPI(chat.spaces().members(), 'patch',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.INTERNAL_ERROR],
useAdminAccess=useAdminAccess,
name=name, updateMask='role', body=body)
name=name, updateMask='role', body=body, **kwargsUAA)
_getChatMemberEmail(cd, member)
Ind.Increment()
_showChatItem(member, Ent.CHAT_MEMBER, FJQC, j, jcount)
@@ -25947,14 +25939,12 @@ def syncChatMembers(users):
callGAPI(chat.spaces().members(), 'create',
bailOnInternalError=True,
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.NOT_FOUND, GAPI.INVALID, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.INTERNAL_ERROR],
useAdminAccess=useAdminAccess,
parent=parent, body=body)
parent=parent, body=body, **kwargsUAA)
if role != 'ROLE_MEMBER' and entityType == Ent.CHAT_MANAGER_USER:
callGAPI(chat.spaces().members(), 'patch',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.INTERNAL_ERROR],
useAdminAccess=useAdminAccess,
name=memberName, updateMask='role', body={'role': role})
name=memberName, updateMask='role', body={'role': role}, **kwargsUAA)
entityActionPerformed(kvList, j, jcount)
except (GAPI.alreadyExists, GAPI.notFound, GAPI.invalid, GAPI.invalidArgument, GAPI.permissionDenied, GAPI.internalError) as e:
entityActionFailedWarning(kvList, str(e), j, jcount)
@@ -25971,11 +25961,11 @@ def syncChatMembers(users):
return
kvList.extend([entityType, ''])
Ind.Increment()
_deleteChatMembers(chat, kvList, jcount, memberNames, i, count, useAdminAccess=useAdminAccess)
_deleteChatMembers(chat, kvList, jcount, memberNames, i, count, kwargsUAA)
Ind.Decrement()
del kvList[-2:]
useAdminAccess, api = _getChatAdminAccess(API.CHAT_MEMBERSHIPS_ADMIN, API.CHAT_MEMBERSHIPS)
useAdminAccess, api, kwargsUAA = _getChatAdminAccess(API.CHAT_MEMBERSHIPS_ADMIN, API.CHAT_MEMBERSHIPS)
cd = buildGAPIObject(API.DIRECTORY)
parent = None
role = CHAT_MEMBER_ROLE_MAP['member']
@@ -26045,7 +26035,7 @@ def syncChatMembers(users):
members = callGAPIpages(chat.spaces().members(), 'list', 'memberships',
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, i, count, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
pageSize=CHAT_PAGE_SIZE, parent=parent, showGroups=groupsSpecified)
pageSize=CHAT_PAGE_SIZE, parent=parent, showGroups=groupsSpecified, **kwargsUAA)
for member in members:
if 'member' in member:
if member['member']['type'] == mtype and member['role'] == role:
@@ -26091,7 +26081,7 @@ CHAT_MEMBERS_FIELDS_CHOICE_MAP = {
def infoChatMember(users):
cd = buildGAPIObject(API.DIRECTORY)
FJQC = FormatJSONQuoteChar()
useAdminAccess, api = _getChatAdminAccess(API.CHAT_MEMBERSHIPS_ADMIN, API.CHAT_MEMBERSHIPS)
useAdminAccess, api, kwargsUAA = _getChatAdminAccess(API.CHAT_MEMBERSHIPS_ADMIN, API.CHAT_MEMBERSHIPS)
fieldsList = []
memberNames = []
while Cmd.ArgumentsRemaining():
@@ -26125,8 +26115,7 @@ def infoChatMember(users):
member = callGAPI(chat.spaces().members(), 'get',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.INTERNAL_ERROR],
useAdminAccess=useAdminAccess,
name=name, fields=fields)
name=name, fields=fields, **kwargsUAA)
_getChatMemberEmail(cd, member)
Ind.Increment()
_showChatItem(member, Ent.CHAT_MEMBER, FJQC, j, jcount)
@@ -26166,7 +26155,7 @@ def printShowChatMembers(users):
csvPF = CSVPrintFile(['User', 'space.name', 'space.displayName', 'name'] if not isinstance(users, list) else ['space.name', 'space.displayName', 'name']) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF)
OBY = OrderBy(CHAT_SPACES_ADMIN_ORDERBY_CHOICE_MAP)
useAdminAccess, api = _getChatAdminAccess(API.CHAT_MEMBERSHIPS_ADMIN, API.CHAT_MEMBERSHIPS)
useAdminAccess, api, kwargsUAA = _getChatAdminAccess(API.CHAT_MEMBERSHIPS_ADMIN, API.CHAT_MEMBERSHIPS)
if useAdminAccess:
queries = ['customer = "customers/my_customer" AND spaceType = "SPACE"']
queryTimes = {}
@@ -26277,14 +26266,12 @@ def printShowChatMembers(users):
if not parent['displayName']:
space = callGAPI(chatsp.spaces(), 'get',
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
useAdminAccess=useAdminAccess,
name=parentName, fields='displayName')
name=parentName, fields='displayName', **kwargsUAA)
parent['displayName'] = space.get('displayName', 'None')
members = callGAPIpages(chat.spaces().members(), 'list', 'memberships',
useAdminAccess=useAdminAccess,
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, j, jcount, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
parent=parentName, fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargs)
parent=parentName, fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargs, **kwargsUAA)
for member in members:
_getChatMemberEmail(cd, member)
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e: