mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-19 21:51:37 +00:00
Compare commits
16 Commits
20250213.1
...
v7.05.02
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4200b66dc | ||
|
|
2afc28e017 | ||
|
|
90a2d385d6 | ||
|
|
f123fe197f | ||
|
|
8503aabefe | ||
|
|
80933755c4 | ||
|
|
03148a6ae8 | ||
|
|
96acd40692 | ||
|
|
3004da5ad7 | ||
|
|
bd699e2b31 | ||
|
|
0d9e35d013 | ||
|
|
af43db44ed | ||
|
|
8e3f30e901 | ||
|
|
cccbddcf45 | ||
|
|
a70bbf08ed | ||
|
|
57e1625246 |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -18,7 +18,7 @@ defaults:
|
||||
working-directory: src
|
||||
|
||||
env:
|
||||
SCRATCH_COUNTER: 9
|
||||
SCRATCH_COUNTER: 11
|
||||
OPENSSL_CONFIG_OPTS: no-fips --api=3.0.0
|
||||
OPENSSL_INSTALL_PATH: ${{ github.workspace }}/bin/ssl
|
||||
OPENSSL_SOURCE_PATH: ${{ github.workspace }}/src/openssl
|
||||
@@ -917,7 +917,7 @@ jobs:
|
||||
$gam calendar $gam_user addevent summary "GHA test event" start +1h end +2h attendee $newgroup hangoutsmeet guestscanmodify true sendupdates all
|
||||
$gam calendar $gam_user printevents after -0d
|
||||
$gam config enable_dasa false save
|
||||
matterid=uid:$($gam create vaultmatter name "GHA matter $newbase" description "test matter" collaborators $newuser returnidonly)
|
||||
matterid=uid:$($gam create vaultmatter name "GHA matter $newbase" description "test matter" returnidonly)
|
||||
$gam create vaulthold matter $matterid name "GHA hold $newbase" corpus mail accounts $newuser
|
||||
$gam print vaultmatters matterstate open
|
||||
$gam print vaultholds matter $matterid
|
||||
|
||||
@@ -3846,6 +3846,7 @@ gam info group|groups <GroupEntity>
|
||||
[formatjson]
|
||||
gam print groups [todrive <ToDriveAttribute>*]
|
||||
[([domain|domains <DomainNameEntity>] ([member|showownedby <EmailItem>]|[(query <QueryGroup>)|(queries <QueryGroupList>)]))|
|
||||
(group|group_ns|group_susp <GroupItem>)|
|
||||
(select <GroupEntity>)]
|
||||
[emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
|
||||
[descriptionmatchpattern [not] <RegularExpression>] (matchsetting [not] <GroupAttribute>)*
|
||||
@@ -3997,13 +3998,14 @@ gam print cigroups [todrive <ToDriveAttribute>*]
|
||||
|
||||
<CIGroupMembersFieldName> ::=
|
||||
createtime
|
||||
email|useremail|
|
||||
expiretime|
|
||||
memberkey|
|
||||
name|
|
||||
role|
|
||||
type|
|
||||
updatetime|
|
||||
useremail
|
||||
updatetime
|
||||
|
||||
<CIGroupMembersFieldNameList> ::= "<CIGroupMembersFieldName>(,<CIGroupMembersFieldName>)*"
|
||||
|
||||
gam <UserTypeEntity> info cimember <GroupEntity>
|
||||
@@ -4017,16 +4019,19 @@ gam print cigroup-members [todrive <ToDriveAttribute>*]
|
||||
[types <CIGroupMemberTypeList>]
|
||||
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
|
||||
<CIGroupMembersFieldName>* [fields <CIGroupMembersFieldNameList>]
|
||||
[(recursive [noduplicates])includederivedmembership] [nogroupeemail]
|
||||
[minimal|basic|full]
|
||||
[(recursive [noduplicates]) | includederivedmembership] [nogroupemail]
|
||||
[formatjson [quotechar <Character>]]
|
||||
gam show cigroup-members
|
||||
[(cimember|ciowner <UserItem>)|(cigroup <GroupItem>)|(select <GroupEntity>)]
|
||||
[showownedby <UserItem>]
|
||||
[emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
|
||||
[descriptionmatchpattern [not] <RegularExpression>]
|
||||
[roles <GroupRoleList>] [members] [managers] [owners] [depth <Number>]
|
||||
[roles <GroupRoleList>] [members] [managers] [owners]
|
||||
[types <CIGroupMemberTypeList>]
|
||||
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
|
||||
[minimal|basic|full]
|
||||
[(depth <Number>) | includederivedmembership]
|
||||
|
||||
# Cloud Identity Devices
|
||||
|
||||
@@ -4068,6 +4073,7 @@ gam show cigroup-members
|
||||
releaseversion|
|
||||
securitypatchtime|
|
||||
serialnumber|
|
||||
unifieddeviceid|
|
||||
wifimacaddresses
|
||||
<DeviceFieldNameList> ::= "<DeviceFieldName>(,<DeviceFieldName>)*"
|
||||
|
||||
@@ -4469,6 +4475,7 @@ gam report <ActivityApplicationName> [todrive <ToDriveAttribute>*]
|
||||
app_maker|
|
||||
apps_scripts|
|
||||
calendar|
|
||||
chat|
|
||||
classroom|
|
||||
cros|
|
||||
device_management|
|
||||
@@ -4489,6 +4496,7 @@ gam report customers|customer|domain [todrive <ToDriveAttribute>*]
|
||||
|
||||
<UserServiceName> ::=
|
||||
accounts|
|
||||
chat|
|
||||
classroom|
|
||||
docs|
|
||||
drive|
|
||||
@@ -4959,6 +4967,7 @@ gam create|add permissions <SharedDriveEntityAdmin> <DriveFilePermissionEntity>
|
||||
<PermissionMatch>* [<PermissionMatchAction>]
|
||||
gam delete permissions <SharedDriveEntityAdmin> <DriveFilePermissionIDEntity>
|
||||
<PermissionMatch>* [<PermissionMatchAction>]
|
||||
[enforceexpansiveaccess [<Boolean>]]
|
||||
|
||||
In these commands, you specify an administrator and then indicate that you want domain administrator access with the adminaccess option.
|
||||
|
||||
@@ -4972,9 +4981,11 @@ gam <UserTypeEntity> create|add drivefileacl <SharedDriveEntityAdmin>
|
||||
adminaccess
|
||||
gam <UserTypeEntity> update drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail>
|
||||
(role <DriveFileACLRole>) [expires|expiration <Time>] [removeexpiration [<Boolean>]]
|
||||
[enforceexpansiveaccess [<Boolean>]]
|
||||
[showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
|
||||
adminaccess
|
||||
gam <UserTypeEntity> delete drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail>
|
||||
[enforceexpansiveaccess [<Boolean>]]
|
||||
[showtitles] adminaccess
|
||||
gam <UserTypeEntity> info drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail> adminaccess
|
||||
[showtitles]
|
||||
@@ -5000,6 +5011,7 @@ gam <UserTypeEntity> create|add permissions <SharedDriveEntityAdmin> <DriveFileP
|
||||
<PermissionMatch>* [<PermissionMatchAction>]
|
||||
gam <UserTypeEntity> delete permissions <SharedDriveEntityAdmin> <DriveFilePermissionIDEntity> adminaccess
|
||||
<PermissionMatch>* [<PermissionMatchAction>]
|
||||
[enforceexpansiveaccess [<Boolean>]]
|
||||
|
||||
In these commands, the Google administrator named in oauth2.txt is used.
|
||||
|
||||
@@ -6562,6 +6574,7 @@ gam <UserTypeEntity> copy drivefile <DriveFileEntity>
|
||||
[sendemailifrequired [<Boolean>]]
|
||||
[suppressnotselectedmessages [<Boolean>]]
|
||||
[verifyorganizer [<Boolean>]]
|
||||
[enforceexpansiveaccess [<Boolean>]]
|
||||
|
||||
gam <UserTypeEntity> move drivefile <DriveFileEntity> [newfilename <DriveFileName>]
|
||||
[summary [<Boolean>]] [showpermissionmessages [<Boolean>]]
|
||||
@@ -6585,6 +6598,7 @@ gam <UserTypeEntity> move drivefile <DriveFileEntity> [newfilename <DriveFileNam
|
||||
[retainsourcefolders [<Boolean>]]
|
||||
[sendemailifrequired [<Boolean>]]
|
||||
[verifyorganizer [<Boolean>]]
|
||||
[enforceexpansiveaccess [<Boolean>]]
|
||||
|
||||
gam <UserTypeEntity> get document <DriveFileEntity>
|
||||
[viewmode default|suggestions_inline|preview_suggestions_accepted|preview_without_suggestions]
|
||||
@@ -6690,10 +6704,10 @@ gam <UserTypeEntity> create|add drivefileacl <DriveFileEntity> [adminaccess|asad
|
||||
[showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
|
||||
gam <UserTypeEntity> update drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail>
|
||||
(role <DriveFileACLRole>) [expires|expiration <Time>] [removeexpiration [<Boolean>]]
|
||||
[updatesheetprotectedranges [<Boolean>]]
|
||||
[updatesheetprotectedranges [<Boolean>]] [enforceexpansiveaccess [<Boolean>]]
|
||||
[showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
|
||||
gam <UserTypeEntity> delete drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail>
|
||||
[updatesheetprotectedranges [<Boolean>]]
|
||||
[updatesheetprotectedranges [<Boolean>]] [enforceexpansiveaccess [<Boolean>]]
|
||||
[showtitles]
|
||||
gam <UserTypeEntity> info drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail>
|
||||
[showtitles]
|
||||
@@ -6817,6 +6831,7 @@ gam <UserTypeEntity> print filerevisions <DriveFileEntity> [todrive <ToDriveAttr
|
||||
|
||||
gam <UserTypeEntity> transfer ownership <DriveFileEntity> <UserItem>
|
||||
[<DriveFileParentAttribute>] [includetrashed] [norecursion [<Boolean>]]
|
||||
[enforceexpansiveaccess [<Boolean>]]
|
||||
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||
[preview] [filepath] [pathdelimiter <Character>] [buildtree]
|
||||
[todrive <ToDriveAttribute>*]
|
||||
@@ -6825,6 +6840,7 @@ gam <UserTypeEntity> claim ownership <DriveFileEntity>
|
||||
[skipids <DriveFileEntity>] [onlyusers|skipusers <UserTypeEntity>] [subdomains <DomainNameEntity>]
|
||||
[restricted [<Boolean>]] [writerscanshare|writerscantshare [<Boolean>]]
|
||||
[keepuser | (retainrole commenter|reader|writer|editor|fileorganizer|none)] [noretentionmessages]
|
||||
[enforceexpansiveaccess [<Boolean>]]
|
||||
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||
[preview] [filepath] [pathdelimiter <Character>] [buildtree]
|
||||
[todrive <ToDriveAttribute>*]
|
||||
@@ -6832,6 +6848,7 @@ gam <UserTypeEntity> claim ownership <DriveFileEntity>
|
||||
gam <UserTypeEntity> transfer drive <UserItem> [select <DriveFileEntity>]
|
||||
[(targetfolderid <DriveFolderID>)|(targetfoldername <DriveFolderName>)]
|
||||
[targetuserfoldername <DriveFolderName>] [targetuserorphansfoldername <DriveFolderName>]
|
||||
[enforceexpansiveaccess [<Boolean>]]
|
||||
[mergewithtarget [<Boolean>]]
|
||||
[skipids <DriveFileEntity>]
|
||||
[keepuser | (retainrole reader|commenter|writer|editor|fileorganizer|none)] [noretentionmessages]
|
||||
@@ -7878,7 +7895,15 @@ gam <UserTypeEntity> show lookerstudiopermissions
|
||||
<MeetSpaceName> ::= spaces/<String> | <String>
|
||||
<MeetSpaceOptions> ::=
|
||||
accesstype open|trusted|restricted |
|
||||
entrypointaccess all|creatorapponly
|
||||
entrypointaccess all|creatorapponly |
|
||||
moderation <Boolean> |
|
||||
chatrestriction hostsonly|norestriction |
|
||||
reactionrestriction hostsonly|norestriction |
|
||||
presentrestriction hostsonly|norestriction |
|
||||
defaultjoinasviewer <Boolean> |
|
||||
recording <Boolean> |
|
||||
transcription <Boolean> |
|
||||
smartnotes <Boolean>
|
||||
|
||||
gam <UserTypeEntity> create meetspace
|
||||
<MeetSpaceOptions>*
|
||||
|
||||
@@ -1,3 +1,97 @@
|
||||
7.05.02
|
||||
|
||||
Chat usage reports are now available. Added `chat` to `<CustomerServiceName>` and `<UserServiceName>`
|
||||
for use in `gam report customer|user`.
|
||||
|
||||
* https://workspaceupdates.googleblog.com/2025/02/chat-usage-analytics-updates.html
|
||||
|
||||
7.05.01
|
||||
|
||||
Updated from `v1beta1` to `v1` for `Cloud Identity - Policy`.
|
||||
|
||||
* See: https://workspaceupdates.googleblog.com/2025/02/policy-api-general-availability.html
|
||||
|
||||
7.05.00
|
||||
|
||||
Enabled support for Limited Access as described here:
|
||||
* https://workspaceupdates.googleblog.com/2025/02/updating-access-experience-in-google-drive.html
|
||||
|
||||
Note that the rollout may take 15 days.
|
||||
|
||||
Added option `inheritedpermissionsdisabled [<Boolean>]` to `<DriveFileAttribute>`; this
|
||||
attribute can be set on folders.
|
||||
|
||||
Added `inheritedpermissionsdisabled` to `<DriveFieldName>`.
|
||||
|
||||
Added `capabilities.candisableinheritedpermissions` and `capabilities.canenableinheritedpermissions`
|
||||
to `<DriveCapabilitiesSubfieldName>`.
|
||||
|
||||
Added option `enforceexpansiveaccess [<Boolean>]` to all commands that delete or update
|
||||
drive file ACLs/permissions.
|
||||
```
|
||||
gam <UserTypeEntity> delete permissions
|
||||
gam <UserTypeEntity> delete drivefileacl
|
||||
gam <UserTypeEntity> update drivefileacl
|
||||
gam <UserTypeEntity> copy drivefile
|
||||
gam <UserTypeEntity> move drivefile
|
||||
gam <UserTypeEntity> transfer ownership
|
||||
gam <UserTypeEntity> claim ownership
|
||||
gam <UserTypeEntity> transfer drive
|
||||
```
|
||||
|
||||
7.04.05
|
||||
|
||||
Added initial support for Meet API v2beta; you must be in the Developer Preview program
|
||||
for this to be effective.
|
||||
* https://developers.google.com/meet/api/guides/beta/configuration-beta#auto-artifacts
|
||||
|
||||
Added `meet_v2_beta` Boolean variable to `gam.cfg`. When this variable is true,
|
||||
the following options are added to `<MeetSpaceOptions>` used in `gam <UserTypeEntity> create|update meetspace`.
|
||||
```
|
||||
moderation <Boolean> |
|
||||
chatrestriction hostsonly|norestriction |
|
||||
reactionrestriction hostsonly|norestriction |
|
||||
presentrestriction hostsonly|norestriction |
|
||||
defaultjoinasviewer <Boolean> |
|
||||
recording <Boolean> |
|
||||
transcription <Boolean> |
|
||||
smartnotes <Boolean>
|
||||
```
|
||||
|
||||
This isn't called beta for nothing, I have found problems and reported them.
|
||||
|
||||
7.04.04
|
||||
|
||||
Updated `gam print group-members|cigroup-members` to include the `email` column
|
||||
when `fields <MembersFieldNameList>` did not include `email`.
|
||||
|
||||
7.04.03
|
||||
|
||||
Added option `minimal|basic|full` to `gam print cigroup-members`:
|
||||
* `minimal` - Fields displayed: group, id, role, email
|
||||
* `basic` - Fields displayed: group, type, id, role, email
|
||||
* `full` - Fields displayed: group, type, id, role, email, createTime, updateTime; this is the default
|
||||
|
||||
Added option `minimal|basic|full` to `gam show cigroup-members`:
|
||||
* `minimal` - Fields displayed: role, email
|
||||
* `basic` - Fields displayed: type, role, email
|
||||
* `full` - Fields displayed: type, role, email, createTime, updateTime; this is the default
|
||||
|
||||
Upgraded `gam print cigroup-members ... recursive` to display sub-group email addresses rather than IDs.
|
||||
|
||||
7.04.02
|
||||
|
||||
Improved output formatting for the following commands:
|
||||
```
|
||||
gam info peoplecontact
|
||||
gam show peoplecontacts
|
||||
gam info peopleprofile
|
||||
gam show peopleprofile
|
||||
gam <UserTypeEntity> info contacts
|
||||
gam <UserTypeEntity> show contacts
|
||||
gam <UserTypeEntity> show peopleprofile
|
||||
```
|
||||
|
||||
7.04.01
|
||||
|
||||
Fixed bug where multiple `querytime<String>` values in a query were not properly processed;
|
||||
|
||||
@@ -31,6 +31,7 @@ for pkg in GAM_VER_LIBS:
|
||||
datas += [('gam/cbcm-v1.1beta1.json', '.')]
|
||||
datas += [('gam/contactdelegation-v1.json', '.')]
|
||||
datas += [('gam/datastudio-v1.json', '.')]
|
||||
datas += [('gam/meet-v2beta.json', '.')]
|
||||
datas += [('gam/serviceaccountlookup-v1.json', '.')]
|
||||
datas += [('cacerts.pem', '.')]
|
||||
hiddenimports = [
|
||||
|
||||
@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
|
||||
"""
|
||||
|
||||
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
|
||||
__version__ = '7.04.01'
|
||||
__version__ = '7.05.02'
|
||||
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||
|
||||
#pylint: disable=wrong-import-position
|
||||
@@ -4710,7 +4710,7 @@ def getAPIService(api, httpObj):
|
||||
|
||||
def getService(api, httpObj):
|
||||
### Drive v3beta
|
||||
mapDriveURL = api == API.DRIVE3 and GC.Values[GC.DRIVE_V3_BETA]
|
||||
# mapDriveURL = api == API.DRIVE3 and GC.Values[GC.DRIVE_V3_BETA]
|
||||
hasLocalJSON = API.hasLocalJSON(api)
|
||||
api, version, v2discovery = API.getVersion(api)
|
||||
if api in GM.Globals[GM.CURRENT_API_SERVICES] and version in GM.Globals[GM.CURRENT_API_SERVICES][api]:
|
||||
@@ -4727,8 +4727,8 @@ def getService(api, httpObj):
|
||||
GM.Globals[GM.CURRENT_API_SERVICES].setdefault(api, {})
|
||||
GM.Globals[GM.CURRENT_API_SERVICES][api][version] = service._rootDesc.copy()
|
||||
### Drive v3beta
|
||||
if mapDriveURL:
|
||||
setattr(service, '_baseUrl', getattr(service, '_baseUrl').replace('/v3/', '/v3beta/'))
|
||||
# if mapDriveURL:
|
||||
# setattr(service, '_baseUrl', getattr(service, '_baseUrl').replace('/v3/', '/v3beta/'))
|
||||
if GM.Globals[GM.CACHE_DISCOVERY_ONLY]:
|
||||
clearServiceCache(service)
|
||||
return service
|
||||
@@ -5571,6 +5571,8 @@ def buildGAPIServiceObject(api, user, i=0, count=0, displayError=True):
|
||||
userEmail = getSaUser(user)
|
||||
httpObj = getHttpObj(cache=GM.Globals[GM.CACHE_DIR])
|
||||
service = getService(api, httpObj)
|
||||
if api == API.MEET_BETA:
|
||||
api = API.MEET
|
||||
credentials = getSvcAcctCredentials(api, userEmail)
|
||||
request = transportCreateRequest(httpObj)
|
||||
triesLimit = 3
|
||||
@@ -5981,6 +5983,8 @@ def getCIGroupTransitiveMemberRoleFixType(groupName, tmember):
|
||||
member['type'] = Ent.TYPE_USER if not tid.endswith('.iam.gserviceaccount.com') else Ent.TYPE_SERVICE_ACCOUNT
|
||||
elif ttype == 'groups':
|
||||
member['type'] = Ent.TYPE_GROUP
|
||||
elif tid.startswith('cbcm-browser.'):
|
||||
member['type'] = Ent.TYPE_CBCM_BROWSER
|
||||
else:
|
||||
member['type'] = Ent.TYPE_OTHER
|
||||
else:
|
||||
@@ -7322,12 +7326,6 @@ def _getRawFields(requiredField=None):
|
||||
return rawFields
|
||||
return f'{requiredField},{rawFields}'
|
||||
|
||||
def _addInitialField(fieldsList, initialField):
|
||||
if isinstance(initialField, list):
|
||||
fieldsList.extend(initialField)
|
||||
else:
|
||||
fieldsList.append(initialField)
|
||||
|
||||
def CheckInputRowFilterHeaders(titlesList, rowFilter, rowDropFilter):
|
||||
status = True
|
||||
for filterVal in rowFilter:
|
||||
@@ -7742,6 +7740,12 @@ def RowFilterMatch(row, titlesList, rowFilter, rowFilterModeAll, rowDropFilter,
|
||||
# }
|
||||
# fieldsList is the list of API fields
|
||||
def getFieldsList(myarg, fieldsChoiceMap, fieldsList, initialField=None, fieldsArg='fields', onlyFieldsArg=False):
|
||||
def addInitialField():
|
||||
if isinstance(initialField, list):
|
||||
fieldsList.extend(initialField)
|
||||
else:
|
||||
fieldsList.append(initialField)
|
||||
|
||||
def addMappedFields(mappedFields):
|
||||
if isinstance(mappedFields, list):
|
||||
fieldsList.extend(mappedFields)
|
||||
@@ -7750,11 +7754,11 @@ def getFieldsList(myarg, fieldsChoiceMap, fieldsList, initialField=None, fieldsA
|
||||
|
||||
if not onlyFieldsArg and myarg in fieldsChoiceMap:
|
||||
if not fieldsList and initialField is not None:
|
||||
_addInitialField(fieldsList, initialField)
|
||||
addInitialField()
|
||||
addMappedFields(fieldsChoiceMap[myarg])
|
||||
elif myarg == fieldsArg:
|
||||
if not fieldsList and initialField is not None:
|
||||
_addInitialField(fieldsList, initialField)
|
||||
addInitialField()
|
||||
for field in _getFieldsList():
|
||||
if field in fieldsChoiceMap:
|
||||
addMappedFields(fieldsChoiceMap[field])
|
||||
@@ -7931,14 +7935,21 @@ class CSVPrintFile():
|
||||
fieldsList.append(fields)
|
||||
self.AddTitles(fields.replace('.', GC.Values[GC.CSV_OUTPUT_SUBFIELD_DELIMITER]))
|
||||
|
||||
def addInitialField(self, initialField, fieldsChoiceMap, fieldsList):
|
||||
if isinstance(initialField, list):
|
||||
for field in initialField:
|
||||
self.AddField(field, fieldsChoiceMap, fieldsList)
|
||||
else:
|
||||
self.AddField(initialField, fieldsChoiceMap, fieldsList)
|
||||
|
||||
def GetFieldsListTitles(self, fieldName, fieldsChoiceMap, fieldsList, initialField=None):
|
||||
if fieldName in fieldsChoiceMap:
|
||||
if not fieldsList and initialField is not None:
|
||||
_addInitialField(fieldsList, initialField)
|
||||
self.addInitialField(initialField, fieldsChoiceMap, fieldsList)
|
||||
self.AddField(fieldName, fieldsChoiceMap, fieldsList)
|
||||
elif fieldName == 'fields':
|
||||
if not fieldsList and initialField is not None:
|
||||
_addInitialField(fieldsList, initialField)
|
||||
self.addInitialField(initialField, fieldsChoiceMap, fieldsList)
|
||||
for field in _getFieldsList():
|
||||
if field in fieldsChoiceMap:
|
||||
self.AddField(field, fieldsChoiceMap, fieldsList)
|
||||
@@ -9831,7 +9842,7 @@ def MultiprocessGAMCommands(items, showCmds):
|
||||
if GM.Globals[GM.MULTIPROCESS_EXIT_CONDITION] is not None and checkChildProcessRC(result[1]):
|
||||
GM.Globals[GM.MULTIPROCESS_EXIT_PROCESSING] = True
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
def signal_handler(*_):
|
||||
nonlocal controlC
|
||||
controlC = True
|
||||
|
||||
@@ -13098,6 +13109,7 @@ CUSTOMER_REPORT_SERVICES = {
|
||||
'app_maker',
|
||||
'apps_scripts',
|
||||
'calendar',
|
||||
'chat',
|
||||
'classroom',
|
||||
'cros',
|
||||
'device_management',
|
||||
@@ -13111,6 +13123,7 @@ CUSTOMER_REPORT_SERVICES = {
|
||||
|
||||
USER_REPORT_SERVICES = {
|
||||
'accounts',
|
||||
'chat',
|
||||
'classroom',
|
||||
'docs',
|
||||
'drive',
|
||||
@@ -17245,7 +17258,7 @@ def checkOrgUnitPathExists(cd, orgUnitPath, i=0, count=0, showError=False):
|
||||
return (False, orgUnitPath, orgUnitPath)
|
||||
|
||||
def _batchMoveCrOSesToOrgUnit(cd, orgUnitPath, orgUnitId, i, count, items, quickCrOSMove, fromOrgUnitPath=None):
|
||||
def _callbackMoveCrOSesToOrgUnit(request_id, response, exception):
|
||||
def _callbackMoveCrOSesToOrgUnit(request_id, _, exception):
|
||||
ri = request_id.splitlines()
|
||||
if exception is None:
|
||||
if not fromOrgUnitPath:
|
||||
@@ -17326,7 +17339,7 @@ def _batchMoveCrOSesToOrgUnit(cd, orgUnitPath, orgUnitId, i, count, items, quick
|
||||
|
||||
def _batchMoveUsersToOrgUnit(cd, orgUnitPath, i, count, items, fromOrgUnitPath=None):
|
||||
_MOVE_USER_REASON_TO_MESSAGE_MAP = {GAPI.USER_NOT_FOUND: Msg.DOES_NOT_EXIST, GAPI.DOMAIN_NOT_FOUND: Msg.SERVICE_NOT_APPLICABLE, GAPI.FORBIDDEN: Msg.SERVICE_NOT_APPLICABLE}
|
||||
def _callbackMoveUsersToOrgUnit(request_id, response, exception):
|
||||
def _callbackMoveUsersToOrgUnit(request_id, _, exception):
|
||||
ri = request_id.splitlines()
|
||||
if exception is None:
|
||||
if not fromOrgUnitPath:
|
||||
@@ -21864,12 +21877,29 @@ def _printPerson(entityTypeName, user, person, csvPF, FJQC, parameters):
|
||||
'JSON': json.dumps(cleanJSON(person),
|
||||
ensure_ascii=False, sort_keys=True)})
|
||||
|
||||
PEOPLE_CONTACT_OBJECT_KEYS = {
|
||||
'addresses': 'type',
|
||||
'calendarUrls': 'type',
|
||||
'emailAddresses': 'type',
|
||||
'events': 'type',
|
||||
'externalIds': 'type',
|
||||
'genders': 'value',
|
||||
'imClients': 'type',
|
||||
'locations': 'type',
|
||||
'miscKeywords': 'type',
|
||||
'nicknames': 'type',
|
||||
'organizations': 'type',
|
||||
'relations': 'type',
|
||||
'urls': 'type',
|
||||
'userDefined': 'key',
|
||||
}
|
||||
|
||||
def _showPerson(userEntityType, user, entityType, person, i, count, FJQC, parameters):
|
||||
_processPersonMetadata(person, parameters)
|
||||
if not FJQC.formatJSON:
|
||||
printEntity([userEntityType, user, entityType, person['resourceName']], i, count)
|
||||
Ind.Increment()
|
||||
showJSON(None, person)
|
||||
showJSON(None, person, dictObjectsKey=PEOPLE_CONTACT_OBJECT_KEYS)
|
||||
Ind.Decrement()
|
||||
else:
|
||||
printLine(json.dumps(cleanJSON(person), ensure_ascii=False, sort_keys=True))
|
||||
@@ -27462,6 +27492,8 @@ def printShowChatEvents(users):
|
||||
csvPF.writeCSVfile('Chat Events')
|
||||
|
||||
def buildMeetServiceObject(api=API.MEET, user=None, i=0, count=0, entityTypeList=None):
|
||||
if GC.Values[GC.MEET_V2_BETA]:
|
||||
api = API.MEET_BETA
|
||||
user, meet = buildGAPIServiceObject(api, user, i, count)
|
||||
kvList = [Ent.USER, user]
|
||||
if entityTypeList is not None:
|
||||
@@ -27485,7 +27517,10 @@ MEET_SPACE_OPTIONS_MAP = {
|
||||
'reactionrestriction': 'reactionRestriction',
|
||||
'presentrestriction': 'presentRestriction',
|
||||
'defaultjoinasviewer': 'defaultJoinAsViewerType',
|
||||
'firstjoiner': 'firstJoinerType'
|
||||
'firstjoiner': 'firstJoinerType',
|
||||
'autorecording': 'recordingConfig',
|
||||
'autosmartnotes': 'smartNotesConfig',
|
||||
'autotranscription': 'transcriptionConfig',
|
||||
}
|
||||
|
||||
MEET_SPACE_ACCESSTYPE_CHOICES = {'open', 'trusted', 'restricted'}
|
||||
@@ -27499,9 +27534,15 @@ MEET_SPACE_RESTRICTIONS_CHOICES_MAP = {
|
||||
'norestriction': 'NO_RESTRICTION'
|
||||
}
|
||||
|
||||
MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP = {
|
||||
'hostsonly': 'HOSTS_ONLY',
|
||||
'anyone': 'ANYONE'
|
||||
#MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP = {
|
||||
# 'hostsonly': 'HOSTS_ONLY',
|
||||
# 'anyone': 'ANYONE'
|
||||
# }
|
||||
|
||||
MEET_SPACE_ARTIFACT_SUB_OPTIONS = {
|
||||
'recordingConfig': 'autoRecordingGeneration',
|
||||
'smartNotesConfig': 'autoSmartNotesGeneration',
|
||||
'transcriptionConfig': 'autoTranscriptionGeneration'
|
||||
}
|
||||
|
||||
# [accesstype open|trusted|restricted]
|
||||
@@ -27512,7 +27553,10 @@ MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP = {
|
||||
# [presentrestriction hostsonly|norestriction]
|
||||
# [defaultjoinasviewer <Boolean>]
|
||||
# [firstjoiner hostsonly|anyone]
|
||||
def _getMeetSpaceParameters(myarg, body, updateMask):
|
||||
# [autorecording <Boolean>]
|
||||
# [autosmartnotes <Boolean>]
|
||||
# [autotranscription <Boolean>]
|
||||
def _getMeetSpaceParameters(myarg, body):
|
||||
option = MEET_SPACE_OPTIONS_MAP.get(myarg, None)
|
||||
if option is None:
|
||||
return False
|
||||
@@ -27522,15 +27566,17 @@ def _getMeetSpaceParameters(myarg, body, updateMask):
|
||||
body['config'][option] = getChoice(MEET_SPACE_ENTRYPOINTACCESS_CHOICES_MAP, mapChoice=True)
|
||||
elif option == 'moderation':
|
||||
body['config'][option] = 'ON' if getBoolean() else 'OFF'
|
||||
elif option in {'chatrestriction', 'reactionrestriction', 'presentrestriction'}:
|
||||
body['config'].setdefault('moderationRestictions', {})
|
||||
elif option in {'chatRestriction', 'reactionRestriction', 'presentRestriction'}:
|
||||
body['config'].setdefault('moderationRestrictions', {})
|
||||
body['config']['moderationRestrictions'][option] = getChoice(MEET_SPACE_RESTRICTIONS_CHOICES_MAP, mapChoice=True)
|
||||
option = f'moderationRestrictions.{option}'
|
||||
elif option == 'defaultJoinAsViewerType':
|
||||
body['config'][option] = 'ON' if getBoolean() else 'OFF'
|
||||
elif option == 'firstJoinerType':
|
||||
body['config'][option] = getChoice(MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP, mapChoice=True)
|
||||
updateMask.append(f'config.{option}')
|
||||
# elif option == 'firstJoinerType':
|
||||
# body['config'][option] = getChoice(MEET_SPACE_FIRSTJOINERTYPE_CHOICES_MAP, mapChoice=True)
|
||||
elif option in {'recordingConfig', 'transcriptionConfig', 'smartNotesConfig'}:
|
||||
body['config'].setdefault('artifactConfig', {})
|
||||
body['config']['artifactConfig'].setdefault(option, {})
|
||||
body['config']['artifactConfig'][option][MEET_SPACE_ARTIFACT_SUB_OPTIONS[option]] = 'ON' if getBoolean() else 'OFF'
|
||||
return True
|
||||
|
||||
# gam <UserTypeEntity> create meetspace
|
||||
@@ -27545,10 +27591,9 @@ def createMeetSpace(users):
|
||||
# 'firstJoinerType': 'ANYONE',
|
||||
}}
|
||||
returnIdOnly = False
|
||||
updateMask = []
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
if _getMeetSpaceParameters(myarg, body, updateMask):
|
||||
if _getMeetSpaceParameters(myarg, body):
|
||||
pass
|
||||
elif myarg == 'returnidonly':
|
||||
returnIdOnly = True
|
||||
@@ -27583,12 +27628,11 @@ def updateMeetSpace(users):
|
||||
FJQC = FormatJSONQuoteChar()
|
||||
name = None
|
||||
body = {'config': {}}
|
||||
updateMask = []
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
if (myarg == 'space' or myarg.startswith('spaces/') or myarg.startswith('space/')):
|
||||
name = getSpaceName(myarg)
|
||||
elif _getMeetSpaceParameters(myarg, body, updateMask):
|
||||
elif _getMeetSpaceParameters(myarg, body):
|
||||
pass
|
||||
else:
|
||||
FJQC.GetFormatJSON(myarg)
|
||||
@@ -27603,7 +27647,7 @@ def updateMeetSpace(users):
|
||||
try:
|
||||
space = callGAPI(meet.spaces(), 'patch',
|
||||
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
|
||||
name=name, updateMask=','.join(updateMask), body=body)
|
||||
name=name, updateMask='', body=body)
|
||||
if not FJQC.formatJSON:
|
||||
entityActionPerformed(kvList, i, count)
|
||||
Ind.Increment()
|
||||
@@ -29209,6 +29253,7 @@ DEVICE_FIELDS_CHOICE_MAP = {
|
||||
'releaseversion': 'releaseVersion',
|
||||
'securitypatchtime': 'securityPatchTime',
|
||||
'serialnumber': 'serialNumber',
|
||||
'unifieddeviceid': 'unifiedDeviceId',
|
||||
'wifimacaddresses': 'wifiMacAddresses'
|
||||
}
|
||||
|
||||
@@ -31981,7 +32026,7 @@ def doUpdateGroups():
|
||||
GAPI.INVALID_MEMBER: Msg.INVALID_MEMBER,
|
||||
GAPI.CYCLIC_MEMBERSHIPS_NOT_ALLOWED: Msg.WOULD_MAKE_MEMBERSHIP_CYCLE}
|
||||
|
||||
def _callbackAddGroupMembers(request_id, response, exception):
|
||||
def _callbackAddGroupMembers(request_id, _, exception):
|
||||
ri = request_id.splitlines()
|
||||
if exception is None:
|
||||
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
||||
@@ -32070,7 +32115,7 @@ def doUpdateGroups():
|
||||
GAPI.CONDITION_NOT_MET: f'{Msg.NOT_A} {Ent.Singular(Ent.MEMBER)}',
|
||||
GAPI.INVALID_MEMBER: Msg.DOES_NOT_EXIST}
|
||||
|
||||
def _callbackRemoveGroupMembers(request_id, response, exception):
|
||||
def _callbackRemoveGroupMembers(request_id, _, exception):
|
||||
ri = request_id.splitlines()
|
||||
if exception is None:
|
||||
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], DELIVERY_SETTINGS_UNDEFINED, int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
||||
@@ -32169,7 +32214,7 @@ def doUpdateGroups():
|
||||
except (GAPI.invalidMember, GAPI.resourceNotFound, GAPI.serviceNotAvailable) as e:
|
||||
_showFailure(group, member, role, str(e), j, jcount)
|
||||
|
||||
def _callbackUpdateGroupMembers(request_id, response, exception):
|
||||
def _callbackUpdateGroupMembers(request_id, _, exception):
|
||||
ri = request_id.splitlines()
|
||||
if exception is None:
|
||||
_showSuccess(ri[RI_ENTITY], ri[RI_ITEM], ri[RI_ROLE], ri[RI_OPTION], int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
||||
@@ -33406,6 +33451,7 @@ PRINT_GROUPS_JSON_TITLES = ['email', 'JSON']
|
||||
|
||||
# gam print groups [todrive <ToDriveAttribute>*]
|
||||
# [([domain|domains <DomainNameEntity>] ([member|showownedby <EmailItem>]|[(query <QueryGroup>)|(queries <QueryUserList>)]))|
|
||||
# (group|group_ns|group_susp <GroupItem>)|
|
||||
# (select <GroupEntity>)]
|
||||
# [emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
|
||||
# [descriptionmatchpattern [not] <RegularExpression>] (matchsetting [not] <GroupAttribute>)*
|
||||
@@ -33618,6 +33664,12 @@ def doPrintGroups():
|
||||
pass
|
||||
elif getGroupMatchPatterns(myarg, matchPatterns, False):
|
||||
pass
|
||||
elif myarg in {'group', 'groupns', 'groupsusp'}:
|
||||
entitySelection = [getString(Cmd.OB_EMAIL_ADDRESS)]
|
||||
if myarg == 'groupns':
|
||||
isSuspended = False
|
||||
elif myarg == 'groupsusp':
|
||||
isSuspended = True
|
||||
elif myarg == 'select':
|
||||
entitySelection = getEntityList(Cmd.OB_GROUP_ENTITY)
|
||||
elif myarg in SUSPENDED_ARGUMENTS:
|
||||
@@ -33942,6 +33994,8 @@ def infoGroupMembers(entityList, ciGroupsAPI=False):
|
||||
printKeyValueList(['type', result['type']])
|
||||
for field in ['createTime', 'updateTime']:
|
||||
printKeyValueList([field, formatLocalTime(result[field])])
|
||||
if 'deliverySetting' in result:
|
||||
printKeyValueList(['deliverySetting', result['deliverySetting']])
|
||||
Ind.Decrement()
|
||||
except (GAPI.groupNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.invalid, GAPI.forbidden) as e:
|
||||
entityActionFailedWarning([entityType, groupKey], str(e), j, jcount)
|
||||
@@ -34185,7 +34239,7 @@ def doPrintGroupMembers():
|
||||
pass
|
||||
elif getMemberMatchOptions(myarg, memberOptions):
|
||||
pass
|
||||
elif csvPF.GetFieldsListTitles(myarg, GROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList):
|
||||
elif csvPF.GetFieldsListTitles(myarg, GROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList, initialField='email'):
|
||||
pass
|
||||
elif myarg == 'membernames':
|
||||
memberOptions[MEMBEROPTION_MEMBERNAMES] = True
|
||||
@@ -36104,8 +36158,9 @@ def getCIGroupTransitiveMembers(ci, groupName, membersList, i, count):
|
||||
return True
|
||||
|
||||
def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, count,
|
||||
memberOptions, memberDisplayOptions, level, typesSet):
|
||||
printGettingAllEntityItemsForWhom(memberRoles if memberRoles else Ent.ROLE_MANAGER_MEMBER_OWNER, groupName, i, count)
|
||||
memberOptions, memberDisplayOptions, level, typesSet, groupEmail, kwargs):
|
||||
nameToPrint = groupEmail if groupEmail else groupName
|
||||
printGettingAllEntityItemsForWhom(memberRoles if memberRoles else Ent.ROLE_MANAGER_MEMBER_OWNER, nameToPrint, i, count)
|
||||
validRoles = _getCIRoleVerification(memberRoles)
|
||||
if memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP]:
|
||||
groupMembers = []
|
||||
@@ -36120,12 +36175,11 @@ def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, co
|
||||
groupMembers = callGAPIpages(ci.groups().memberships(), 'list', 'memberships',
|
||||
pageMessage=getPageMessageForWhom(),
|
||||
throwReasons=GAPI.CIGROUP_LIST_THROW_REASONS, retryReasons=GAPI.CIGROUP_RETRY_REASONS,
|
||||
parent=groupName, view='FULL',
|
||||
fields='nextPageToken,memberships(*)', pageSize=GC.Values[GC.MEMBER_MAX_RESULTS])
|
||||
parent=groupName, **kwargs)
|
||||
except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis,
|
||||
GAPI.forbidden, GAPI.badRequest, GAPI.invalid, GAPI.invalidArgument, GAPI.systemError,
|
||||
GAPI.permissionDenied, GAPI.serviceNotAvailable):
|
||||
entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, groupName, i, count)
|
||||
entityUnknownWarning(Ent.CLOUD_IDENTITY_GROUP, nameToPrint, i, count)
|
||||
return
|
||||
checkCategory = memberDisplayOptions['showCategory']
|
||||
if not memberOptions[MEMBEROPTION_RECURSIVE]:
|
||||
@@ -36159,7 +36213,7 @@ def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, co
|
||||
memberName not in membersSet):
|
||||
membersSet.add(memberName)
|
||||
member['level'] = level
|
||||
member['subgroup'] = groupName
|
||||
member['subgroup'] = nameToPrint
|
||||
membersList.append(member)
|
||||
else:
|
||||
if memberName not in membersSet:
|
||||
@@ -36168,37 +36222,41 @@ def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, co
|
||||
checkCIMemberMatch(member, memberOptions) and
|
||||
(not checkCategory or _checkCIMemberCategory(member, memberDisplayOptions))):
|
||||
member['level'] = level
|
||||
member['subgroup'] = groupName
|
||||
member['subgroup'] = nameToPrint
|
||||
membersList.append(member)
|
||||
_, gname = member['name'].rsplit('/', 1)
|
||||
groupMemberList.append(f'groups/{gname}')
|
||||
groupMemberList.append((f'groups/{gname}', memberName))
|
||||
for member in groupMemberList:
|
||||
getCIGroupMembers(ci, member, memberRoles, membersList, membersSet, i, count,
|
||||
memberOptions, memberDisplayOptions, level+1, typesSet)
|
||||
getCIGroupMembers(ci, member[0], memberRoles, membersList, membersSet, i, count,
|
||||
memberOptions, memberDisplayOptions, level+1, typesSet, member[1], kwargs)
|
||||
else:
|
||||
for member in groupMembers:
|
||||
getCIGroupMemberRoleFixType(member)
|
||||
memberName = member.get('preferredMemberKey', {}).get('id', '')
|
||||
if member['type'] != Ent.TYPE_GROUP:
|
||||
if (member['type'] in typesSet and
|
||||
checkCIMemberMatch(member, memberOptions) and
|
||||
_checkMemberRole(member, validRoles) and
|
||||
(not checkCategory or _checkCIMemberCategory(member, memberDisplayOptions))):
|
||||
member['level'] = level
|
||||
member['subgroup'] = groupName
|
||||
member['subgroup'] = nameToPrint
|
||||
membersList.append(member)
|
||||
else:
|
||||
if (member['type'] in typesSet and
|
||||
checkCIMemberMatch(member, memberOptions) and
|
||||
(not checkCategory or _checkCIMemberCategory(member, memberDisplayOptions))):
|
||||
member['level'] = level
|
||||
member['subgroup'] = groupName
|
||||
member['subgroup'] = nameToPrint
|
||||
membersList.append(member)
|
||||
_, gname = member['name'].rsplit('/', 1)
|
||||
getCIGroupMembers(ci, f'groups/{gname}', memberRoles, membersList, membersSet, i, count,
|
||||
memberOptions, memberDisplayOptions, level+1, typesSet)
|
||||
memberOptions, memberDisplayOptions, level+1, typesSet, memberName, kwargs)
|
||||
|
||||
CIGROUPMEMBERS_FIELDS_CHOICE_MAP = {
|
||||
'createtime': 'createTime',
|
||||
'delivery': 'deliverySetting',
|
||||
'deliverysettings': 'deliverySetting',
|
||||
'email': 'preferredMemberKey',
|
||||
'expiretime': 'expireTime',
|
||||
'id': 'name',
|
||||
'memberkey': 'preferredMemberKey',
|
||||
@@ -36219,6 +36277,16 @@ CIGROUPMEMBERS_SORT_FIELDS = [
|
||||
]
|
||||
CIGROUPMEMBERS_TIME_OBJECTS = {'createTime', 'updateTime', 'expireTime'}
|
||||
|
||||
def _getCIListGroupMembersArgs(listView):
|
||||
if listView == 'full':
|
||||
return {'view': 'FULL', 'pageSize': GC.Values[GC.MEMBER_MAX_RESULTS_CI_FULL],
|
||||
'fields': 'nextPageToken,memberships(*)'}
|
||||
if listView == 'basic':
|
||||
return {'view': 'FULL', 'pageSize': GC.Values[GC.MEMBER_MAX_RESULTS_CI_FULL],
|
||||
'fields': 'nextPageToken,memberships(name,preferredMemberKey,roles,type)'}
|
||||
return {'view': 'BASIC', 'pageSize': GC.Values[GC.MEMBER_MAX_RESULTS_CI_BASIC],
|
||||
'fields': 'nextPageToken,memberships(*)'}
|
||||
|
||||
# gam print cigroup-members [todrive <ToDriveAttribute>*]
|
||||
# [(cimember|ciowner <UserItem>)|(cigroup <GroupItem>)|(select <GroupEntity>)]
|
||||
# [showownedby <UserItem>]
|
||||
@@ -36228,6 +36296,7 @@ CIGROUPMEMBERS_TIME_OBJECTS = {'createTime', 'updateTime', 'expireTime'}
|
||||
# [types <CIGroupMemberTypeList>]
|
||||
# [memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
|
||||
# <CIGroupMembersFieldName>* [fields <CIGroupMembersFieldNameList>]
|
||||
# [minimal|basic|full]
|
||||
# [(recursive [noduplicates])|includederivedmembership] [nogroupeemail]
|
||||
# [formatjson [quotechar <Character>]]
|
||||
def doPrintCIGroupMembers():
|
||||
@@ -36245,6 +36314,7 @@ def doPrintCIGroupMembers():
|
||||
rolesSet = set()
|
||||
typesSet = set()
|
||||
matchPatterns = {}
|
||||
listView = 'full'
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
if myarg == 'todrive':
|
||||
@@ -36273,7 +36343,7 @@ def doPrintCIGroupMembers():
|
||||
pass
|
||||
elif getMemberMatchOptions(myarg, memberOptions):
|
||||
pass
|
||||
elif getFieldsList(myarg, CIGROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList):
|
||||
elif getFieldsList(myarg, CIGROUPMEMBERS_FIELDS_CHOICE_MAP, fieldsList, initialField='preferredMemberKey'):
|
||||
pass
|
||||
elif myarg == 'noduplicates':
|
||||
memberOptions[MEMBEROPTION_NODUPLICATES] = True
|
||||
@@ -36285,8 +36355,12 @@ def doPrintCIGroupMembers():
|
||||
memberOptions[MEMBEROPTION_RECURSIVE] = False
|
||||
elif myarg == 'nogroupemail':
|
||||
groupColumn = False
|
||||
elif myarg in {'minimal', 'basic', 'full'}:
|
||||
listView = myarg
|
||||
else:
|
||||
FJQC.GetFormatJSONQuoteChar(myarg, False)
|
||||
if listView == 'minimal' and memberOptions[MEMBEROPTION_RECURSIVE]:
|
||||
usageErrorExit(Msg.ARE_MUTUALLY_EXCLUSIVE.format('minimal', 'recursive'))
|
||||
if not typesSet:
|
||||
typesSet = {Ent.TYPE_USER} if memberOptions[MEMBEROPTION_RECURSIVE] else ALL_CIGROUP_MEMBER_TYPES
|
||||
fields = ','.join(set(groupFieldsLists['ci']))
|
||||
@@ -36313,6 +36387,7 @@ def doPrintCIGroupMembers():
|
||||
if showOwnedBy:
|
||||
getRolesSet.add(Ent.ROLE_OWNER)
|
||||
getRoles = ','.join(sorted(getRolesSet))
|
||||
kwargs = _getCIListGroupMembersArgs(listView)
|
||||
level = 0
|
||||
i = 0
|
||||
count = len(entityList)
|
||||
@@ -36339,7 +36414,7 @@ def doPrintCIGroupMembers():
|
||||
membersList = []
|
||||
membersSet = set()
|
||||
getCIGroupMembers(ci, groupEntity['name'], getRoles, membersList, membersSet, i, count,
|
||||
memberOptions, memberDisplayOptions, level, typesSet)
|
||||
memberOptions, memberDisplayOptions, level, typesSet, groupEmail, kwargs)
|
||||
if showOwnedBy and not checkCIGroupShowOwnedBy(showOwnedBy, membersList):
|
||||
continue
|
||||
for member in membersList:
|
||||
@@ -36357,6 +36432,8 @@ def doPrintCIGroupMembers():
|
||||
row['subgroup'] = member['subgroup']
|
||||
if memberDisplayOptions['showCategory']:
|
||||
row['category'] = member['category']
|
||||
if listView == 'minimal':
|
||||
dmember.pop('type', None)
|
||||
mapCIGroupMemberFieldNames(dmember)
|
||||
if not FJQC.formatJSON:
|
||||
csvPF.WriteRowTitles(flattenJSON(dmember, flattened=row, timeObjects=CIGROUPMEMBERS_TIME_OBJECTS))
|
||||
@@ -36386,17 +36463,19 @@ def doPrintCIGroupMembers():
|
||||
# [showownedby <UserItem>]
|
||||
# [emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
|
||||
# [descriptionmatchpattern [not] <RegularExpression>]
|
||||
# [roles <GroupRoleList>] [members] [managers] [owners] [depth <Number>]
|
||||
# [roles <GroupRoleList>] [members] [managers] [owners]
|
||||
# [internal] [internaldomains <DomainList>] [external]
|
||||
# [types <CIGroupMemberTypeList>]
|
||||
# [memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
|
||||
# [includederivedmembership]
|
||||
# [minimal|basic|full]
|
||||
# [(depth <Number>) | includederivedmembership]
|
||||
def doShowCIGroupMembers():
|
||||
def _roleOrder(key):
|
||||
return {Ent.ROLE_OWNER: 0, Ent.ROLE_MANAGER: 1, Ent.ROLE_MEMBER: 2}.get(key, 3)
|
||||
|
||||
def _typeOrder(key):
|
||||
return {Ent.TYPE_CUSTOMER: 0, Ent.TYPE_USER: 1, Ent.TYPE_GROUP: 2, Ent.TYPE_EXTERNAL: 3}.get(key, 4)
|
||||
return {Ent.TYPE_CUSTOMER: 0, Ent.TYPE_USER: 1, Ent.TYPE_GROUP: 2,
|
||||
Ent.TYPE_CBCM_BROWSER: 3, Ent.TYPE_OTHER: 4, Ent.TYPE_EXTERNAL: 5}.get(key, 6)
|
||||
|
||||
def _showGroup(groupName, groupEmail, depth):
|
||||
if includeDerivedMembership:
|
||||
@@ -36407,8 +36486,7 @@ def doShowCIGroupMembers():
|
||||
try:
|
||||
membersList = callGAPIpages(ci.groups().memberships(), 'list', 'memberships',
|
||||
throwReasons=GAPI.CIGROUP_LIST_THROW_REASONS, retryReasons=GAPI.CIGROUP_RETRY_REASONS,
|
||||
parent=groupName, view='FULL',
|
||||
fields='nextPageToken,memberships(*)', pageSize=GC.Values[GC.MEMBER_MAX_RESULTS])
|
||||
parent=groupName, **kwargs)
|
||||
for member in membersList:
|
||||
getCIGroupMemberRoleFixType(member)
|
||||
except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis,
|
||||
@@ -36429,7 +36507,10 @@ def doShowCIGroupMembers():
|
||||
if (_checkMemberRole(member, rolesSet) and
|
||||
member['type'] in typesSet and
|
||||
checkCIMemberMatch(member, memberOptions)):
|
||||
memberDetails = f'{member.get("role", Ent.ROLE_MEMBER)}, {member["type"]}, {member["preferredMemberKey"]["id"]}'
|
||||
if listView != 'minimal':
|
||||
memberDetails = f'{member.get("role", Ent.ROLE_MEMBER)}, {member["type"]}, {member["preferredMemberKey"]["id"]}'
|
||||
else:
|
||||
memberDetails = f'{member.get("role", Ent.ROLE_MEMBER)}, {member["preferredMemberKey"]["id"]}'
|
||||
if checkCategory:
|
||||
memberDetails += f', {member["category"]}'
|
||||
for field in ['createTime', 'updateTime', 'expireTime']:
|
||||
@@ -36454,6 +36535,7 @@ def doShowCIGroupMembers():
|
||||
matchPatterns = {}
|
||||
maxdepth = -1
|
||||
includeDerivedMembership = False
|
||||
listView = 'full'
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
if myarg == 'showownedby':
|
||||
@@ -36484,6 +36566,8 @@ def doShowCIGroupMembers():
|
||||
maxdepth = getInteger(minVal=-1)
|
||||
elif myarg == 'includederivedmembership':
|
||||
includeDerivedMembership = True
|
||||
elif myarg in {'minimal', 'basic', 'full'}:
|
||||
listView = myarg
|
||||
else:
|
||||
unknownArgumentExit()
|
||||
if not rolesSet:
|
||||
@@ -36493,6 +36577,7 @@ def doShowCIGroupMembers():
|
||||
checkCategory = memberDisplayOptions['showCategory']
|
||||
fields = ','.join(set(groupFieldsLists['ci']))
|
||||
entityList = getCIGroupMembersEntityList(ci, entityList, query, subTitle, matchPatterns, groupFieldsLists['ci'], None)
|
||||
kwargs = _getCIListGroupMembersArgs(listView)
|
||||
i = 0
|
||||
count = len(entityList)
|
||||
for group in entityList:
|
||||
@@ -42272,7 +42357,7 @@ def doPrintVaultCounts():
|
||||
# gam [<UserTypeEntity>] print siteacls <SiteEntity> [todrive <ToDriveAttribute>*]
|
||||
# gam [<UserTypeEntity>] print siteactivity <SiteEntity> [todrive <ToDriveAttribute>*]
|
||||
# [startindex <Number>] [maxresults <Number>] [updated_min <Date>] [updated_max <Date>]
|
||||
def deprecatedUserSites(users):
|
||||
def deprecatedUserSites(_):
|
||||
deprecatedCommandExit()
|
||||
|
||||
def deprecatedDomainSites():
|
||||
@@ -43594,7 +43679,7 @@ def waitForMailbox(entityList):
|
||||
Ind.Decrement()
|
||||
|
||||
def getUserLicenses(lic, user, skus):
|
||||
def _callbackGetLicense(request_id, response, exception):
|
||||
def _callbackGetLicense(_, response, exception):
|
||||
if exception is None:
|
||||
if response and 'skuId' in response:
|
||||
licenses.append(response['skuId'])
|
||||
@@ -48100,7 +48185,7 @@ def _batchAddItemsToCourse(croom, courseId, i, count, addParticipants, role):
|
||||
_ADD_PART_REASON_TO_MESSAGE_MAP = {GAPI.NOT_FOUND: Msg.DOES_NOT_EXIST,
|
||||
GAPI.ALREADY_EXISTS: Msg.DUPLICATE,
|
||||
GAPI.FAILED_PRECONDITION: Msg.NOT_ALLOWED}
|
||||
def _callbackAddItemsToCourse(request_id, response, exception):
|
||||
def _callbackAddItemsToCourse(request_id, _, exception):
|
||||
ri = request_id.splitlines()
|
||||
if exception is None:
|
||||
entityActionPerformed([Ent.COURSE, ri[RI_ENTITY], ri[RI_ROLE], ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
||||
@@ -48180,7 +48265,7 @@ def _batchRemoveItemsFromCourse(croom, courseId, i, count, removeParticipants, r
|
||||
_REMOVE_PART_REASON_TO_MESSAGE_MAP = {GAPI.NOT_FOUND: Msg.DOES_NOT_EXIST,
|
||||
GAPI.FORBIDDEN: Msg.FORBIDDEN,
|
||||
GAPI.PERMISSION_DENIED: Msg.PERMISSION_DENIED}
|
||||
def _callbackRemoveItemsFromCourse(request_id, response, exception):
|
||||
def _callbackRemoveItemsFromCourse(request_id, _, exception):
|
||||
ri = request_id.splitlines()
|
||||
if exception is None:
|
||||
entityActionPerformed([Ent.COURSE, ri[RI_ENTITY], ri[RI_ROLE], ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
||||
@@ -48392,7 +48477,7 @@ def doCourseRemoveItems(courseIdList, getEntityListArg):
|
||||
|
||||
# gam courses <CourseEntity> clear teachers|students
|
||||
# gam course <CourseID> clear teacher|student
|
||||
def doCourseClearParticipants(courseIdList, getEntityListArg):
|
||||
def doCourseClearParticipants(courseIdList, _):
|
||||
croom = buildGAPIObject(API.CLASSROOM)
|
||||
role = getChoice(CLEAR_SYNC_PARTICIPANT_TYPES_MAP, mapChoice=True)
|
||||
checkForExtraneousArguments()
|
||||
@@ -48408,7 +48493,7 @@ def doCourseClearParticipants(courseIdList, getEntityListArg):
|
||||
# gam course <CourseID> sync students [addonly|removeonly] <UserTypeEntity>
|
||||
# gam courses <CourseEntity> sync teachers [addonly|removeonly] [makefirstteacherowner] <UserTypeEntity>
|
||||
# gam course <CourseID> sync teachers [addonly|removeonly] [makefirstteacherowner] <UserTypeEntity>
|
||||
def doCourseSyncParticipants(courseIdList, getEntityListArg):
|
||||
def doCourseSyncParticipants(courseIdList, _):
|
||||
croom = buildGAPIObject(API.CLASSROOM)
|
||||
role = getChoice(CLEAR_SYNC_PARTICIPANT_TYPES_MAP, mapChoice=True)
|
||||
if role == Ent.TEACHER:
|
||||
@@ -58144,6 +58229,7 @@ def initCopyMoveOptions(copyCmd):
|
||||
'showPermissionMessages': False,
|
||||
'sendEmailIfRequired': False,
|
||||
'useDomainAdminAccess': False,
|
||||
'enforceExpansiveAccess': False,
|
||||
'copiedShortcutsPointToCopiedFiles': True,
|
||||
'createShortcutsForNonmovableFiles': False,
|
||||
'duplicateFiles': DUPLICATE_FILE_OVERWRITE_OLDER,
|
||||
@@ -58242,6 +58328,8 @@ def getCopyMoveOptions(myarg, copyMoveOptions):
|
||||
elif myarg == 'mappermissionsdomain':
|
||||
oldDomain = getString(Cmd.OB_DOMAIN_NAME).lower()
|
||||
copyMoveOptions['mapPermissionsDomains'][oldDomain] = getString(Cmd.OB_DOMAIN_NAME).lower()
|
||||
elif myarg == 'enforceexpansiveaccess':
|
||||
copyMoveOptions['enforceExpansiveAccess'] = getBoolean()
|
||||
else:
|
||||
# Move arguments
|
||||
if not copyMoveOptions['copyCmd']:
|
||||
@@ -58513,6 +58601,9 @@ def _copyPermissions(drive, user, i, count, j, jcount,
|
||||
updateTargetPerms[permissionId].update(updatePerm)
|
||||
updateTargetPerms[permissionId]['updates'] = updatePerm
|
||||
copySourcePerms.pop(permissionId)
|
||||
deleteUpdateKwargs = {'useDomainAdminAccess': copyMoveOptions['useDomainAdminAccess']}
|
||||
if entityType != Ent.SHAREDDRIVE:
|
||||
deleteUpdateKwargs['enforceExpansiveAccess'] = copyMoveOptions['enforceExpansiveAccess']
|
||||
Ind.Increment()
|
||||
action = Act.Get()
|
||||
Act.Set(Act.COPY)
|
||||
@@ -58531,8 +58622,9 @@ def _copyPermissions(drive, user, i, count, j, jcount,
|
||||
callGAPI(drive.permissions(), 'create',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_CREATE_ACL_THROW_REASONS,
|
||||
# retryReasons=[GAPI.INVALID_SHARING_REQUEST],
|
||||
useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'],
|
||||
fileId=newFileId, sendNotificationEmail=sendNotificationEmail, emailMessage=None,
|
||||
body=permission, fields='', useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'], supportsAllDrives=True)
|
||||
body=permission, fields='', supportsAllDrives=True)
|
||||
if copyMoveOptions['showPermissionMessages']:
|
||||
entityActionPerformed(kvList, k, kcount)
|
||||
break
|
||||
@@ -58570,7 +58662,8 @@ def _copyPermissions(drive, user, i, count, j, jcount,
|
||||
try:
|
||||
callGAPI(drive.permissions(), 'delete',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
|
||||
fileId=newFileId, permissionId=permissionId, useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'], supportsAllDrives=True)
|
||||
**deleteUpdateKwargs,
|
||||
fileId=newFileId, permissionId=permissionId, supportsAllDrives=True)
|
||||
if copyMoveOptions['showPermissionMessages']:
|
||||
entityActionPerformed(kvList, k, kcount)
|
||||
except (GAPI.notFound, GAPI.permissionNotFound,
|
||||
@@ -58595,8 +58688,9 @@ def _copyPermissions(drive, user, i, count, j, jcount,
|
||||
callGAPI(drive.permissions(), 'update',
|
||||
bailOnInternalError=True,
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_UPDATE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
|
||||
fileId=newFileId, permissionId=permissionId, removeExpiration=removeExpiration,
|
||||
body=permission['updates'], useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'], supportsAllDrives=True)
|
||||
removeExpiration=removeExpiration,
|
||||
**deleteUpdateKwargs,
|
||||
fileId=newFileId, permissionId=permissionId, body=permission['updates'], supportsAllDrives=True)
|
||||
if copyMoveOptions['showPermissionMessages']:
|
||||
entityActionPerformed(kvList, k, kcount)
|
||||
except (GAPI.notFound, GAPI.permissionNotFound,
|
||||
@@ -58870,6 +58964,7 @@ copyReturnItemMap = {
|
||||
# [sendemailifrequired [<Boolean>]]
|
||||
# [suppressnotselectedmessages [<Boolean>]]
|
||||
# [verifyorganizer [<Boolean>]]
|
||||
# [enforceexpansiveaccess [<Boolean>]]
|
||||
def copyDriveFile(users):
|
||||
def _writeCSVData(user, oldName, oldId, newName, newId, mimeType):
|
||||
row = {'User': user, fileNameTitle: oldName, 'id': oldId,
|
||||
@@ -59597,7 +59692,9 @@ def _updateMoveFilePermissions(drive, user, i, count,
|
||||
try:
|
||||
callGAPI(drive.permissions(), 'delete',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
|
||||
fileId=fileId, permissionId=permissionId, useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'], supportsAllDrives=True)
|
||||
useDomainAdminAccess=copyMoveOptions['useDomainAdminAccess'],
|
||||
enforceExpansiveAccess=copyMoveOptions['enforceExpansiveAccess'],
|
||||
fileId=fileId, permissionId=permissionId, supportsAllDrives=True)
|
||||
if copyMoveOptions['showPermissionMessages']:
|
||||
entityActionPerformed(kvList, k, kcount)
|
||||
except (GAPI.notFound, GAPI.permissionNotFound,
|
||||
@@ -59685,6 +59782,7 @@ def _updateMoveFilePermissions(drive, user, i, count,
|
||||
# [retainsourcefolders [<Boolean>]]
|
||||
# [sendemailifrequired [<Boolean>]]
|
||||
# [verifyorganizer [<Boolean>]]
|
||||
# [enforceexpansiveaccess [<Boolean>]]
|
||||
def moveDriveFile(users):
|
||||
def _cloneFolderMove(drive, user, i, count, j, jcount,
|
||||
source, targetChildren, newFolderName, newParentId, newParentName, mergeParentModifiedTime,
|
||||
@@ -60028,9 +60126,8 @@ def moveDriveFile(users):
|
||||
parentBody = {}
|
||||
parentParms = initDriveFileAttributes()
|
||||
copyMoveOptions = initCopyMoveOptions(False)
|
||||
newParentsSpecified = False
|
||||
newParentsSpecified = updateFilePermissions = False
|
||||
movedFiles = {}
|
||||
updateFilePermissions = False
|
||||
verifyOrganizer = True
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
@@ -60919,6 +61016,7 @@ TRANSFER_DRIVEFILE_ACL_ROLES_MAP = {
|
||||
# [nonowner_retainrole reader|commenter|writer|editor|fileorganizer|current|none]
|
||||
# [nonowner_targetrole reader|commenter|writer|editor|fileorganizer|current|none|source]
|
||||
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||
# [enforceexpansiveaccess [<Boolean>]]
|
||||
# [preview] [todrive <ToDriveAttribute>*]
|
||||
def transferDrive(users):
|
||||
|
||||
@@ -61105,6 +61203,7 @@ def transferDrive(users):
|
||||
callGAPI(sourceDrive.permissions(), 'update',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.BAD_REQUEST, GAPI.INVALID_OWNERSHIP_TRANSFER,
|
||||
GAPI.PERMISSION_NOT_FOUND, GAPI.SHARING_RATE_LIMIT_EXCEEDED],
|
||||
enforceExpansiveAccess=enforceExpansiveAccess,
|
||||
fileId=childFileId, permissionId=targetPermissionId,
|
||||
transferOwnership=True, body={'role': 'owner'}, fields='')
|
||||
if removeSourceParents:
|
||||
@@ -61293,6 +61392,7 @@ def transferDrive(users):
|
||||
if ownerRetainRoleBody['role'] != 'writer':
|
||||
callGAPI(targetDrive.permissions(), 'update',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND, GAPI.BAD_REQUEST, GAPI.SHARING_RATE_LIMIT_EXCEEDED],
|
||||
enforceExpansiveAccess=enforceExpansiveAccess,
|
||||
fileId=childFileId, permissionId=sourcePermissionId, body=ownerRetainRoleBody, fields='')
|
||||
else:
|
||||
callGAPI(targetDrive.permissions(), 'delete',
|
||||
@@ -61342,6 +61442,7 @@ def transferDrive(users):
|
||||
if nonOwnerRetainRoleBody['role'] != 'current':
|
||||
callGAPI(ownerDrive.permissions(), 'update',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND, GAPI.BAD_REQUEST, GAPI.SHARING_RATE_LIMIT_EXCEEDED],
|
||||
enforceExpansiveAccess=enforceExpansiveAccess,
|
||||
fileId=childFileId, permissionId=sourcePermissionId, body=sourceUpdateRole, fields='')
|
||||
else:
|
||||
try:
|
||||
@@ -61502,7 +61603,7 @@ def transferDrive(users):
|
||||
targetUserFolderPattern = '#user# old files'
|
||||
targetUserOrphansFolderPattern = '#user# orphaned files'
|
||||
targetIds = [None, None]
|
||||
createShortcutsForNonmovableFiles = False
|
||||
createShortcutsForNonmovableFiles = enforceExpansiveAccess = False
|
||||
mergeWithTarget = False
|
||||
thirdPartyOwners = {}
|
||||
skipFileIdEntity = initDriveFileEntity()
|
||||
@@ -61520,6 +61621,8 @@ def transferDrive(users):
|
||||
nonOwnerRetainRoleBody['role'] = 'current'
|
||||
elif myarg == 'nonownertargetrole':
|
||||
nonOwnerTargetRoleBody['role'] = getChoice(TRANSFER_DRIVEFILE_ACL_ROLES_MAP, mapChoice=True)
|
||||
elif myarg == 'enforceexpansiveaccess':
|
||||
enforceExpansiveAccess = getBoolean()
|
||||
elif myarg == 'noretentionmessages':
|
||||
showRetentionMessages = False
|
||||
elif myarg == 'orderby':
|
||||
@@ -61757,6 +61860,7 @@ def getPermissionIdForEmail(user, i, count, email):
|
||||
# [<DriveFileParentAttribute>] [includetrashed] [norecursion [<Boolean>]]
|
||||
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||
# [preview] [filepath] [pathdelimiter <Character>] [buildtree]
|
||||
# [enforceexpansiveaccess [<Boolean>]]
|
||||
# [todrive <ToDriveAttribute>*]
|
||||
def transferOwnership(users):
|
||||
def _identifyFilesToTransfer(fileEntry):
|
||||
@@ -61805,7 +61909,7 @@ def transferOwnership(users):
|
||||
body = {}
|
||||
newOwner = getEmailAddress()
|
||||
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
|
||||
changeParents = filepath = includeTrashed = noRecursion = False
|
||||
changeParents = enforceExpansiveAccess = filepath = includeTrashed = noRecursion = False
|
||||
pathDelimiter = '/'
|
||||
csvPF = fileTree = None
|
||||
addParents = ''
|
||||
@@ -61832,6 +61936,8 @@ def transferOwnership(users):
|
||||
csvPF.GetTodriveParameters()
|
||||
elif getDriveFileParentAttribute(myarg, parentParms):
|
||||
changeParents = True
|
||||
elif myarg == 'enforceexpansiveaccess':
|
||||
enforceExpansiveAccess = getBoolean()
|
||||
else:
|
||||
unknownArgumentExit()
|
||||
Act.Set(Act.TRANSFER_OWNERSHIP)
|
||||
@@ -61949,6 +62055,7 @@ def transferOwnership(users):
|
||||
Act.Set(action)
|
||||
callGAPI(drive.permissions(), 'update',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
|
||||
enforceExpansiveAccess=enforceExpansiveAccess,
|
||||
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
|
||||
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_TO, None, [Ent.USER, newOwner], k, kcount)
|
||||
else:
|
||||
@@ -61970,6 +62077,7 @@ def transferOwnership(users):
|
||||
fileId=xferFileId, sendNotificationEmail=False, body=bodyAdd, fields='')
|
||||
callGAPI(drive.permissions(), 'update',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
|
||||
enforceExpansiveAccess=enforceExpansiveAccess,
|
||||
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
|
||||
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_TO, None, [Ent.USER, newOwner], k, kcount)
|
||||
except GAPI.invalidSharingRequest as e:
|
||||
@@ -62042,6 +62150,7 @@ def transferOwnership(users):
|
||||
# [keepuser | (retainrole reader|commenter|writer|editor|none)] [noretentionmessages]
|
||||
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||
# [preview] [filepath] [pathdelimiter <Character>] [buildtree]
|
||||
# [enforceexpansiveaccess [<Boolean>]]
|
||||
# [todrive <ToDriveAttribute>*]
|
||||
def claimOwnership(users):
|
||||
def _identifyFilesToClaim(fileEntry):
|
||||
@@ -62102,6 +62211,7 @@ def claimOwnership(users):
|
||||
if sourceRetainRoleBody['role'] != 'writer':
|
||||
callGAPI(sourceDrive.permissions(), 'update',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND, GAPI.BAD_REQUEST],
|
||||
enforceExpansiveAccess=enforceExpansiveAccess,
|
||||
fileId=ofileId, permissionId=oldOwnerPermissionId, body=sourceRetainRoleBody, fields='')
|
||||
else:
|
||||
callGAPI(sourceDrive.permissions(), 'delete',
|
||||
@@ -62125,7 +62235,7 @@ def claimOwnership(users):
|
||||
onlyOwners = set()
|
||||
skipOwners = set()
|
||||
subdomains = []
|
||||
filepath = includeTrashed = False
|
||||
enforceExpansiveAccess = filepath = includeTrashed = False
|
||||
pathDelimiter = '/'
|
||||
addParents = ''
|
||||
parentBody = {}
|
||||
@@ -62160,6 +62270,8 @@ def claimOwnership(users):
|
||||
includeTrashed = True
|
||||
elif myarg == 'orderby':
|
||||
OBY.GetChoice()
|
||||
elif myarg == 'enforceexpansiveaccess':
|
||||
enforceExpansiveAccess = getBoolean()
|
||||
elif myarg == 'restricted':
|
||||
bodyShare['copyRequiresWriterPermission'] = getBoolean()
|
||||
elif myarg == 'writerscanshare':
|
||||
@@ -62330,6 +62442,7 @@ def claimOwnership(users):
|
||||
Act.Set(action)
|
||||
callGAPI(sourceDrive.permissions(), 'update',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
|
||||
enforceExpansiveAccess=enforceExpansiveAccess,
|
||||
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
|
||||
kvList = [Ent.USER, user, entityType, fileDesc]
|
||||
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_FROM, None, [Ent.USER, oldOwner], l, lcount)
|
||||
@@ -62354,6 +62467,7 @@ def claimOwnership(users):
|
||||
fileId=xferFileId, sendNotificationEmail=False, body=bodyAdd, fields='')
|
||||
callGAPI(sourceDrive.permissions(), 'update',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+[GAPI.PERMISSION_NOT_FOUND],
|
||||
enforceExpansiveAccess=enforceExpansiveAccess,
|
||||
fileId=xferFileId, permissionId=permissionId, transferOwnership=True, body=body, fields='')
|
||||
entityModifierNewValueItemValueListActionPerformed(kvList, Act.MODIFIER_FROM, None, [Ent.USER, oldOwner], l, lcount)
|
||||
_processRetainedRole(user, i, count, oldOwner, entityType, xferFileId, fileDesc, l, lcount)
|
||||
@@ -62890,11 +63004,12 @@ def doCreateDriveFileACL():
|
||||
|
||||
# gam [<UserTypeEntity>] update drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail> [asadmin]
|
||||
# (role <DriveFileACLRole>) [expiration <Time>] [removeexpiration [<Boolean>]]
|
||||
# [updatesheetprotectedranges [<Boolean>]]
|
||||
# [updatesheetprotectedranges [<Boolean>]] [enforceexpansiveaccess [<Boolean>]]
|
||||
# [showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
|
||||
def updateDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
fileIdEntity = getDriveFileEntity()
|
||||
isEmail, permissionId = getPermissionId()
|
||||
enforceExpansiveAccess = None
|
||||
removeExpiration = showTitles = updateSheetProtectedRanges = False
|
||||
showDetails = True
|
||||
csvPF = None
|
||||
@@ -62913,6 +63028,8 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
showTitles = True
|
||||
elif myarg == 'updatesheetprotectedranges':
|
||||
updateSheetProtectedRanges = getBoolean()
|
||||
elif myarg == 'enforceexpansiveaccess':
|
||||
enforceExpansiveAccess = getBoolean()
|
||||
elif myarg == 'nodetails':
|
||||
showDetails = False
|
||||
elif myarg == 'csv':
|
||||
@@ -62930,6 +63047,9 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
_checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
|
||||
if 'role' not in body:
|
||||
missingArgumentExit(f'role {formatChoiceList(DRIVEFILE_ACL_ROLES_MAP)}')
|
||||
updateKwargs = {'useDomainAdminAccess': useDomainAdminAccess}
|
||||
if enforceExpansiveAccess is not None:
|
||||
updateKwargs['enforceExpansiveAccess'] = enforceExpansiveAccess
|
||||
printKeys, timeObjects = _getDriveFileACLPrintKeysTimeObjects()
|
||||
if csvPF and showTitles:
|
||||
csvPF.AddTitles(fileNameTitle)
|
||||
@@ -62967,7 +63087,7 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
permission = callGAPI(drive.permissions(), 'update',
|
||||
bailOnInternalError=True,
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_UPDATE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
|
||||
useDomainAdminAccess=useDomainAdminAccess,
|
||||
**updateKwargs,
|
||||
fileId=fileId, permissionId=permissionId, removeExpiration=removeExpiration,
|
||||
transferOwnership=body.get('role', '') == 'owner', body=body, fields='*', supportsAllDrives=True)
|
||||
if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
|
||||
@@ -63063,7 +63183,7 @@ def createDriveFilePermissions(users, useDomainAdminAccess=False):
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def _callbackCreatePermission(request_id, response, exception):
|
||||
def _callbackCreatePermission(request_id, _, exception):
|
||||
ri = request_id.splitlines()
|
||||
if int(ri[RI_J]) == 1:
|
||||
entityPerformActionNumItems([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY]], int(ri[RI_JCOUNT]), Ent.PERMITTEE, int(ri[RI_I]), int(ri[RI_COUNT]))
|
||||
@@ -63211,11 +63331,12 @@ def doCreatePermissions():
|
||||
createDriveFilePermissions([_getAdminEmail()], True)
|
||||
|
||||
# gam [<UserTypeEntity>] delete drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail> [asadmin]
|
||||
# [updatesheetprotectedranges [<Boolean>]]
|
||||
# [updatesheetprotectedranges [<Boolean>]] [enforceexpansiveaccess [<Boolean>]]
|
||||
# [showtitles]
|
||||
def deleteDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
fileIdEntity = getDriveFileEntity()
|
||||
isEmail, permissionId = getPermissionId()
|
||||
enforceExpansiveAccess = None
|
||||
showTitles = updateSheetProtectedRanges = False
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
@@ -63223,11 +63344,16 @@ def deleteDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
showTitles = getBoolean()
|
||||
elif myarg == 'updatesheetprotectedranges':
|
||||
updateSheetProtectedRanges = getBoolean()
|
||||
elif myarg == 'enforceexpansiveaccess':
|
||||
enforceExpansiveAccess = getBoolean()
|
||||
elif myarg in ADMIN_ACCESS_OPTIONS:
|
||||
useDomainAdminAccess = True
|
||||
else:
|
||||
unknownArgumentExit()
|
||||
_checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
|
||||
deleteKwargs = {'useDomainAdminAccess': useDomainAdminAccess}
|
||||
if enforceExpansiveAccess is not None:
|
||||
deleteKwargs['enforceExpansiveAccess'] = enforceExpansiveAccess
|
||||
i, count, users = getEntityArgument(users)
|
||||
for user in users:
|
||||
i += 1
|
||||
@@ -63260,7 +63386,8 @@ def deleteDriveFileACLs(users, useDomainAdminAccess=False):
|
||||
break
|
||||
callGAPI(drive.permissions(), 'delete',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS+[GAPI.FILE_NEVER_WRITABLE],
|
||||
useDomainAdminAccess=useDomainAdminAccess, fileId=fileId, permissionId=permissionId, supportsAllDrives=True)
|
||||
**deleteKwargs,
|
||||
fileId=fileId, permissionId=permissionId, supportsAllDrives=True)
|
||||
entityActionPerformed([Ent.USER, user, entityType, fileName, Ent.PERMISSION_ID, permissionId], j, jcount)
|
||||
if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
|
||||
_updateSheetProtectedRangesACLchange(sheet, user, i, count, j, jcount, fileId, fileName, False, permission)
|
||||
@@ -63282,6 +63409,7 @@ def doDeleteDriveFileACLs():
|
||||
|
||||
# gam [<UserTypeEntity>] delete permissions <DriveFileEntity> <DriveFilePermissionIDEntity> [asadmin]
|
||||
# <PermissionMatch>* [<PermissionMatchAction>]
|
||||
# [enforceexpansiveaccess [<Boolean>]]
|
||||
def deletePermissions(users, useDomainAdminAccess=False):
|
||||
def convertJSONPermissions(jsonPermissions):
|
||||
permissionIds = []
|
||||
@@ -63291,7 +63419,7 @@ def deletePermissions(users, useDomainAdminAccess=False):
|
||||
permissionIds.append(permission['id'])
|
||||
return permissionIds
|
||||
|
||||
def _callbackDeletePermissionId(request_id, response, exception):
|
||||
def _callbackDeletePermissionId(request_id, _, exception):
|
||||
ri = request_id.splitlines()
|
||||
if int(ri[RI_J]) == 1:
|
||||
entityPerformActionNumItems([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY]], int(ri[RI_JCOUNT]), Ent.PERMISSION_ID, int(ri[RI_I]), int(ri[RI_COUNT]))
|
||||
@@ -63316,7 +63444,8 @@ def deletePermissions(users, useDomainAdminAccess=False):
|
||||
callGAPI(drive.permissions(), 'delete',
|
||||
throwReasons=GAPI.DRIVE_ACCESS_THROW_REASONS+GAPI.DRIVE3_DELETE_ACL_THROW_REASONS,
|
||||
retryReasons=[GAPI.SERVICE_LIMIT],
|
||||
useDomainAdminAccess=useDomainAdminAccess, fileId=ri[RI_ENTITY], permissionId=ri[RI_ITEM], supportsAllDrives=True)
|
||||
useDomainAdminAccess=useDomainAdminAccess, enforceExpansiveAccess=enforceExpansiveAccess,
|
||||
fileId=ri[RI_ENTITY], permissionId=ri[RI_ITEM], supportsAllDrives=True)
|
||||
entityActionPerformed([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY], Ent.PERMISSION_ID, ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
||||
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
|
||||
GAPI.badRequest, GAPI.cannotRemoveOwner, GAPI.cannotModifyInheritedTeamDrivePermission,
|
||||
@@ -63336,12 +63465,15 @@ def deletePermissions(users, useDomainAdminAccess=False):
|
||||
jsonData = getJSON([])
|
||||
PM = PermissionMatch()
|
||||
PM.SetDefaultMatch(False, {'role': 'owner'})
|
||||
enforceExpansiveAccess = False
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
if myarg in ADMIN_ACCESS_OPTIONS:
|
||||
useDomainAdminAccess = True
|
||||
elif PM and PM.ProcessArgument(myarg):
|
||||
pass
|
||||
elif myarg == 'enforceexpansiveaccess':
|
||||
enforceExpansiveAccess = getBoolean()
|
||||
else:
|
||||
unknownArgumentExit()
|
||||
_checkFileIdEntityDomainAccess(fileIdEntity, useDomainAdminAccess)
|
||||
@@ -68572,7 +68704,7 @@ def deleteLabels(users, labelEntity):
|
||||
http_status, reason, message = checkGAPIError(exception)
|
||||
entityActionFailedWarning([Ent.USER, ri[RI_ENTITY], Ent.LABEL, labelIdToNameMap[ri[RI_ITEM]]], formatHTTPError(http_status, reason, message), int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
||||
|
||||
def _callbackDeleteLabel(request_id, response, exception):
|
||||
def _callbackDeleteLabel(request_id, _, exception):
|
||||
ri = request_id.splitlines()
|
||||
if exception is None:
|
||||
entityActionPerformed([Ent.USER, ri[RI_ENTITY], Ent.LABEL, labelIdToNameMap[ri[RI_ITEM]]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
||||
@@ -69173,7 +69305,7 @@ def _processMessagesThreads(users, entityType):
|
||||
GAPI.INVALID_MESSAGE_ID: Msg.INVALID_MESSAGE_ID,
|
||||
GAPI.FAILED_PRECONDITION: Msg.FAILED_PRECONDITION}
|
||||
|
||||
def _callbackProcessMessage(request_id, response, exception):
|
||||
def _callbackProcessMessage(request_id, _, exception):
|
||||
ri = request_id.splitlines()
|
||||
if exception is None:
|
||||
if not csvPF:
|
||||
|
||||
@@ -75,6 +75,7 @@ KEEP = 'keep'
|
||||
LICENSING = 'licensing'
|
||||
LOOKERSTUDIO = 'datastudio'
|
||||
MEET = 'meet'
|
||||
MEET_BETA = 'meetbeta'
|
||||
OAUTH2 = 'oauth2'
|
||||
ORGPOLICY = 'orgpolicy'
|
||||
PEOPLE = 'people'
|
||||
@@ -226,7 +227,7 @@ _INFO = {
|
||||
CLOUDIDENTITY_INBOUND_SSO: {'name': 'Cloud Identity Inbound SSO API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
|
||||
CLOUDIDENTITY_ORGUNITS: {'name': 'Cloud Identity OrgUnits API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
|
||||
CLOUDIDENTITY_ORGUNITS_BETA: {'name': 'Cloud Identity OrgUnits API', 'version': 'v1beta1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
|
||||
CLOUDIDENTITY_POLICY: {'name': 'Cloud Identity Policy API', 'version': 'v1beta1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
|
||||
CLOUDIDENTITY_POLICY: {'name': 'Cloud Identity Policy API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
|
||||
CLOUDIDENTITY_USERINVITATIONS: {'name': 'Cloud Identity User Invitations API', 'version': 'v1', 'v2discovery': True, 'mappedAPI': 'cloudidentity'},
|
||||
CLOUDRESOURCEMANAGER: {'name': 'Cloud Resource Manager API v3', 'version': 'v3', 'v2discovery': True},
|
||||
CONTACTS: {'name': 'Contacts API', 'version': 'v3', 'v2discovery': False},
|
||||
@@ -251,6 +252,7 @@ _INFO = {
|
||||
LICENSING: {'name': 'License Manager API', 'version': 'v1', 'v2discovery': True},
|
||||
LOOKERSTUDIO: {'name': 'Looker Studio API', 'version': 'v1', 'v2discovery': True, 'localjson': True},
|
||||
MEET: {'name': 'Meet API', 'version': 'v2', 'v2discovery': True},
|
||||
MEET_BETA: {'name': 'Meet API', 'version': 'v2beta', 'v2discovery': True, 'localjson': True, 'mappedAPI': MEET},
|
||||
OAUTH2: {'name': 'OAuth2 API', 'version': 'v2', 'v2discovery': False},
|
||||
ORGPOLICY: {'name': 'Organization Policy API', 'version': 'v2', 'v2discovery': True},
|
||||
PEOPLE: {'name': 'People API', 'version': 'v1', 'v2discovery': True},
|
||||
|
||||
@@ -177,8 +177,14 @@ INTER_BATCH_WAIT = 'inter_batch_wait'
|
||||
LICENSE_MAX_RESULTS = 'license_max_results'
|
||||
# License SKUs to process
|
||||
LICENSE_SKUS = 'license_skus'
|
||||
# Use Meet V2 beta
|
||||
MEET_V2_BETA = 'meet_v2_beta'
|
||||
# When retrieving lists of Google Group members from API, how many should be retrieved in each chunk
|
||||
MEMBER_MAX_RESULTS = 'member_max_results'
|
||||
# CI API Group members max page size when view=BASIC
|
||||
MEMBER_MAX_RESULTS_CI_BASIC = 'member_max_results_ci_basic'
|
||||
# CI API Group members max page size when view=FULL
|
||||
MEMBER_MAX_RESULTS_CI_FULL = 'member_max_results_ci_full'
|
||||
# When deleting or modifying Gmail messages, how many should be processed in each batch
|
||||
MESSAGE_BATCH_SIZE = 'message_batch_size'
|
||||
# When retrieving lists of Gmail messages from API, how many should be retrieved in each chunk
|
||||
@@ -384,7 +390,10 @@ Defaults = {
|
||||
INTER_BATCH_WAIT: '0',
|
||||
LICENSE_MAX_RESULTS: '100',
|
||||
LICENSE_SKUS: '',
|
||||
MEET_V2_BETA: FALSE,
|
||||
MEMBER_MAX_RESULTS: '200',
|
||||
MEMBER_MAX_RESULTS_CI_BASIC: '1000',
|
||||
MEMBER_MAX_RESULTS_CI_FULL: '500',
|
||||
MESSAGE_BATCH_SIZE: '50',
|
||||
MESSAGE_MAX_RESULTS: '500',
|
||||
MOBILE_MAX_RESULTS: '100',
|
||||
@@ -549,7 +558,10 @@ VAR_INFO = {
|
||||
INTER_BATCH_WAIT: {VAR_TYPE: TYPE_FLOAT, VAR_LIMITS: (0.0, 60.0)},
|
||||
LICENSE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 1000)},
|
||||
LICENSE_SKUS: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
|
||||
MEET_V2_BETA: {VAR_TYPE: TYPE_BOOLEAN},
|
||||
MEMBER_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 200)},
|
||||
MEMBER_MAX_RESULTS_CI_BASIC: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
|
||||
MEMBER_MAX_RESULTS_CI_FULL: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 500)},
|
||||
MESSAGE_BATCH_SIZE: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
|
||||
MESSAGE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 10000)},
|
||||
MOBILE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 100)},
|
||||
|
||||
@@ -1,283 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2009 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Data model classes for parsing and generating XML for the Sites Data API."""
|
||||
|
||||
import atom
|
||||
import gdata
|
||||
|
||||
# XML Namespaces used in Google Sites entities.
|
||||
SITES_NAMESPACE = 'http://schemas.google.com/sites/2008'
|
||||
SITES_TEMPLATE = '{http://schemas.google.com/sites/2008}%s'
|
||||
SPREADSHEETS_NAMESPACE = 'http://schemas.google.com/spreadsheets/2006'
|
||||
SPREADSHEETS_TEMPLATE = '{http://schemas.google.com/spreadsheets/2006}%s'
|
||||
GACL_NAMESPACE = 'http://schemas.google.com/acl/2007'
|
||||
GACL_TEMPLATE = '{http://schemas.google.com/acl/2007}%s'
|
||||
DC_TERMS_TEMPLATE = '{http://purl.org/dc/terms}%s'
|
||||
THR_TERMS_TEMPLATE = '{http://purl.org/syndication/thread/1.0}%s'
|
||||
XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'
|
||||
XHTML_TEMPLATE = '{http://www.w3.org/1999/xhtml}%s'
|
||||
|
||||
SITES_INVITE_LINK_REL = SITES_NAMESPACE + '#invite'
|
||||
SITES_PARENT_LINK_REL = SITES_NAMESPACE + '#parent'
|
||||
SITES_REVISION_LINK_REL = SITES_NAMESPACE + '#revision'
|
||||
SITES_SOURCE_LINK_REL = SITES_NAMESPACE + '#source'
|
||||
SITES_TEMPLATE_LINK_REL = SITES_NAMESPACE + '#template'
|
||||
|
||||
ALTERNATE_REL = 'alternate'
|
||||
WEB_ADDRESS_MAPPING_REL = 'webAddressMapping'
|
||||
|
||||
SITES_KIND_SCHEME = 'http://schemas.google.com/g/2005#kind'
|
||||
ANNOUNCEMENT_KIND_TERM = SITES_NAMESPACE + '#announcement'
|
||||
ANNOUNCEMENT_PAGE_KIND_TERM = SITES_NAMESPACE + '#announcementspage'
|
||||
ATTACHMENT_KIND_TERM = SITES_NAMESPACE + '#attachment'
|
||||
COMMENT_KIND_TERM = SITES_NAMESPACE + '#comment'
|
||||
FILECABINET_KIND_TERM = SITES_NAMESPACE + '#filecabinet'
|
||||
LISTITEM_KIND_TERM = SITES_NAMESPACE + '#listitem'
|
||||
LISTPAGE_KIND_TERM = SITES_NAMESPACE + '#listpage'
|
||||
WEBPAGE_KIND_TERM = SITES_NAMESPACE + '#webpage'
|
||||
WEBATTACHMENT_KIND_TERM = SITES_NAMESPACE + '#webattachment'
|
||||
FOLDER_KIND_TERM = SITES_NAMESPACE + '#folder'
|
||||
TAG_KIND_TERM = SITES_NAMESPACE + '#tag'
|
||||
|
||||
SUPPORT_KINDS = [
|
||||
'announcement', 'announcementspage', 'attachment', 'comment', 'filecabinet',
|
||||
'listitem', 'listpage', 'webpage', 'webattachment', 'tag'
|
||||
]
|
||||
|
||||
|
||||
class GDataBase(atom.AtomBase):
|
||||
"""The Google Sites intermediate class from atom.AtomBase."""
|
||||
_namespace = gdata.GDATA_NAMESPACE
|
||||
_children = atom.AtomBase._children.copy()
|
||||
_attributes = atom.AtomBase._attributes.copy()
|
||||
|
||||
def __init__(self, text=None):
|
||||
atom.AtomBase.__init__(self, text=text)
|
||||
|
||||
class SitesBase(GDataBase):
|
||||
_namespace = SITES_NAMESPACE
|
||||
|
||||
class SiteName(SitesBase):
|
||||
"""Google Sites <sites:siteName>."""
|
||||
_tag = 'siteName'
|
||||
|
||||
class Theme(SitesBase):
|
||||
"""Google Sites <sites:theme>."""
|
||||
_tag = 'theme'
|
||||
|
||||
class SiteEntry(gdata.BatchEntry):
|
||||
"""Google Sites Site Feed Entry."""
|
||||
_tag = 'entry'
|
||||
_namespace = atom.ATOM_NAMESPACE
|
||||
_children = gdata.BatchEntry._children.copy()
|
||||
|
||||
_children['{%s}siteName' % SITES_NAMESPACE] = ('siteName', SiteName)
|
||||
_children['{%s}theme' % SITES_NAMESPACE] = ('theme', Theme)
|
||||
_attributes = gdata.BatchEntry._attributes.copy()
|
||||
_attributes['{%s}etag' % gdata.GDATA_NAMESPACE] = 'etag'
|
||||
|
||||
def __init__(self, siteName=None, title=None, summary=None, theme=None, sourceSite=None, category=None, etag=None):
|
||||
gdata.BatchEntry.__init__(self, category=category)
|
||||
self.siteName = siteName
|
||||
self.title = title
|
||||
self.summary = summary
|
||||
self.theme = theme
|
||||
if sourceSite is not None:
|
||||
sourceLink = atom.Link(href=sourceSite, rel=SITES_SOURCE_LINK_REL, link_type='application/atom+xml')
|
||||
self.link.append(sourceLink)
|
||||
self.etag = etag
|
||||
|
||||
def find_alternate_link(self):
|
||||
for link in self.link:
|
||||
if link.rel == ALTERNATE_REL and link.href:
|
||||
return link.href
|
||||
return None
|
||||
|
||||
FindAlternateLink = find_alternate_link
|
||||
|
||||
def find_source_link(self):
|
||||
for link in self.link:
|
||||
if link.rel == SITES_SOURCE_LINK_REL and link.href:
|
||||
return link.href
|
||||
return None
|
||||
|
||||
FindSourceLink = find_source_link
|
||||
|
||||
def find_webaddress_mappings(self):
|
||||
mappingLinks = []
|
||||
for link in self.link:
|
||||
if link.rel == WEB_ADDRESS_MAPPING_REL and link.href:
|
||||
mappingLinks.append(link.href)
|
||||
return mappingLinks
|
||||
|
||||
FindWebAddressMappings = find_webaddress_mappings
|
||||
|
||||
def SiteEntryFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(SiteEntry, xml_string)
|
||||
|
||||
class SiteFeed(gdata.BatchFeed, gdata.LinkFinder):
|
||||
"""A Google Sites feed flavor of an Atom Feed."""
|
||||
_tag = 'feed'
|
||||
_namespace = atom.ATOM_NAMESPACE
|
||||
_children = gdata.BatchFeed._children.copy()
|
||||
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [SiteEntry])
|
||||
|
||||
def __init__(self):
|
||||
gdata.BatchFeed.__init__(self)
|
||||
|
||||
def SiteFeedFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(SiteFeed, xml_string)
|
||||
|
||||
class AclBase(GDataBase):
|
||||
_namespace = GACL_NAMESPACE
|
||||
|
||||
class AclRole(AclBase):
|
||||
"""Describes the role of an entry in an access control list."""
|
||||
_tag = 'role'
|
||||
_children = AclBase._children.copy()
|
||||
_attributes = AclBase._attributes.copy()
|
||||
_attributes['value'] = 'value'
|
||||
|
||||
def __init__(self, value=None):
|
||||
AclBase.__init__(self)
|
||||
self.value = value
|
||||
|
||||
class AclAdditionalRole(AclBase):
|
||||
"""Describes an additionalRole element."""
|
||||
_tag = 'additionalRole'
|
||||
_children = AclBase._children.copy()
|
||||
_attributes = AclBase._attributes.copy()
|
||||
_attributes['value'] = 'value'
|
||||
|
||||
def __init__(self, value=None):
|
||||
AclBase.__init__(self)
|
||||
self.value = value
|
||||
|
||||
class AclScope(AclBase):
|
||||
"""Describes the scope of an entry in an access control list."""
|
||||
_tag = 'scope'
|
||||
_children = AclBase._children.copy()
|
||||
_attributes = AclBase._attributes.copy()
|
||||
_attributes['type'] = 'type'
|
||||
_attributes['value'] = 'value'
|
||||
|
||||
def __init__(self, stype=None, value=None):
|
||||
AclBase.__init__(self)
|
||||
self.type = stype
|
||||
self.value = value
|
||||
|
||||
|
||||
class AclWithKey(AclBase):
|
||||
"""Describes a key that can be used to access a document."""
|
||||
_tag = 'withKey'
|
||||
_children = AclBase._children.copy()
|
||||
_children['{%s}role' % GACL_NAMESPACE] = ('role', AclRole)
|
||||
_children['{%s}additionalRole' % GACL_NAMESPACE] = ('additionalRole', AclAdditionalRole)
|
||||
_attributes = AclBase._attributes.copy()
|
||||
_attributes['key'] = 'key'
|
||||
|
||||
def __init__(self, key=None, role=None, additionalRole=None):
|
||||
AclBase.__init__(self)
|
||||
self.key = key
|
||||
self.role = role
|
||||
self.additionalRole = additionalRole
|
||||
|
||||
class AclEntry(gdata.BatchEntry):
|
||||
"""Describes an entry in a feed of an access control list (ACL)."""
|
||||
_tag = 'entry'
|
||||
_namespace = atom.ATOM_NAMESPACE
|
||||
_children = gdata.BatchEntry._children.copy()
|
||||
|
||||
_children['{%s}role' % GACL_NAMESPACE] = ('role', AclRole)
|
||||
_children['{%s}additionalRole' % GACL_NAMESPACE] = ('additionalRole', AclAdditionalRole)
|
||||
_children['{%s}scope' % GACL_NAMESPACE] = ('scope', AclScope)
|
||||
_children['{%s}withKey' % GACL_NAMESPACE] = ('withKey', AclWithKey)
|
||||
_attributes = gdata.BatchEntry._attributes.copy()
|
||||
_attributes['{%s}etag' % gdata.GDATA_NAMESPACE] = 'etag'
|
||||
|
||||
def __init__(self, role=None, additionalRole=None, scope=None, withKey=None, etag=None):
|
||||
gdata.BatchEntry.__init__(self)
|
||||
self.role = role
|
||||
self.additionalRole = additionalRole
|
||||
self.scope = scope
|
||||
self.withKey = withKey
|
||||
self.etag = etag
|
||||
|
||||
def find_invite_link(self):
|
||||
for link in self.link:
|
||||
if link.rel == SITES_INVITE_LINK_REL and link.href:
|
||||
return link.href
|
||||
return None
|
||||
|
||||
FindInviteLink = find_invite_link
|
||||
|
||||
def AclEntryFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(AclEntry, xml_string)
|
||||
|
||||
class AclFeed(gdata.BatchFeed, gdata.LinkFinder):
|
||||
"""Describes a feed of an access control list (ACL)."""
|
||||
_tag = 'feed'
|
||||
_namespace = atom.ATOM_NAMESPACE
|
||||
_children = gdata.BatchFeed._children.copy()
|
||||
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [AclEntry])
|
||||
|
||||
def __init__(self):
|
||||
gdata.BatchFeed.__init__(self)
|
||||
|
||||
def AclFeedFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(AclFeed, xml_string)
|
||||
|
||||
class ActivityEntry(gdata.BatchEntry):
|
||||
"""Describes an entry in a feed of site activity (changes)."""
|
||||
_tag = 'entry'
|
||||
_namespace = atom.ATOM_NAMESPACE
|
||||
_children = gdata.BatchEntry._children.copy()
|
||||
_attributes = gdata.BatchEntry._attributes.copy()
|
||||
|
||||
def __init__(self):
|
||||
gdata.BatchEntry.__init__(self)
|
||||
|
||||
def __find_category_scheme(self, scheme):
|
||||
for category in self.category:
|
||||
if category.scheme == scheme:
|
||||
return category
|
||||
return None
|
||||
|
||||
def kind(self):
|
||||
kind = self.__find_category_scheme(SITES_KIND_SCHEME)
|
||||
if kind is not None:
|
||||
return kind.term[len(SITES_NAMESPACE) + 1:]
|
||||
else:
|
||||
return None
|
||||
|
||||
Kind = kind
|
||||
|
||||
def ActivityEntryFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(ActivityEntry, xml_string)
|
||||
|
||||
class ActivityFeed(gdata.BatchFeed, gdata.LinkFinder):
|
||||
"""Describes a feed of site activity (changes)."""
|
||||
_tag = 'feed'
|
||||
_namespace = atom.ATOM_NAMESPACE
|
||||
_children = gdata.BatchFeed._children.copy()
|
||||
_children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [ActivityEntry])
|
||||
|
||||
def __init__(self):
|
||||
gdata.BatchFeed.__init__(self)
|
||||
|
||||
def ActivityFeedFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(ActivityFeed, xml_string)
|
||||
@@ -1,246 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright 2009 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""SitesService extends the GDataService for Google Sites API calls."""
|
||||
|
||||
import gdata.apps
|
||||
import gdata.apps.service
|
||||
import gdata.service
|
||||
|
||||
|
||||
# Feed URI templates
|
||||
CONTENT_FEED_TEMPLATE = '/feeds/content/%s/%s/'
|
||||
REVISION_FEED_TEMPLATE = '/feeds/revision/%s/%s/'
|
||||
ACTIVITY_FEED_TEMPLATE = '/feeds/activity/%s/%s/'
|
||||
ACTIVITY_ENTRY_TEMPLATE = '/feeds/activity/%s/%s/%s'
|
||||
SITE_FEED_TEMPLATE = '/feeds/site/%s/'
|
||||
ACL_FEED_TEMPLATE = '/feeds/acl/site/%s/%s'
|
||||
ACL_ENTRY_TEMPLATE = '/feeds/acl/site/%s/%s/%s'
|
||||
|
||||
|
||||
class SitesService(gdata.service.GDataService):
|
||||
"""Client extension for the Google Sites API service."""
|
||||
|
||||
def __init__(self,
|
||||
source=None, server='sites.google.com', additional_headers=None,
|
||||
**kwargs):
|
||||
"""Constructs a new client for the Sites API.
|
||||
|
||||
Args:
|
||||
site: string (optional) Name (webspace) of the Google Site
|
||||
domain: string (optional) Domain of the (Google Apps hosted) Site.
|
||||
If no domain is given, the Site is assumed to be a consumer Google
|
||||
Site, in which case the value 'site' is used.
|
||||
source: string (optional) The name of the user's application.
|
||||
server: string (optional) The name of the server to which a connection
|
||||
will be opened. Default value: 'sites..google.com'.
|
||||
**kwargs: The other parameters to pass to gdata.service.GDataService
|
||||
constructor.
|
||||
"""
|
||||
if additional_headers == None:
|
||||
additional_headers = {}
|
||||
additional_headers['GData-Version'] = '1.4'
|
||||
gdata.service.GDataService.__init__(self,
|
||||
source=source, server=server, additional_headers=additional_headers,
|
||||
**kwargs)
|
||||
self.ssl = True
|
||||
self.port = 443
|
||||
|
||||
def make_site_feed_uri(self, domain=None, site=None):
|
||||
if not domain:
|
||||
domain = 'site'
|
||||
if not site:
|
||||
return SITE_FEED_TEMPLATE % domain
|
||||
return (SITE_FEED_TEMPLATE % domain) + site
|
||||
|
||||
MakeSiteFeedUri = make_site_feed_uri
|
||||
|
||||
def get_site_feed(self, uri=None, domain=None, site=None,
|
||||
extra_headers=None, url_params=None, escape_params=True):
|
||||
|
||||
uri = uri or self.make_site_feed_uri(domain=domain, site=site)
|
||||
try:
|
||||
return self.Get(uri,
|
||||
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
|
||||
converter=gdata.apps.sites.SiteFeedFromString)
|
||||
except gdata.service.RequestError as e:
|
||||
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
|
||||
|
||||
GetSiteFeed = get_site_feed
|
||||
|
||||
def create_site(self, siteentry=None, uri=None, domain=None, site=None,
|
||||
extra_headers=None, url_params=None, escape_params=True):
|
||||
|
||||
if uri is None:
|
||||
uri = self.make_site_feed_uri(domain=domain, site=site)
|
||||
try:
|
||||
return self.Post(siteentry, uri,
|
||||
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
|
||||
converter=gdata.apps.sites.SiteEntryFromString)
|
||||
except gdata.service.RequestError as e:
|
||||
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
|
||||
|
||||
CreateSite = create_site
|
||||
|
||||
def get_site(self, uri=None, domain=None, site=None,
|
||||
extra_headers=None, url_params=None, escape_params=True):
|
||||
|
||||
uri = uri or self.make_site_feed_uri(domain=domain, site=site)
|
||||
try:
|
||||
return self.Get(uri,
|
||||
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
|
||||
converter=gdata.apps.sites.SiteEntryFromString)
|
||||
except gdata.service.RequestError as e:
|
||||
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
|
||||
|
||||
GetSite = get_site
|
||||
|
||||
def update_site(self, siteentry=None, uri=None, domain=None, site=None,
|
||||
extra_headers=None, url_params=None, escape_params=True):
|
||||
|
||||
uri = uri or self.make_site_feed_uri(domain=domain, site=site)
|
||||
try:
|
||||
return self.Put(siteentry, uri,
|
||||
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
|
||||
converter=gdata.apps.sites.SiteEntryFromString)
|
||||
except gdata.service.RequestError as e:
|
||||
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
|
||||
|
||||
UpdateSite = update_site
|
||||
|
||||
def make_acl_feed_uri(self, domain=None, site=None):
|
||||
return ACL_FEED_TEMPLATE % (domain, site)
|
||||
|
||||
MakeAclFeedUri = make_acl_feed_uri
|
||||
|
||||
def get_acl_feed(self, uri=None, domain=None, site=None,
|
||||
extra_headers=None, url_params=None, escape_params=True):
|
||||
|
||||
uri = uri or self.make_acl_feed_uri(domain=domain, site=site)
|
||||
try:
|
||||
return self.Get(uri,
|
||||
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
|
||||
converter=gdata.apps.sites.AclFeedFromString)
|
||||
except gdata.service.RequestError as e:
|
||||
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
|
||||
|
||||
GetAclFeed = get_acl_feed
|
||||
|
||||
def make_acl_entry_uri(self, domain=None, site=None, ruleId=None):
|
||||
return ACL_ENTRY_TEMPLATE % (domain, site, ruleId)
|
||||
|
||||
MakeAclEntryUri = make_acl_entry_uri
|
||||
|
||||
def create_acl_entry(self, aclentry=None, uri=None, domain=None, site=None,
|
||||
extra_headers=None, url_params=None, escape_params=True):
|
||||
|
||||
uri = uri or self.make_acl_feed_uri(domain=domain, site=site)
|
||||
try:
|
||||
return self.Post(aclentry, uri,
|
||||
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
|
||||
converter=gdata.apps.sites.AclEntryFromString)
|
||||
except gdata.service.RequestError as e:
|
||||
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
|
||||
|
||||
CreateAclEntry = create_acl_entry
|
||||
|
||||
def get_acl_entry(self, uri=None, domain=None, site=None, ruleId=None,
|
||||
extra_headers=None, url_params=None, escape_params=True):
|
||||
|
||||
uri = uri or self.make_acl_entry_uri(domain=domain, site=site, ruleId=ruleId)
|
||||
try:
|
||||
return self.Get(uri,
|
||||
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
|
||||
converter=gdata.apps.sites.AclEntryFromString)
|
||||
except gdata.service.RequestError as e:
|
||||
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
|
||||
|
||||
GetAclEntry = get_acl_entry
|
||||
|
||||
def update_acl_entry(self, aclentry=None, uri=None, domain=None, site=None, ruleId=None,
|
||||
extra_headers=None, url_params=None, escape_params=True):
|
||||
|
||||
uri = uri or self.make_acl_entry_uri(domain=domain, site=site, ruleId=ruleId)
|
||||
try:
|
||||
return self.Put(aclentry, uri,
|
||||
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
|
||||
converter=gdata.apps.sites.AclEntryFromString)
|
||||
except gdata.service.RequestError as e:
|
||||
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
|
||||
|
||||
UpdateAclEntry = update_acl_entry
|
||||
|
||||
def delete_acl_entry(self, uri=None, domain=None, site=None, ruleId=None,
|
||||
extra_headers=None, url_params=None, escape_params=True):
|
||||
|
||||
uri = uri or self.make_acl_entry_uri(domain=domain, site=site, ruleId=ruleId)
|
||||
try:
|
||||
return self.Delete(uri,
|
||||
url_params=url_params, escape_params=escape_params, extra_headers=extra_headers)
|
||||
except gdata.service.RequestError as e:
|
||||
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
|
||||
|
||||
DeleteAclEntry = delete_acl_entry
|
||||
|
||||
def make_activity_feed_uri(self, domain=None, site=None):
|
||||
return ACTIVITY_FEED_TEMPLATE % (domain, site)
|
||||
|
||||
MakeActivityFeedUri = make_activity_feed_uri
|
||||
|
||||
def get_activity_feed(self, uri=None, domain=None, site=None,
|
||||
extra_headers=None, url_params=None, escape_params=True):
|
||||
|
||||
uri = uri or self.make_activity_feed_uri(domain=domain, site=site)
|
||||
try:
|
||||
return self.Get(uri,
|
||||
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
|
||||
converter=gdata.apps.sites.ActivityFeedFromString)
|
||||
except gdata.service.RequestError as e:
|
||||
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
|
||||
|
||||
GetActivityFeed = get_activity_feed
|
||||
|
||||
def make_activity_entry_uri(self, domain=None, site=None, activityId=None):
|
||||
return ACTIVITY_ENTRY_TEMPLATE % (domain, site, activityId)
|
||||
|
||||
MakeActivityEntryUri = make_activity_entry_uri
|
||||
|
||||
def get_activity_entry(self, uri=None, domain=None, site=None, activityId=None,
|
||||
extra_headers=None, url_params=None, escape_params=True):
|
||||
|
||||
uri = uri or self.make_activity_entry_uri(domain=domain, site=site, activityId=activityId)
|
||||
try:
|
||||
return self.Get(uri,
|
||||
url_params=url_params, extra_headers=extra_headers, escape_params=escape_params,
|
||||
converter=gdata.apps.sites.ActivityEntryFromString)
|
||||
except gdata.service.RequestError as e:
|
||||
raise gdata.apps.service.AppsForYourDomainException(e.args[0])
|
||||
|
||||
GetActivityEntry = get_activity_entry
|
||||
|
||||
class SitesQuery(gdata.service.Query):
|
||||
|
||||
def make_site_feed_uri(self, domain=None, site=None):
|
||||
if not domain:
|
||||
domain = 'site'
|
||||
if not site:
|
||||
return SITE_FEED_TEMPLATE % domain
|
||||
return (SITE_FEED_TEMPLATE % domain) + site
|
||||
|
||||
def __init__(self, feed=None, domain=None, site=None, params=None):
|
||||
self.feed = feed or self.make_site_feed_uri(domain=domain, site=site)
|
||||
gdata.service.Query.__init__(self, feed=self.feed, params=params)
|
||||
|
||||
1152
src/gam/meet-v2beta.json
Normal file
1152
src/gam/meet-v2beta.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user