Compare commits

..

2 Commits

Author SHA1 Message Date
Ross Scroggs
98ef879a34 Fixed logic flaw in gam print|show policies where non-matching policies were displayed.
Some checks failed
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Has been cancelled
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2024-11-10 18:57:22 -08:00
Ross Scroggs
95b3a97925 Added group/ou filtering to print|show policies
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 5, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 7, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 4, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 6, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-24.04, 3.9) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run
Updated `gam get|update|delete contactphotos` to use the People API
2024-11-10 08:18:43 -08:00
8 changed files with 168 additions and 172 deletions

View File

@@ -1,6 +1,7 @@
# Cloud Identity Policies
- [API documentation](#api-documentation)
- [Notes](#notes)
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [Policies](#policies)
- [Display Cloud Identity Policies](#display-cloud-identity-policies)
@@ -322,8 +323,8 @@ gam info policies <CIPolicyEntity>
Select policies::
* `polices/<String>` - A policy name, `policies/ahv4hg7qc24kvaghb7zihwf4riid4`
* `settings/<String>` - A policy setting type, `settings/workspace_marketplace.apps_allowlist'
* `<String>` - A policy setting type, `workspace_marketplace.apps_allowlist'
* `settings/<String>` - A policy setting type, `settings/workspace_marketplace.apps_allowlist`
* `<String>` - A policy setting type, `workspace_marketplace.apps_allowlist`
By default, policy warnings are displayed, use the 'nowarnings` option to suppress their display.
@@ -337,10 +338,13 @@ Display all or filtered policies.
```
gam show policies
[filter <String>] [nowarnings] [noappnames]
[group <RegularExpression>] [ou|org|orgunit <RegularExpression>]
[formatjson]
```
By default, all policies are displayed.
* `filter <String>` - Display filtered policies, See https://cloud.google.com/identity/docs/reference/rest/v1beta1/policies/list
* `group <RegularExpression>` - Only display policies whose group email address matches the `<RegularExpression>`
* `ou|org|orgunit <RegularExpression> - Only display policies whose OU path matches the `<RegularExpression>`
By default, policy warnings are displayed, use the 'nowarnings` option to suppress their display.
@@ -353,10 +357,13 @@ By default, Gam displays the information as an indented list of keys and values.
```
gam print policies [todrive <ToDriveAttribute>*]
[filter <String>] [nowarnings] [noappnames]
[group <RegularExpression>] [ou|org|orgunit <RegularExpression>]
[formatjson [quotechar <Character>]]
```
By default, all policies are displayed:
* `filter <String>` - Display filtered policies, See https://cloud.google.com/identity/docs/reference/rest/v1beta1/policies/list
* `group <RegularExpression>` - Only display policies whose group email address matches the `<RegularExpression>`
* `ou|org|orgunit <RegularExpression> - Only display policies whose OU path matches the `<RegularExpression>`
By default, policy warnings are displayed, use the 'nowarnings` option to suppress their display.
@@ -371,3 +378,9 @@ the quote character itself, the column delimiter (comma by default) and new-line
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
### Examples
Print all service status policies.
```
gam redirect csv ./ServiceStatusPolicies.csv print policies filter "setting.type.matches('.*service_status')"
```

View File

@@ -10,6 +10,20 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
### 7.00.38
Fixed logic flaw in `gam print|show policies` where non-matching policies were displayed.
### 7.00.37
Added options `group <RegularExpression>` and `ou|org|orgunit <RegularExpression>`
to `gam print|show policies` that causes GAM to only display policies whose group email address
or OU path match the `<RegularExpression>`.
Updated `gam get|update|delete contactphotos` to use the People API for domain shared contact photos
as Google has deprecated the Domain Shared Contacts API for these commands. Unfortunately,
the People API fails with `gam update|delete contactphotos`.
### 7.00.36
Updated `gam print chromeapps` to correct a trap caused by an API change.

View File

@@ -251,7 +251,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.00.36 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.38 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 64-bit final
MacOS Sonoma 14.5 x86_64
@@ -923,7 +923,7 @@ writes the credentials into the file oauth2.txt.
C:\>del C:\GAMConfig\oauth2.txt
C:\>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAM7 7.00.36 - https://github.com/GAM-team/GAM - pythonsource
GAM7 7.00.38 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 64-bit final
Windows-10-10.0.17134 AMD64

View File

@@ -6,8 +6,8 @@
- [Display calendar UI settings](#display-calendar-ui-settings)
- [Manage calendars](#manage-calendars)
- [Create and remove calendars](#create-and-remove-calendars)
- [Display calendar settings](#display-calendar-settings)
- [Modify calendar settings](#modify-calendar-settings)
- [Display calendar settings](#display-calendar-settings)
- [Manage calendar lists](#manage-calendar-lists)
- [Display specific calendars from list](#display-specific-calendars-from-list)
- [Display calendar lists](#display-calendar-lists)
@@ -23,6 +23,8 @@
<EmailAddress> ::= <String>@<DomainName>
<CalendarItem> ::= <EmailAddress>
<CalendarList> ::= "<CalendarItem>(,<CalendarItem>)*"
<CalendarEntity> ::= <CalendarList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
See: https://github.com/taers232c/GAMADV-XTD3/wiki/Collections-of-Items
<CourseAlias> ::= <String>
<CourseID> ::= <Number>|d:<CourseAlias>
<CourseIDList> ::= "<CourseID>(,<CourseID>)*"
@@ -38,6 +40,21 @@
<CalendarACLRole> ::=
editor|freebusy|freebusyreader|owner|reader|writer
<CalendarSettings> ::=
(description <String>)|
(location <String>)|
(summary <String>)|
(timezone <TimeZone>)
<CalendarSettingsField> ::=
conferenceproperties|
description|
id|
location|
summary|
timezone
<CalendarSettingsFieldList> ::= "<CalendarSettingsField>(,<CalendarSettingsField>)*"
<CalendarSelectProperty> ::=
minaccessrole <CalendarACLRole>|
showdeleted|
@@ -111,12 +128,6 @@
(selected <Boolean>)|
(summary <String>)
<CalendarSettings> ::=
(description <String>)|
(location <String>)|
(summary <String>)|
(timezone <TimeZone>)
<CalendarListField> ::=
accessrole|
backgroundcolor|
@@ -189,18 +200,30 @@ gam <UserTypeEntity> create calendar <CalendarSettings>
gam <UserTypeEntity> remove calendars <UserCalendarEntity>
```
### Display calendar settings
```
gam <UserTypeEntity> info calendars <UserCalendarEntity> [formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Modify calendar settings
```
gam <UserTypeEntity> modify calendars <UserCalendarEntity> <CalendarSettings>
```
### Display calendar settings
```
gam calendar <CalendarEntity> show settings
[fields <CalendarSettingsFieldList>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam calendar <CalendarEntity> print settings [todrive <ToDriveAttribute>*]
[fields <CalendarSettingsFieldList>]
[formatjson [quotechar <Character>]]
```
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
## Manage calendar lists
These commands manage a user's list of calendars.
```

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details
```
gam version
GAM 7.00.36 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.38 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 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
GAM 7.00.36 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.38 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 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
GAM 7.00.36 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.00.38 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 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/gam7
Version Check:
Current: 5.35.08
Latest: 7.00.36
Latest: 7.00.38
echo $?
1
```
@@ -72,7 +72,7 @@ echo $?
Print the current version number without details
```
gam version simple
7.00.36
7.00.38
```
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 7.00.36 - https://github.com/GAM-team/GAM
GAM 7.00.38 - https://github.com/GAM-team/GAM
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.0 64-bit final
MacOS Sonoma 14.5 x86_64

View File

@@ -4075,9 +4075,11 @@ gam info policies <CIPolicyNameEntity>
[formatjson]
gam print policies [todrive <ToDriveAttribute>*]
[filter <String>] [nowarnings] [noappnames]
[group <RegularExpression>] [ou|org|orgunit <RegularExpression>]
[formatjson [quotechar <Character>]]
gam show policies
[filter <String>] [nowarnings] [noappnames]
[group <RegularExpression>] [ou|org|orgunit <RegularExpression>]
[formatjson]
# Inbound SSO

View File

@@ -1,3 +1,17 @@
7.00.38
Fixed logic flaw in `gam print|show policies` where non-matching policies were displayed.
7.00.37
Added options `group <RegularExpression>` and `ou|org|orgunit <RegularExpression>`
to `gam print|show policies` that causes GAM to only display policies whose group email address
or OU path match the `<RegularExpression>`.
Updated `gam get|update|delete contactphotos` to use the People API for domain shared contact photos
as Google has deprecated the Domain Shared Contacts API for these commands. Unfortunately,
the People API fails with `gam update|delete contactphotos`.
7.00.36
Updated `gam print chromeapps` to correct a trap caused by an API change.

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
"""
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.00.36'
__version__ = '7.00.38'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position
@@ -2693,6 +2693,11 @@ def performActionNumItems(itemCount, itemType, i=0, count=0):
[f'{Act.ToPerform()} {itemCount} {Ent.Choose(itemType, itemCount)}'],
currentCountNL(i, count)))
def performActionModifierNumItems(modifier, itemCount, itemType, i=0, count=0):
writeStdout(formatKeyValueList(Ind.Spaces(),
[f'{Act.ToPerform()} {modifier} {itemCount} {Ent.Choose(itemType, itemCount)}'],
currentCountNL(i, count)))
def actionPerformedNumItems(itemCount, itemType, i=0, count=0):
writeStderr(formatKeyValueList(Ind.Spaces(),
[f'{itemCount} {Ent.Choose(itemType, itemCount)} {Act.Performed()} '],
@@ -20287,137 +20292,6 @@ def doPrintShowDomainContacts():
def doPrintShowGAL():
_printShowContacts(False)
def _processContactPhotos(function):
def _makeFilenameFromPattern():
filename = filenamePattern[:]
if subForContactId:
filename = filename.replace('#contactid#', contactId)
if subForEmail:
for email in fields.get('Emails', []):
if email.get('primary', 'false') == 'true':
filename = filename.replace('#email#', email['value'])
break
else:
filename = filename.replace('#email#', contactId)
return filename
entityType = Ent.DOMAIN
contactsManager = ContactsManager()
entityList, contactQuery, queriedContacts = _getContactEntityList(1, False)
if function in {'ChangePhoto', 'GetPhoto'}:
targetFolder = os.getcwd()
filenamePattern = '#contactid#.jpg'
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'drivedir':
targetFolder = GC.Values[GC.DRIVE_DIR]
elif myarg in {'sourcefolder', 'targetfolder'}:
targetFolder = os.path.expanduser(getString(Cmd.OB_FILE_PATH))
if function == 'GetPhoto' and not os.path.isdir(targetFolder):
os.makedirs(targetFolder)
elif myarg == 'filename':
filenamePattern = getString(Cmd.OB_PHOTO_FILENAME_PATTERN)
else:
unknownArgumentExit()
subForContactId = filenamePattern.find('#contactid#') != -1
subForEmail = filenamePattern.find('#email#') != -1
if not subForContactId and not subForEmail:
filename = filenamePattern
else: #elif function == 'DeletePhoto':
checkForExtraneousArguments()
user, contactsObject = getContactsObject(True)
if queriedContacts:
entityList = queryContacts(contactsObject, contactQuery)
if entityList is None:
return
j = 0
jcount = len(entityList)
entityPerformActionModifierNumItems([entityType, user], Msg.MAXIMUM_OF, jcount, Ent.PHOTO)
if jcount == 0:
setSysExitRC(NO_ENTITIES_FOUND_RC)
return
Ind.Increment()
for contact in entityList:
j += 1
try:
if not queriedContacts:
contactId = normalizeContactId(contact)
contact = callGData(contactsObject, 'GetContact',
throwErrors=[GDATA.NOT_FOUND, GDATA.BAD_REQUEST, GDATA.SERVICE_NOT_APPLICABLE, GDATA.FORBIDDEN, GDATA.NOT_IMPLEMENTED],
retryErrors=[GDATA.INTERNAL_SERVER_ERROR],
uri=contactsObject.GetContactFeedUri(contact_list=user, contactId=contactId))
fields = contactsManager.ContactToFields(contact)
else:
contactId = contactsManager.GetContactShortId(contact)
fields = contactsManager.ContactToFields(contact)
if not localContactSelects(contactsManager, contactQuery, fields):
continue
except (GDATA.notFound, GDATA.badRequest) as e:
entityActionFailedWarning([entityType, user, Ent.CONTACT, contactId], str(e), j, jcount)
break
except (GDATA.forbidden, GDATA.notImplemented):
entityServiceNotApplicableWarning(entityType, user)
break
except GDATA.serviceNotApplicable:
entityUnknownWarning(entityType, user)
break
try:
if function == 'ChangePhoto':
if subForContactId or subForEmail:
filename = _makeFilenameFromPattern()
filename = os.path.join(targetFolder, filename)
callGData(contactsObject, function,
throwErrors=[GDATA.NOT_FOUND, GDATA.BAD_REQUEST, GDATA.SERVICE_NOT_APPLICABLE, GDATA.FORBIDDEN, GDATA.NOT_IMPLEMENTED],
retryErrors=[GDATA.INTERNAL_SERVER_ERROR],
media=filename, contact_entry_or_url=contact,
content_type='image/*', content_length=os.path.getsize(filename), extra_headers={'If-Match': '*'})
entityActionPerformed([entityType, user, Ent.CONTACT, contactId, Ent.PHOTO, filename])
elif function == 'GetPhoto':
if subForContactId or subForEmail:
filename = _makeFilenameFromPattern()
filename = os.path.join(targetFolder, filename)
photo_data = callGData(contactsObject, function,
throwErrors=[GDATA.NOT_FOUND, GDATA.BAD_REQUEST, GDATA.SERVICE_NOT_APPLICABLE, GDATA.FORBIDDEN, GDATA.NOT_IMPLEMENTED],
retryErrors=[GDATA.INTERNAL_SERVER_ERROR],
contact_entry_or_url=contact)
if photo_data:
status, e = writeFileReturnError(filename, eval(photo_data), mode='wb') #pylint: disable=eval-used
if status:
entityActionPerformed([entityType, user, Ent.CONTACT, contactId, Ent.PHOTO, filename])
else:
entityActionFailedWarning([entityType, user, Ent.CONTACT, contactId, Ent.PHOTO, filename], str(e))
else:
entityDoesNotHaveItemWarning([entityType, user, Ent.CONTACT, contactId, Ent.PHOTO, ''])
else: #elif function == 'DeletePhoto':
filename = ''
callGData(contactsObject, function,
throwErrors=[GDATA.NOT_FOUND, GDATA.BAD_REQUEST, GDATA.SERVICE_NOT_APPLICABLE, GDATA.FORBIDDEN, GDATA.NOT_IMPLEMENTED],
retryErrors=[GDATA.INTERNAL_SERVER_ERROR],
contact_entry_or_url=contact, extra_headers={'If-Match': '*'})
entityActionPerformed([entityType, user, Ent.CONTACT, contactId, Ent.PHOTO, filename])
except GDATA.notFound as e:
entityActionFailedWarning([entityType, user, Ent.CONTACT, contactId, Ent.PHOTO, filename], str(e), j, jcount)
except (GDATA.badRequest, OSError, IOError) as e:
entityActionFailedWarning([entityType, user, Ent.CONTACT, contactId, Ent.PHOTO, filename], str(e), j, jcount)
except (GDATA.forbidden, GDATA.notImplemented):
entityServiceNotApplicableWarning(entityType, user)
break
Ind.Decrement()
# gam update contactphotos <ContactEntity>|<ContactSelection>
# [drivedir|(sourcefolder <FilePath>)] [filename <FileNamePattern>]
def doUpdateDomainContactPhoto():
_processContactPhotos('ChangePhoto')
# gam get contactphotos <ContactEntity>|<ContactSelection>
# [drivedir|(targetfolder <FilePath>)] [filename <FileNamePattern>]
def doGetDomainContactPhoto():
_processContactPhotos('GetPhoto')
# gam delete contactphotos <ContactEntity>|<ContactSelection>
def doDeleteDomainContactPhoto():
_processContactPhotos('DeletePhoto')
# Prople commands utilities
#
def normalizePeopleResourceName(resourceName):
@@ -22634,9 +22508,16 @@ def _processPeopleContactPhotos(users, function):
filename = filename.replace('#email#', resourceName.split('/')[1])
return filename
entityType = Ent.USER
peopleEntityType = Ent.PEOPLE_CONTACT
sources = [PEOPLE_READ_SOURCES_CHOICE_MAP['contact']]
if users is not None:
entityType = Ent.USER
peopleEntityType = Ent.PEOPLE_CONTACT
sources = [PEOPLE_READ_SOURCES_CHOICE_MAP['contact']]
else:
users = [None]
people = buildGAPIObject(API.PEOPLE_DIRECTORY)
entityType = Ent.DOMAIN
peopleEntityType = Ent.PEOPLE_CONTACT
sources = [PEOPLE_READ_SOURCES_CHOICE_MAP['domaincontact']]
entityList, resourceNameLists, contactQuery, queriedContacts = _getPeopleContactEntityList(entityType, 1)
if function in {'updateContactPhoto', 'getContactPhoto'}:
targetFolder = os.getcwd()
@@ -22665,9 +22546,12 @@ def _processPeopleContactPhotos(users, function):
i += 1
if resourceNameLists:
entityList = resourceNameLists[user]
user, people = buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
if user is not None:
user, people = buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
else:
user = Ent.Singular(entityType)
if contactQuery['contactGroupSelect']:
groupId, _, contactGroupNames = validatePeopleContactGroup(people, contactQuery['contactGroupSelect'],
None, None, entityType, user, i, count)
@@ -22774,6 +22658,20 @@ def getUserPeopleContactPhoto(users):
def deleteUserPeopleContactPhoto(users):
_processPeopleContactPhotos(users, 'deleteContactPhoto')
# gam update contactphotos <PeopleResourceNameEntity>|<PeopleUserContactSelection>
# [drivedir|(sourcefolder <FilePath>)] [filename <FileNamePattern>]
def doUpdateDomainContactPhoto():
_processPeopleContactPhotos(None, 'updateContactPhoto')
# gam get contactphotos <PeopleResourceNameEntity>|<PeopleUserContactSelection>
# [drivedir|(targetfolder <FilePath>)] [filename <FileNamePattern>]
def doGetDomainContactPhoto():
_processPeopleContactPhotos(None, 'getContactPhoto')
# gam delete contactphoto <PeopleResourceNameEntity>|<PeopleUserContactSelection>
def doDeleteDomainContactPhoto():
_processPeopleContactPhotos(None, 'deleteContactPhoto')
# gam <UserTypeEntity> create contactgroup <ContactGroupAttribute>+
# [(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*))| returnidonly]
def createUserPeopleContactGroup(users):
@@ -32648,6 +32546,8 @@ def infoGroups(entityList):
getCloudIdentity = True
cifields = getFieldsFromFieldsList(groupFieldsLists['ci'])
ci = buildGAPIObject(API.CLOUDIDENTITY_GROUPS)
else:
cifields = None
i = 0
count = len(entityList)
for group in entityList:
@@ -35131,7 +35031,9 @@ def _getPolicyAppNameFromId(httpObj, app):
if a:
app['applicationName'] = a.group(1)
def _cleanPolicy(policy, add_warnings, no_appnames, cd, groups_ci):
def _cleanPolicy(policy, add_warnings, no_appnames,
groupEmailPattern, orgUnitPathPattern,
cd, groups_ci):
# convert any wordlists into spaced strings to reduce output complexity
if policy['setting']['type'] == 'settings/detector.word_list':
policy['setting']['value']['wordList'] = ' '.join(policy['setting']['value']['wordList']['words'])
@@ -35147,8 +35049,17 @@ def _cleanPolicy(policy, add_warnings, no_appnames, cd, groups_ci):
_, _, policy['policyQuery']['groupEmail'] = convertGroupCloudIDToEmail(groups_ci, groupId)
# all groups are in the root OU so the orgUnit attribute is useless
policy['policyQuery'].pop('orgUnit', None)
if groupEmailPattern is not None:
return groupEmailPattern.match(policy['policyQuery']['groupEmail'])
if orgUnitPathPattern is not None:
return False
elif orgId := policy['policyQuery'].get('orgUnit'):
policy['policyQuery']['orgUnitPath'] = convertOrgUnitIDtoPath(cd, orgId)
if orgUnitPathPattern is not None:
return orgUnitPathPattern.match(policy['policyQuery']['orgUnitPath'])
if groupEmailPattern is not None:
return False
return True
def _showPolicy(policy, FJQC, i=0, count=0):
if FJQC is not None and FJQC.formatJSON:
@@ -35163,15 +35074,22 @@ def _showPolicy(policy, FJQC, i=0, count=0):
printBlankLine()
Ind.Decrement()
def _showPolicies(policies, FJQC, add_warnings, no_appnames, cd, groups_ci):
def _showPolicies(policies, FJQC, add_warnings, no_appnames,
groupEmailPattern, orgUnitPathPattern,
cd, groups_ci):
count = len(policies)
performActionNumItems(count, Ent.POLICY)
if groupEmailPattern is None and orgUnitPathPattern is None:
performActionNumItems(count, Ent.POLICY)
else:
performActionModifierNumItems(Msg.MAXIMUM_OF, count, Ent.POLICY)
Ind.Increment()
i = 0
for policy in policies:
i += 1
_cleanPolicy(policy, add_warnings, no_appnames, cd, groups_ci)
_showPolicy(policy, FJQC, i, count)
if _cleanPolicy(policy, add_warnings, no_appnames,
groupEmailPattern, orgUnitPathPattern,
cd, groups_ci):
_showPolicy(policy, FJQC, i, count)
Ind.Decrement()
# gam info policies <CIPolicyNameEntity>
@@ -35213,13 +35131,16 @@ def doInfoCIPolicies():
ifilter = f"setting.type.matches('{pname}')"
printGettingAllAccountEntities(Ent.POLICY, ifilter)
policies = _filterPolicies(ci, getPageMessage(), ifilter)
_showPolicies(policies, FJQC, add_warnings, no_appnames, cd, groups_ci)
_showPolicies(policies, FJQC, add_warnings, no_appnames,
None, None, cd, groups_ci)
# gam print policies [todrive <ToDriveAttribute>*]
# [filter <String>] [nowarnings] [noappnames]
# [group <RegularExpression>] [ou|org|orgunit <RegularExpression>]
# [formatjson [quotechar <Character>]]
# gam show policies
# [filter <String>] [nowarnings] [noappnames]
# [group <RegularExpression>] [ou|org|orgunit <RegularExpression>]
# [formatjson]
def doPrintShowCIPolicies():
@@ -35241,6 +35162,7 @@ def doPrintShowCIPolicies():
ifilter = None
add_warnings = True
no_appnames = False
groupEmailPattern = orgUnitPathPattern = None
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
@@ -35250,17 +35172,25 @@ def doPrintShowCIPolicies():
elif myarg == 'nowarnings':
add_warnings = False
elif myarg == 'noappnames':
no_appnames=True
no_appnames = True
elif myarg == 'group':
groupEmailPattern = getREPattern(re.IGNORECASE)
elif myarg in {'ou', 'org', 'orgunit'}:
orgUnitPathPattern = getREPattern(re.IGNORECASE)
else:
FJQC.GetFormatJSONQuoteChar(myarg, True)
printGettingAllAccountEntities(Ent.POLICY, ifilter)
policies = _filterPolicies(ci, getPageMessage(), ifilter)
if not csvPF:
_showPolicies(policies, FJQC, add_warnings, no_appnames, cd, groups_ci)
_showPolicies(policies, FJQC, add_warnings, no_appnames,
groupEmailPattern, orgUnitPathPattern,
cd, groups_ci)
else:
for policy in policies:
_cleanPolicy(policy, add_warnings, no_appnames, cd, groups_ci)
_printPolicy(policy)
if _cleanPolicy(policy, add_warnings, no_appnames,
groupEmailPattern, orgUnitPathPattern,
cd, groups_ci):
_printPolicy(policy)
if csvPF:
csvPF.writeCSVfile('Policies')