mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-17 20:51:37 +00:00
Compare commits
30 Commits
20240914.2
...
20240918.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6ced7fff6 | ||
|
|
484238ece2 | ||
|
|
ee32bb87f0 | ||
|
|
73803acb89 | ||
|
|
a40df40f9b | ||
|
|
a33b89788c | ||
|
|
54f815e503 | ||
|
|
e54d3d274a | ||
|
|
b7a20ceb4f | ||
|
|
bbc965d38f | ||
|
|
8935cf7041 | ||
|
|
4583f6d996 | ||
|
|
92282fb493 | ||
|
|
65ea328f2a | ||
|
|
2da4833a0d | ||
|
|
631ce68126 | ||
|
|
480aca680d | ||
|
|
6e3ab6700d | ||
|
|
61319fa08e | ||
|
|
673e9f88ad | ||
|
|
f2b8200a3b | ||
|
|
0383624c72 | ||
|
|
cb03b8d9d4 | ||
|
|
e7e821ca3d | ||
|
|
6b21fdbcc6 | ||
|
|
ee326c6fe3 | ||
|
|
8945fd163c | ||
|
|
4dab0bd4bb | ||
|
|
49ec0c6df4 | ||
|
|
f3d29c47e2 |
13
.github/actions/entitlements.plist
vendored
Normal file
13
.github/actions/entitlements.plist
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- These are required for binaries built by PyInstaller -->
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
109
.github/workflows/build.yml
vendored
109
.github/workflows/build.yml
vendored
@@ -31,68 +31,68 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
jid: 1
|
||||
goal: build
|
||||
arch: x86_64
|
||||
openssl_archs: linux-x86_64
|
||||
- os: [self-hosted, linux, arm64]
|
||||
- os: ubuntu-20.04
|
||||
jid: 2
|
||||
goal: build
|
||||
arch: x86_64
|
||||
openssl_archs: linux-x86_64
|
||||
- os: [self-hosted, linux, arm64]
|
||||
jid: 3
|
||||
goal: build
|
||||
arch: aarch64
|
||||
openssl_archs: linux-aarch64
|
||||
- os: ubuntu-20.04
|
||||
jid: 3
|
||||
jid: 4
|
||||
goal: build
|
||||
arch: x86_64
|
||||
openssl_archs: linux-x86_64
|
||||
staticx: yes
|
||||
- os: [self-hosted, linux, arm64]
|
||||
jid: 4
|
||||
jid: 5
|
||||
goal: build
|
||||
arch: aarch64
|
||||
openssl_archs: linux-aarch64
|
||||
staticx: yes
|
||||
- os: macos-12
|
||||
jid: 5
|
||||
jid: 6
|
||||
goal: build
|
||||
arch: x86_64
|
||||
openssl_archs: darwin64-x86_64
|
||||
- os: macos-14
|
||||
jid: 6
|
||||
jid: 7
|
||||
goal: build
|
||||
arch: aarch64
|
||||
openssl_archs: darwin64-arm64
|
||||
# - os: macos-14
|
||||
# jid: 7
|
||||
# goal: build
|
||||
# arch: universal2
|
||||
# openssl_archs: darwin64-arm64 darwin64-x86_64
|
||||
- os: windows-2022
|
||||
jid: 8
|
||||
jid: 9
|
||||
goal: build
|
||||
arch: Win64
|
||||
openssl_archs: VC-WIN64A
|
||||
- os: ubuntu-22.04
|
||||
goal: test
|
||||
python: "3.8"
|
||||
jid: 9
|
||||
arch: x86_64
|
||||
- os: ubuntu-22.04
|
||||
goal: test
|
||||
python: "3.9"
|
||||
jid: 10
|
||||
arch: x86_64
|
||||
- os: ubuntu-22.04
|
||||
goal: test
|
||||
python: "3.10"
|
||||
python: "3.9"
|
||||
jid: 11
|
||||
arch: x86_64
|
||||
- os: ubuntu-22.04
|
||||
goal: test
|
||||
python: "3.11"
|
||||
python: "3.10"
|
||||
jid: 12
|
||||
arch: x86_64
|
||||
- os: ubuntu-22.04
|
||||
goal: test
|
||||
python: "3.11"
|
||||
jid: 8
|
||||
arch: x86_64
|
||||
|
||||
steps:
|
||||
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
with:
|
||||
path: |
|
||||
cache.tar.xz
|
||||
key: gam-${{ matrix.jid }}-20240903
|
||||
key: gam-${{ matrix.jid }}-20240916
|
||||
|
||||
- name: Untar Cache archive
|
||||
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'
|
||||
@@ -201,6 +201,14 @@ jobs:
|
||||
#brew install swig
|
||||
#brew install ncurses
|
||||
|
||||
- name: MacOS import developer certificates for signing
|
||||
if: runner.os == 'macOS'
|
||||
uses: apple-actions/import-codesign-certs@v3
|
||||
with:
|
||||
keychain: signing_temp
|
||||
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
|
||||
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
|
||||
|
||||
- name: Windows Configure VCode
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
if: runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true'
|
||||
@@ -521,32 +529,31 @@ jobs:
|
||||
- name: Build GAM with PyInstaller
|
||||
if: matrix.goal != 'test'
|
||||
run: |
|
||||
if [[ "${staticx}" == "yes" ]]; then
|
||||
export distpath="./dist/gam"
|
||||
export gampath="${distpath}"
|
||||
else
|
||||
export distpath="./dist"
|
||||
export gampath="${distpath}/gam"
|
||||
fi
|
||||
export distpath="./dist/gam"
|
||||
export gampath="$distpath"
|
||||
mkdir -p -v "${gampath}"
|
||||
if [[ "${RUNNER_OS}" == "macOS" ]]; then
|
||||
# brew OpenSSL gets picked up by PyInstaller breaking our self-compiled version
|
||||
# Tell our gam.spec to use our code sign certificate
|
||||
export codesign_identity="Jay Lee"
|
||||
# brew OpenSSL gets picked up by PyInstaller
|
||||
# breaking our self-compiled version
|
||||
brew uninstall --ignore-dependencies openssl
|
||||
export gampath=$($PYTHON -c "import os; print(os.path.realpath('$gampath'))")
|
||||
export PYINSTALLER_BUILD_ONEDIR=yes
|
||||
export gampath=$($PYTHON -c "import os; print(os.path.realpath('${gampath}/gam'))")
|
||||
elif [[ "${RUNNER_OS}" == "Windows" ]]; then
|
||||
# Work around issue where PyInstaller picks up python3.dll from other Python versions
|
||||
# https://github.com/pyinstaller/pyinstaller/issues/7102
|
||||
export PATH="$(dirname ${PYTHON}):/usr/bin"
|
||||
export PYINSTALLER_BUILD_ONEDIR=no
|
||||
else
|
||||
export gampath=$(realpath "${gampath}")
|
||||
export PYINSTALLER_BUILD_ONEDIR=no
|
||||
fi
|
||||
export gam="${gampath}/gam"
|
||||
echo "gampath=${gampath}" >> $GITHUB_ENV
|
||||
# TEMP force everything back to one file.
|
||||
export PYINSTALLER_BUILD_ONEFILE="yes"
|
||||
export distpath="./dist/gam"
|
||||
export gampath="${distpath}"
|
||||
"${PYTHON}" -m PyInstaller --clean --noconfirm --distpath="${distpath}" gam.spec
|
||||
echo "dist results:"
|
||||
ls -alRF "$distpath"
|
||||
echo "WARNINGS FROM build/gam/warn-gam.txt"
|
||||
cat build/gam/warn-gam.txt
|
||||
echo "Analysis FROM build/gam/Analysis-00.toc"
|
||||
@@ -570,12 +577,12 @@ jobs:
|
||||
- name: Copy extra package files
|
||||
if: matrix.goal == 'build'
|
||||
run: |
|
||||
cp -v cacerts.pem $gampath
|
||||
cp -v LICENSE $gampath
|
||||
cp -v GamCommands.txt $gampath
|
||||
cp -v GamUpdate.txt $gampath
|
||||
cp -v cacerts.pem "$gampath"
|
||||
cp -v LICENSE "$gampath"
|
||||
cp -v GamCommands.txt "$gampath"
|
||||
cp -v GamUpdate.txt "$gampath"
|
||||
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
||||
cp -v gam-setup.bat $gampath
|
||||
cp -v gam-setup.bat "$gampath"
|
||||
fi
|
||||
|
||||
- name: Install StaticX
|
||||
@@ -596,9 +603,21 @@ jobs:
|
||||
;;
|
||||
esac
|
||||
echo "ldlib=${ldlib}"
|
||||
$PYTHON -m staticx -l "${ldlib}" "${gam}" "${gam}-staticx"
|
||||
rm -v "${gam}"
|
||||
mv -v "${gam}-staticx" "${gam}"
|
||||
$PYTHON -m staticx -l "${ldlib}" "$gam" "${gam}-staticx"
|
||||
rm -v "$gam"
|
||||
mv -v "${gam}-staticx" "$gam"
|
||||
|
||||
- name: MacOS send GAM binary for Apple notarization
|
||||
if: runner.os == 'macOS'
|
||||
env:
|
||||
ASP_NOTARIZE: ${{ secrets.ASP_NOTARIZE }}
|
||||
run: |
|
||||
# Apple wants some kind of "package" submitted so just add gam to a .zip
|
||||
# name it something we can track and link in Apple's notarize process
|
||||
zipfilename="./gam-${RUNNER_ARCH}-${GITHUB_RUN_ID}-${GITHUB_RUN_NUMBER}.zip"
|
||||
zip -r "$zipfilename" "$gampath"
|
||||
xcrun notarytool submit --apple-id "jay0lee@gmail.com" --password "$ASP_NOTARIZE" --team-id GZ85H2DRLM "$zipfilename"
|
||||
rm -v "$zipfilename"
|
||||
|
||||
- name: Basic Tests all jobs
|
||||
id: basictests
|
||||
@@ -715,7 +734,8 @@ jobs:
|
||||
done
|
||||
driveid=$($gam user $gam_user add shareddrive "${newbase}" returnidonly)
|
||||
echo "Created shared drive ${driveid}"
|
||||
$gam create user $newuser firstname GHA lastname $JID displayname "Github Actions ${JID}" password random ou "${newou}" recoveryphone 12125121110 recoveryemail jay0lee@gmail.com gha.jid $JID languages en+,en-GB-
|
||||
# 9/17/24 - temp create in root due to Google API issues creating users in new OUs
|
||||
$gam create user $newuser firstname GHA lastname $JID displayname "Github Actions ${JID}" password random recoveryphone 12125121110 recoveryemail jay0lee@gmail.com gha.jid $JID languages en+,en-GB- # ou "${newou}"
|
||||
$gam user $newuser update photo https://dummyimage.com/400x600/000/fff
|
||||
$gam user $newuser get photo
|
||||
$gam user $newuser delete photo
|
||||
@@ -734,7 +754,8 @@ jobs:
|
||||
$gam update group $newgroup add owner $gam_user
|
||||
$gam update group $newgroup add member $newuser
|
||||
$gam config enable_dasa false save
|
||||
$gam create admin $newuser _GROUPS_EDITOR_ROLE CUSTOMER # condition nonsecuritygroup
|
||||
# 9/17/24 temp disable due to Google API sluggishness to see new users for admin commands
|
||||
# $gam create admin $newuser _GROUPS_EDITOR_ROLE CUSTOMER # condition nonsecuritygroup
|
||||
$gam create admin $newgroup _HELP_DESK_ADMIN_ROLE org_unit "${newou}"
|
||||
$gam config csv_output_row_filter "assignedToUser:regex:${newuser}" print admins | $gam csv - gam delete admin "~roleAssignmentId"
|
||||
$gam config csv_output_row_filter "assignedToGroup:regex:${newgroup}" print admins | $gam csv - gam delete admin "~roleAssignmentId"
|
||||
@@ -858,7 +879,7 @@ jobs:
|
||||
echo "printer model count:"
|
||||
$gam print printermodels | wc -l
|
||||
$gam print printers
|
||||
printerid=$($gam create printer displayname "${newbase}" uri ipp://localhost:631 driverless description "made by $(gam_user)" ou "${newou}" nodetails | awk '{print substr($2, 1, length($2)-1)}')
|
||||
printerid=$($gam create printer displayname "${newbase}" uri ipp://localhost:631 driverless description "made by ${gam_user}" ou "${newou}" nodetails | awk '{print substr($2, 1, length($2)-1)}')
|
||||
$gam info printer "$printerid"
|
||||
$gam delete printer "$printerid"
|
||||
$gam delete ou "${newou}"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
GAM is a command line tool for Google Workspace admins to manage domain and user settings quickly and easily.
|
||||
|
||||

|
||||
[](https://github.com/GAM-team/GAM/actions/workflows/build.yml)
|
||||
|
||||
# Quick Start
|
||||
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
- [Display Chrome policies](#display-chrome-policies)
|
||||
- [Copy simple policies set directly in one OU to another OU](#copy-simple-policies-set-directly-in-one-ou-to-another-ou)
|
||||
- [Copy simple and complex policies set directly in one OU to another OU](#copy-simple-and-complex-policies-set-directly-in-one-ou-to-another-ou)
|
||||
- [Copy simple and complex policies set directly in one OU to multiple other OUs](#copy-simple-and-complex-policies-set-directly-in-one-ou-to-multiple-other-ous)
|
||||
- [Copy simple policies in one Group to another Group](#copy-simple-policies-in-one-group-to-another-group)
|
||||
- [Copy simple and complex policies in one Group to another Group](#copy-simple-and-complex-policies-in-one-group-to-another-group)
|
||||
- [Copy simple and complex policies in one Group to multiple other Groups](#copy-simple-and-complex-policies-in-one-group-to-multiple-other-groups)
|
||||
- [Create Chrome network](#create-chrome-network)
|
||||
- [Delete Chrome network](#delete-chrome-network)
|
||||
- [Chrome Policy Schema Table](#chrome-policy-schema-table)
|
||||
@@ -356,6 +358,22 @@ gam redirect csv ChromePolicies.csv print chromepolicies ou "/Path/To/OU1" forma
|
||||
gam config csv_input_row_filter "direct:boolean:true" csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" ou "/Path/To/OU2"
|
||||
```
|
||||
|
||||
## Copy simple and complex policies set directly in one OU to multiple other OUs
|
||||
Display direct policies, update all
|
||||
```
|
||||
gam redirect csv ChromePolicies.csv print chromepolicies ou "/Path/To/OU1" show direct formatjson quotechar "'"
|
||||
```
|
||||
Make a batch file (SetPolicies.bat) with a line for each target OU
|
||||
```
|
||||
gam csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" ou "/Path/To/OU2"
|
||||
gam csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" ou "/Path/To/OU3"
|
||||
...
|
||||
```
|
||||
Execute batch
|
||||
```
|
||||
gam redirect stdout ./SetPolicies.log multiprocess redirect stderr stdout tbatch SetPolicies.bat
|
||||
```
|
||||
|
||||
## Copy simple policies in one Group to another Group
|
||||
Display all policies, update all
|
||||
```
|
||||
@@ -369,6 +387,22 @@ gam redirect csv ChromePolicies.csv print chromepolicies group group1@domain.com
|
||||
gam csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" group group2@domain.com
|
||||
```
|
||||
|
||||
## Copy simple and complex policies in one Group to multiple other Groups
|
||||
Display all policies, update all
|
||||
```
|
||||
gam redirect csv ChromePolicies.csv print chromepolicies group group1@domain.com formatjson quotechar "'"
|
||||
```
|
||||
Make a batch file (SetPolicies.bat) with a line for each target group
|
||||
```
|
||||
gam csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" group group2@domain.com
|
||||
gam csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" group group3@domain.com
|
||||
...
|
||||
```
|
||||
Execute batch
|
||||
```
|
||||
gam redirect stdout ./SetPolicies.log multiprocess redirect stderr stdout tbatch SetPolicies.bat
|
||||
```
|
||||
|
||||
## Create Chrome network
|
||||
See: [Chrome Policy Schema Table](#chrome-policy-schema-table) for the allowed network settings.
|
||||
* chrome.networks.ethernet.Details: Ethernet network configuration details.
|
||||
|
||||
@@ -10,6 +10,26 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
|
||||
|
||||
See [Downloads-Installs](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads-Installs) for Windows or other options, including manual installation
|
||||
|
||||
### 7.00.02
|
||||
|
||||
Added option `showlastmodification` to `gam <UserTypeEntity> print|show filecounts` that adds
|
||||
the following fields to the output: `lastModifiedFileId,lastModifiedFileName,lastModifyingUser,lastModifiedTime`;
|
||||
these are for the most recently modified file.
|
||||
|
||||
Added option `keepforever [<Boolean>]` to `gam <UserTypeEntity> update filerevisions` that allows setting
|
||||
`Keep forever` in revisions.
|
||||
|
||||
Upgraded to Python 3.12.6 where possible.
|
||||
|
||||
### 7.00.01
|
||||
|
||||
Added option `shownames` to `gam <UserTypeEntity> print|show sheet` that causes GAM
|
||||
to make an additional API call to get and display the sheet file name that is not supplied by the Sheets API.
|
||||
|
||||
### 7.00.00
|
||||
|
||||
Merged GAM-Team version
|
||||
|
||||
### 6.81.02
|
||||
|
||||
Updated `gam update group postmaster@domain.com` to handle the error that is generated.
|
||||
|
||||
@@ -251,7 +251,7 @@ writes the credentials into the file oauth2.txt.
|
||||
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
|
||||
admin@server:/Users/admin$ gam version
|
||||
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
|
||||
GAMADV-XTD3 6.81.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||
GAMADV-XTD3 7.00.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||
Ross Scroggs <ross.scroggs@gmail.com>
|
||||
Python 3.12.5 64-bit final
|
||||
MacOS Sonoma 14.5 x86_64
|
||||
@@ -923,7 +923,7 @@ writes the credentials into the file oauth2.txt.
|
||||
C:\>del C:\GAMConfig\oauth2.txt
|
||||
C:\>gam version
|
||||
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
|
||||
GAMADV-XTD3 6.81.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||
GAMADV-XTD3 7.00.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||
Ross Scroggs <ross.scroggs@gmail.com>
|
||||
Python 3.12.5 64-bit final
|
||||
Windows-10-10.0.17134 AMD64
|
||||
|
||||
@@ -693,7 +693,8 @@ gam <UserTypeEntity> print filecounts [todrive <ToDriveAttribute>*]
|
||||
[filenamematchpattern <RegularExpression>]
|
||||
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||
[excludetrashed]
|
||||
[showsize] [showmimetypesize] (addcsvdata <FieldName> <String>)*
|
||||
[showsize] [showmimetypesize] [showlastmodification]
|
||||
(addcsvdata <FieldName> <String>)*
|
||||
[summary none|only|plus] [summaryuser <String>]
|
||||
gam <UserTypeEntity> show filecounts
|
||||
[((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>)
|
||||
@@ -707,13 +708,13 @@ gam <UserTypeEntity> show filecounts
|
||||
[filenamematchpattern <RegularExpression>]
|
||||
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||
[excludetrashed]
|
||||
[showsize] [showmimetypesize]
|
||||
[showsize] [showmimetypesize] [showlastmodification]
|
||||
[summary none|only|plus] [summaryuser <String>]
|
||||
```
|
||||
|
||||
By default, print filecounts displays counts of all files owned by the specified [`<UserTypeEntity>`](Collections-of-Users).
|
||||
|
||||
The option `continueoninvalidquery [<Boolean>] can be used in special cases where a query of the form
|
||||
The option `continueoninvalidquery [<Boolean>] can be used in special cases where a query of the form
|
||||
`query "'labels/mRoha85IbwCRl490E00xGLvBsSbkwIiuZ6PRNNEbwxyz' in labels" causes Google to issue an error
|
||||
saying that the query is invalid when, in fact, it is but the user does not have a license that suppprts drive file labels.
|
||||
When `continueoninvalidquery` is true, GAM prints an error message and proceeds to the next user rather that terminating
|
||||
@@ -723,6 +724,10 @@ The `showsize` option displays the total size (in bytes) of the files counted.
|
||||
|
||||
The showmimetypesize' displays the total size (in bytes) of each MIME type counted.
|
||||
|
||||
The option `showlastmodification` displays the following fields:
|
||||
`lastModifiedFileId,lastModifiedFileName,lastModifyingUser,lastModifiedTime`;
|
||||
these are for the most recently modified file.
|
||||
|
||||
For print filecouts, add additional columns of data from the command line to the output:
|
||||
* `addcsvdata <FieldName> <String>` - Add additional columns of data from the command line to the output
|
||||
|
||||
|
||||
@@ -85,6 +85,8 @@ gam <UserTypeEntity> update filerevisions <DriveFileEntity> select <DriveFileRev
|
||||
```
|
||||
When `select <DriveFileRevisionIDEntity>` is omitted, all revisions are updated.
|
||||
|
||||
* `keepforever true` - Keep revision forever, even if it is no longer the head revision
|
||||
* `keepforever false` - Do not keep revision forever
|
||||
* `published true` - Publish these revision to the web
|
||||
* `published false` - Do not publish these revision to the web
|
||||
* `publishauto true` - Automaticaly publish subsequent revisions to the web
|
||||
|
||||
@@ -231,18 +231,24 @@ gam user testuser@domain.com update sheet <DriveFileItem> json file Sheet.json
|
||||
gam <UserTypeEntity> info|show sheet <DriveFileEntity>
|
||||
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||
[includegriddata [<Boolean>]]
|
||||
[includegriddata [<Boolean>]] [shownames]
|
||||
[formatjson]
|
||||
```
|
||||
By default, the Sheets API does not return the sheet file name, use the `shownames` option to have GAM
|
||||
make an additional API call to get and display the sheet file name.
|
||||
|
||||
The output is formatted for human readability. Use the following option to produce JSON output for program parsing.
|
||||
* `formatjson` - Display output in JSON format.
|
||||
```
|
||||
gam <UserTypeEntity> print sheet <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
||||
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||
[includegriddata [<Boolean>]]
|
||||
[includegriddata [<Boolean>]] [shownames]
|
||||
[formatjson [quotechar <Character>]]
|
||||
```
|
||||
By default, the Sheets API does not return the sheet file name, use the `shownames` option to have GAM
|
||||
make an additional API call to get and display the sheet file name.
|
||||
|
||||
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
|
||||
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
|
||||
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Print the current version of Gam with details
|
||||
```
|
||||
gam version
|
||||
GAMADV-XTD3 6.81.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||
GAMADV-XTD3 7.00.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||
Ross Scroggs <ross.scroggs@gmail.com>
|
||||
Python 3.12.5 64-bit final
|
||||
MacOS Sonoma 14.5 x86_64
|
||||
@@ -15,7 +15,7 @@ Time: 2023-06-02T21:10:00-07:00
|
||||
Print the current version of Gam with details and time offset information
|
||||
```
|
||||
gam version timeoffset
|
||||
GAMADV-XTD3 6.81.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||
GAMADV-XTD3 7.00.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||
Ross Scroggs <ross.scroggs@gmail.com>
|
||||
Python 3.12.5 64-bit final
|
||||
MacOS Sonoma 14.5 x86_64
|
||||
@@ -27,7 +27,7 @@ Your system time differs from www.googleapis.com by less than 1 second
|
||||
Print the current version of Gam with extended details and SSL information
|
||||
```
|
||||
gam version extended
|
||||
GAMADV-XTD3 6.81.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||
GAMADV-XTD3 7.00.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||
Ross Scroggs <ross.scroggs@gmail.com>
|
||||
Python 3.12.5 64-bit final
|
||||
MacOS Sonoma 14.5 x86_64
|
||||
@@ -64,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
|
||||
Path: /Users/Admin/bin/gamadv-xtd3
|
||||
Version Check:
|
||||
Current: 5.35.08
|
||||
Latest: 6.81.02
|
||||
Latest: 7.00.02
|
||||
echo $?
|
||||
1
|
||||
```
|
||||
@@ -72,7 +72,7 @@ echo $?
|
||||
Print the current version number without details
|
||||
```
|
||||
gam version simple
|
||||
6.81.02
|
||||
7.00.02
|
||||
```
|
||||
In Linux/MacOS you can do:
|
||||
```
|
||||
@@ -82,7 +82,7 @@ echo $VER
|
||||
Print the current version of Gam and address of this Wiki
|
||||
```
|
||||
gam help
|
||||
GAM 6.81.02 - https://github.com/taers232c/GAMADV-XTD3
|
||||
GAM 7.00.02 - https://github.com/taers232c/GAMADV-XTD3
|
||||
Ross Scroggs <ross.scroggs@gmail.com>
|
||||
Python 3.12.5 64-bit final
|
||||
MacOS Sonoma 14.5 x86_64
|
||||
|
||||
@@ -3541,11 +3541,11 @@ gam [<UserTypeEntity>] show drivelabels
|
||||
[formatjson] [adminaccess|asadmin]
|
||||
`
|
||||
gam [<UserTypeEntity>] create drivelabelpermission <DriveLabelNameEntity>
|
||||
(user <UserItem>) | (group <GroupItem) | (audience <String>)
|
||||
(user <UserItem>) | (group <GroupItem>) | (audience <String>)
|
||||
role applier|editor|organizer|reader
|
||||
[formatjson] [adminaccess|asadmin]
|
||||
gam [<UserTypeEntity>] delete drivelabelpermission <DriveLabelNameEntity>
|
||||
(user <UserItem>) | (group <GroupItem) | (audience <String>)
|
||||
(user <UserItem>) | (group <GroupItem>) | (audience <String>)
|
||||
[adminaccess|asadmin]
|
||||
gam [<UserTypeEntity>] remove drivelabelpermission <DriveLabelPermissionNameEntity>
|
||||
[adminaccess|asadmin]
|
||||
@@ -7043,7 +7043,8 @@ gam <UserTypeEntity> print filecounts [todrive <ToDriveAttribute>*]
|
||||
[filenamematchpattern <RegularExpression>]
|
||||
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||
[excludetrashed]
|
||||
[showsize] [showmimetypesize] (addcsvdata <FieldName> <String>)*
|
||||
[showsize] [showmimetypesize] [showlastmodification]
|
||||
(addcsvdata <FieldName> <String>)*
|
||||
[summary none|only|plus] [summaryuser <String>]
|
||||
gam <UserTypeEntity> show filecounts
|
||||
[((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>)
|
||||
@@ -7052,12 +7053,12 @@ gam <UserTypeEntity> show filecounts
|
||||
[corpora <CorporaAttribute>]
|
||||
[select <SharedDriveEntity>]
|
||||
[anyowner|(showownedby any|me|others)]
|
||||
[showmimetype [not] <MimeTypeList>] [`<showmimetype category <MimeTypeNameList>]
|
||||
[showmimetype [not] <MimeTypeList>] [showmimetype category <MimeTypeNameList>]
|
||||
[sizefield quotabytesused|size] [minimumfilesize <Integer>] [maximumfilesize <Integer>]
|
||||
[filenamematchpattern <RegularExpression>]
|
||||
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||
[excludetrashed]
|
||||
[showsize] [showmimetypesize]
|
||||
[showsize] [showmimetypesize] [showlastmodification]
|
||||
[summary none|only|plus] [summaryuser <String>]
|
||||
|
||||
gam <UserTypeEntity> print filesharecounts [todrive <ToDriveAttribute>*]
|
||||
@@ -8244,12 +8245,12 @@ gam <UserTypeEntity> update sheet <DriveFileEntity>
|
||||
gam <UserTypeEntity> info|show sheet <DriveFileEntity>
|
||||
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||
[includegriddata [<Boolean>]]
|
||||
[includegriddata [<Boolean>]] [shownames]
|
||||
[formatjson]
|
||||
gam <UserTypeEntity> print sheet <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
||||
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||
[includegriddata [<Boolean>]]
|
||||
[includegriddata [<Boolean>]] [shownames]
|
||||
[formatjson [quotechar <Character>]]
|
||||
|
||||
See: https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values#ValueRange
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
7.00.02
|
||||
|
||||
Added option `showlastmodification` to `gam <UserTypeEntity> print|show filecounts` that adds
|
||||
the following fields to the output: `lastModifiedFileId,lastModifiedFileName,lastModifyingUser,lastModifiedTime`;
|
||||
these are for the most recently modified file.
|
||||
|
||||
Added option `keepforever [<Boolean>]` to `gam <UserTypeEntity> update filerevisions` that allows setting
|
||||
`Keep forever` in revisions.
|
||||
|
||||
Upgraded to Python 3.12.6 where possible.
|
||||
|
||||
7.00.01
|
||||
|
||||
Added option `shownames` to `gam <UserTypeEntity> print|show sheet` that causes GAM
|
||||
to make an additional API call to get and display the sheet file name that is not supplied by the Sheets API.
|
||||
|
||||
7.00.00
|
||||
|
||||
Merged GAM-Team version
|
||||
|
||||
12
src/add_lib.py
Normal file
12
src/add_lib.py
Normal file
@@ -0,0 +1,12 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
'''
|
||||
for onedir, add_lib.py allows moving many
|
||||
library files into a lib/ directory to make
|
||||
onedir cleaner. Thanks to:
|
||||
https://medium.com/@philipp.h/reduce-clutter-when-using-pyinstaller-in -one-directory-mode-b631b9f7f89b
|
||||
'''
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), 'lib'))
|
||||
sys._MEIPASS=os.path.join(sys._MEIPASS, 'lib')
|
||||
@@ -16,7 +16,7 @@ OPTIONS:
|
||||
-u Admin user email address to use with GAM. Default is to prompt.
|
||||
-r Regular user email address. Used to test service account access to user data. Default is to prompt.
|
||||
-v Version to install (latest, prerelease, draft, 3.8, etc). Default is latest.
|
||||
-s Strip gam7 component from extracted files, files will be downloaded directly to $target_dir
|
||||
-s Strip gam component from extracted files, files will be downloaded directly to $target_dir
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ upgrade_only=false
|
||||
gamversion="latest"
|
||||
adminuser=""
|
||||
regularuser=""
|
||||
gam_x86_64_glibc_vers="2.31"
|
||||
gam_x86_64_glibc_vers="2.35 2.31"
|
||||
gam_arm64_glibc_vers="2.31"
|
||||
strip_gam="--strip-components 0"
|
||||
|
||||
@@ -172,7 +172,9 @@ case $gamos in
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$gamversion" == "latest" -o "$gamversion" == "prerelease" -o "$gamversion" == "draft" ]; then
|
||||
if [ "$gamversion" == "latest" ]; then
|
||||
release_url="https://api.github.com/repos/GAM-team/GAM/releases/latest"
|
||||
elif [ "$gamversion" == "prerelease" -o "$gamversion" == "draft" ]; then
|
||||
release_url="https://api.github.com/repos/GAM-team/GAM/releases"
|
||||
else
|
||||
release_url="https://api.github.com/repos/GAM-team/GAM/releases/tags/v$gamversion"
|
||||
|
||||
78
src/gam.spec
78
src/gam.spec
@@ -21,7 +21,7 @@ hiddenimports = [
|
||||
'gam.gamlib.yubikey',
|
||||
]
|
||||
|
||||
print(f"datas before analysis:\n{datas}")
|
||||
runtime_hooks = []
|
||||
a = Analysis(
|
||||
['gam/__main__.py'],
|
||||
pathex=[],
|
||||
@@ -30,7 +30,7 @@ a = Analysis(
|
||||
hiddenimports=hiddenimports,
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
runtime_hooks=runtime_hooks,
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
@@ -48,12 +48,17 @@ pyz = PYZ(a.pure,
|
||||
cipher=None)
|
||||
# requires Python 3.10+ but no one should be compiling
|
||||
# GAM with older versions anyway
|
||||
target_arch = None
|
||||
codesign_identity = None
|
||||
entitlements_file = None
|
||||
match platform:
|
||||
case "darwin":
|
||||
if getenv('arch') == 'universal2':
|
||||
target_arch = "universal2"
|
||||
else:
|
||||
target_arch = None
|
||||
|
||||
codesign_identity = getenv('codesign_identity')
|
||||
if codesign_identity:
|
||||
entitlements_file = '../.github/actions/entitlements.plist'
|
||||
strip = True
|
||||
case "win32":
|
||||
target_arch = None
|
||||
@@ -68,9 +73,38 @@ upx = False
|
||||
console = True
|
||||
disable_windowed_traceback = False
|
||||
argv_emulation = False
|
||||
codesign_identity = None
|
||||
entitlements_file = None
|
||||
if not getenv('PYINSTALLER_BUILD_ONEDIR') == 'yes':
|
||||
if getenv('PYINSTALLER_BUILD_ONEDIR') == 'yes':
|
||||
# Build one directory
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name=name,
|
||||
debug=debug,
|
||||
bootloader_ignore_signals=bootloader_ignore_signals,
|
||||
strip=strip,
|
||||
upx=upx,
|
||||
console=console,
|
||||
# put most everyting under a lib/ subfolder
|
||||
contents_directory='lib',
|
||||
disable_windowed_traceback=disable_windowed_traceback,
|
||||
argv_emulation=argv_emulation,
|
||||
target_arch=target_arch,
|
||||
codesign_identity=codesign_identity,
|
||||
entitlements_file=entitlements_file,
|
||||
)
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=strip,
|
||||
upx=upx,
|
||||
upx_exclude=[],
|
||||
name=name,
|
||||
)
|
||||
else:
|
||||
# Build one file
|
||||
exe = EXE(
|
||||
pyz,
|
||||
@@ -91,32 +125,4 @@ if not getenv('PYINSTALLER_BUILD_ONEDIR') == 'yes':
|
||||
codesign_identity=codesign_identity,
|
||||
entitlements_file=entitlements_file,
|
||||
)
|
||||
else:
|
||||
# Build one folder
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name=name,
|
||||
debug=debug,
|
||||
bootloader_ignore_signals=bootloader_ignore_signals,
|
||||
strip=strip,
|
||||
upx=upx,
|
||||
console=console,
|
||||
disable_windowed_traceback=disable_windowed_traceback,
|
||||
argv_emulation=argv_emulation,
|
||||
target_arch=target_arch,
|
||||
codesign_identity=codesign_identity,
|
||||
entitlements_file=entitlements_file,
|
||||
)
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=strip,
|
||||
upx=upx,
|
||||
upx_exclude=[],
|
||||
name=name,
|
||||
)
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
|
||||
"""
|
||||
|
||||
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
|
||||
__version__ = '7.00.00'
|
||||
__version__ = '7.00.02'
|
||||
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||
|
||||
#pylint: disable=wrong-import-position
|
||||
@@ -53967,12 +53967,14 @@ def deleteFileRevisions(users):
|
||||
Ind.Decrement()
|
||||
|
||||
REVISIONS_FIELDS_CHOICE_MAP = {
|
||||
'keepforever': 'keepForever',
|
||||
'published': 'published',
|
||||
'publishauto': 'publishAuto',
|
||||
'publishedoutsidedomain': 'publishedOutsideDomain'
|
||||
}
|
||||
# gam <UserTypeEntity> update filerevisions <DriveFileEntity> select <DriveFileRevisionIdEntity> [previewupdate]
|
||||
# [published [<Boolean>]] [publishauto [<Boolean>]] [publishedoutsidedomain [<Boolean>]]
|
||||
# [keepforever [<Boolean>]}
|
||||
# [showtitles] [doit] [max_to_update <Number>]
|
||||
def updateFileRevisions(users):
|
||||
fileIdEntity = getDriveFileEntity()
|
||||
@@ -56118,7 +56120,8 @@ def printFileParentTree(users):
|
||||
# [filenamematchpattern <RegularExpression>]
|
||||
# <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||
# [excludetrashed] (addcsvdata <FieldName> <String>)*
|
||||
# [showsize] [showmimetypesize]
|
||||
# [showsize] [showmimetypesize] [showlastmodification]
|
||||
# (addcsvdata <FieldName> <String>)*
|
||||
# [summary none|only|plus] [summaryuser <String>]
|
||||
# gam <UserTypeEntity> show filecounts
|
||||
# [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime<String> <Time>)*]
|
||||
@@ -56131,7 +56134,7 @@ def printFileParentTree(users):
|
||||
# [filenamematchpattern <RegularExpression>]
|
||||
# <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||
# [excludetrashed]
|
||||
# [showsize] [showmimetypesize]
|
||||
# [showsize] [showmimetypesize] [showlastmodification]
|
||||
# [summary none|only|plus] [summaryuser <String>]
|
||||
def printShowFileCounts(users):
|
||||
def _setSelectionFields():
|
||||
@@ -56139,6 +56142,8 @@ def printShowFileCounts(users):
|
||||
fieldsList.extend(OWNED_BY_ME_FIELDS_TITLES)
|
||||
if showSize or (DLP.minimumFileSize is not None) or (DLP.maximumFileSize is not None):
|
||||
fieldsList.append(sizeField)
|
||||
if showLastModification:
|
||||
fieldsList.extend(['id,name,modifiedTime,lastModifyingUser(emailAddress)'])
|
||||
if DLP.filenameMatchPattern:
|
||||
fieldsList.append('name')
|
||||
if DLP.excludeTrashed:
|
||||
@@ -56148,7 +56153,7 @@ def printShowFileCounts(users):
|
||||
if DLP.onlySharedDrives or getPermissionsForSharedDrives:
|
||||
fieldsList.append('driveId')
|
||||
|
||||
def showMimeTypeInfo(user, mimeTypeInfo, sharedDriveId, sharedDriveName, i, count):
|
||||
def showMimeTypeInfo(user, mimeTypeInfo, sharedDriveId, sharedDriveName, lastModification, i, count):
|
||||
if summary != FILECOUNT_SUMMARY_NONE:
|
||||
if count != 0:
|
||||
for mimeType, mtinfo in iter(mimeTypeInfo.items()):
|
||||
@@ -56173,6 +56178,10 @@ def printShowFileCounts(users):
|
||||
dataList.extend(['Item cap', f"{countTotal/SHARED_DRIVE_MAX_FILES_FOLDERS:.2%}"])
|
||||
printEntityKVList(kvList, dataList, i, count)
|
||||
Ind.Increment()
|
||||
if showLastModification:
|
||||
printKeyValueList(['lastModifiedFile', f"{lastModification['lastModifiedFileName']}({lastModification['lastModifiedFileId']})",
|
||||
'lastModifyingUser', lastModification['lastModifyingUser'],
|
||||
'lastModifiedTime', formatLocalTime(lastModification['lastModifiedTime'])])
|
||||
for mimeType, mtinfo in sorted(iter(mimeTypeInfo.items())):
|
||||
if not showMimeTypeSize:
|
||||
printKeyValueList([mimeType, mtinfo['count']])
|
||||
@@ -56186,6 +56195,11 @@ def printShowFileCounts(users):
|
||||
row = {'User': user, 'Total': countTotal}
|
||||
if showSize:
|
||||
row['Size'] = sizeTotal
|
||||
if showLastModification:
|
||||
row.update({'lastModifiedFileId': lastModification['lastModifiedFileId'],
|
||||
'lastModifiedFileName': lastModification['lastModifiedFileName'],
|
||||
'lastModifyingUser': lastModification['lastModifyingUser'],
|
||||
'lastModifiedTime': formatLocalTime(lastModification['lastModifiedTime'])})
|
||||
if addCSVData:
|
||||
row.update(addCSVData)
|
||||
for mimeType, mtinfo in sorted(iter(mimeTypeInfo.items())):
|
||||
@@ -56200,13 +56214,16 @@ def printShowFileCounts(users):
|
||||
fieldsList = ['mimeType']
|
||||
DLP = DriveListParameters({'allowChoose': False, 'allowCorpora': True, 'allowQuery': True, 'mimeTypeInQuery': True})
|
||||
sharedDriveId = sharedDriveName = ''
|
||||
continueOnInvalidQuery = showSize = showMimeTypeSize = False
|
||||
continueOnInvalidQuery = showSize = showLastModification = showMimeTypeSize = False
|
||||
sizeField = 'quotaBytesUsed'
|
||||
summary = FILECOUNT_SUMMARY_NONE
|
||||
summaryUser = FILECOUNT_SUMMARY_USER
|
||||
summaryMimeTypeInfo = {}
|
||||
fileIdEntity = {}
|
||||
addCSVData = {}
|
||||
summaryLastModification = {
|
||||
'lastModifiedFileId': '', 'lastModifiedFileName': '',
|
||||
'lastModifyingUser': '', 'lastModifiedTime': NEVER_TIME}
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
if csvPF and myarg == 'todrive':
|
||||
@@ -56221,6 +56238,8 @@ def printShowFileCounts(users):
|
||||
showSize = True
|
||||
elif myarg == 'sizefield':
|
||||
sizeField = getChoice(SIZE_FIELD_CHOICE_MAP, mapChoice=True)
|
||||
elif myarg == 'showlastmodification':
|
||||
showLastModification = True
|
||||
elif myarg == 'showmimetypesize':
|
||||
showMimeTypeSize = showSize = True
|
||||
elif myarg == 'summary':
|
||||
@@ -56252,6 +56271,8 @@ def printShowFileCounts(users):
|
||||
sortTitles = ['User', 'id', 'name', 'Total', 'Item cap'] if fileIdEntity.get('shareddrive') else ['User', 'Total']
|
||||
if showSize:
|
||||
sortTitles.insert(sortTitles.index('Total')+1, 'Size')
|
||||
if showLastModification:
|
||||
sortTitles.extend(['lastModifiedFileId', 'lastModifiedFileName', 'lastModifyingUser', 'lastModifiedTime'])
|
||||
if addCSVData:
|
||||
sortTitles.extend(sorted(addCSVData.keys()))
|
||||
csvPF.SetTitles(sortTitles)
|
||||
@@ -56269,6 +56290,9 @@ def printShowFileCounts(users):
|
||||
else:
|
||||
sharedDriveName = ''
|
||||
mimeTypeInfo = {}
|
||||
userLastModification = {
|
||||
'lastModifiedFileId': '', 'lastModifiedFileName': '',
|
||||
'lastModifyingUser': '', 'lastModifiedTime': NEVER_TIME}
|
||||
printGettingAllEntityItemsForWhom(Ent.DRIVE_FILE_OR_FOLDER, user, i, count, query=DLP.fileIdEntity['query'])
|
||||
try:
|
||||
feed = yieldGAPIpages(drive.files(), 'list', 'files',
|
||||
@@ -56309,7 +56333,15 @@ def printShowFileCounts(users):
|
||||
mimeTypeInfo.setdefault(f_file['mimeType'], {'count': 0, 'size': 0})
|
||||
mimeTypeInfo[f_file['mimeType']]['count'] += 1
|
||||
mimeTypeInfo[f_file['mimeType']]['size'] += int(f_file.get(sizeField, '0'))
|
||||
showMimeTypeInfo(user, mimeTypeInfo, sharedDriveId, sharedDriveName, i, count)
|
||||
if showLastModification:
|
||||
if f_file.get('modifiedTime', NEVER_TIME) > userLastModification['lastModifiedTime'] and 'lastModifyingUser' in f_file:
|
||||
userLastModification['lastModifiedFileId'] = f_file['id']
|
||||
userLastModification['lastModifiedFileName'] = _stripControlCharsFromName(f_file['name'])
|
||||
userLastModification['lastModifiedTime'] = f_file['modifiedTime']
|
||||
userLastModification['lastModifyingUser'] = f_file['lastModifyingUser'].get('emailAddress', UNKNOWN)
|
||||
showMimeTypeInfo(user, mimeTypeInfo, sharedDriveId, sharedDriveName, userLastModification, i, count)
|
||||
if showLastModification and userLastModification['lastModifiedTime'] > summaryLastModification['lastModifiedTime']:
|
||||
summaryLastModification = userLastModification.copy()
|
||||
except (GAPI.invalidQuery, GAPI.invalid, GAPI.badRequest):
|
||||
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER, None], invalidQuery(DLP.fileIdEntity['query']), i, count)
|
||||
if not continueOnInvalidQuery:
|
||||
@@ -56324,7 +56356,9 @@ def printShowFileCounts(users):
|
||||
continue
|
||||
if summary != FILECOUNT_SUMMARY_NONE:
|
||||
showMimeTypeInfo(summaryUser, summaryMimeTypeInfo,
|
||||
'' if count > 1 else sharedDriveId, '' if count > 1 else sharedDriveName, 0, 0)
|
||||
'' if count > 1 else sharedDriveId,
|
||||
'' if count > 1 else sharedDriveName,
|
||||
summaryLastModification, 0, 0)
|
||||
if csvPF:
|
||||
csvPF.writeCSVfile('Drive File Counts')
|
||||
|
||||
@@ -66995,14 +67029,14 @@ SPREADSHEET_SHEETS_SUBFIELDS_CHOICE_MAP = {
|
||||
}
|
||||
|
||||
# gam <UserTypeEntity> info|show sheet <DriveFileEntity>
|
||||
# [fields <SpreadsheetFieldList>]
|
||||
# [fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||
# (range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||
# [includegriddata [<Boolean>]]
|
||||
# [includegriddata [<Boolean>]] [shownames]
|
||||
# [formatjson]
|
||||
# gam <UserTypeEntity> print sheet <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
||||
# [fields <SpreadsheetFieldList>]
|
||||
# [fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||
# (range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||
# [includegriddata [<Boolean>]]
|
||||
# [includegriddata [<Boolean>]] [shownames]
|
||||
# [formatjson [quotechar <Character>]]
|
||||
def infoPrintShowSheets(users):
|
||||
csvPF = CSVPrintFile(['User', 'spreadsheetId'], 'sortall') if Act.csvFormat() else None
|
||||
@@ -67010,7 +67044,7 @@ def infoPrintShowSheets(users):
|
||||
spreadsheetIdEntity = getDriveFileEntity()
|
||||
fieldsList = []
|
||||
ranges = []
|
||||
includeGridData = False
|
||||
includeGridData = showSheetNames = False
|
||||
while Cmd.ArgumentsRemaining():
|
||||
myarg = getArgument()
|
||||
if csvPF and myarg == 'todrive':
|
||||
@@ -67029,8 +67063,16 @@ def infoPrintShowSheets(users):
|
||||
fieldsList.append(SPREADSHEET_SHEETS_SUBFIELDS_CHOICE_MAP[field])
|
||||
else:
|
||||
invalidChoiceExit(field, SPREADSHEET_SHEETS_SUBFIELDS_CHOICE_MAP, True)
|
||||
elif myarg == 'shownames':
|
||||
showSheetNames = True
|
||||
else:
|
||||
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
||||
if csvPF and showSheetNames:
|
||||
csvPF.AddTitles('spreadsheetName')
|
||||
csvPF.SetSortAllTitles()
|
||||
if FJQC.formatJSON:
|
||||
csvPF.AddJSONTitles('spreadsheetName')
|
||||
csvPF.MoveJSONTitlesToEnd(['JSON'])
|
||||
if includeGridData and fieldsList:
|
||||
fieldsList.append(SPREADSHEET_SHEETS_SUBFIELDS_CHOICE_MAP['data'])
|
||||
fields = getFieldsFromFieldsList(fieldsList)
|
||||
@@ -67040,6 +67082,10 @@ def infoPrintShowSheets(users):
|
||||
user, sheet, jcount = _validateUserGetSpreadsheetIDs(user, i, count, spreadsheetIdEntity, not FJQC.formatJSON)
|
||||
if jcount == 0:
|
||||
continue
|
||||
if showSheetNames:
|
||||
_, drive = buildGAPIServiceObject(API.DRIVE3, user, i, count)
|
||||
if not drive:
|
||||
continue
|
||||
Ind.Increment()
|
||||
j = 0
|
||||
for spreadsheetId in spreadsheetIdEntity['list']:
|
||||
@@ -67051,11 +67097,25 @@ def infoPrintShowSheets(users):
|
||||
if not includeGridData and 'sheets' in result:
|
||||
for usheet in result['sheets']:
|
||||
usheet.pop('data', None)
|
||||
if showSheetNames:
|
||||
try:
|
||||
spreadsheetName = callGAPI(drive.files(), 'get',
|
||||
throwReasons=GAPI.DRIVE_GET_THROW_REASONS,
|
||||
fileId=spreadsheetId, fields='name', supportsAllDrives=True)['name']
|
||||
except (GAPI.fileNotFound, GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy):
|
||||
spreadsheetName = spreadsheetId
|
||||
if not csvPF:
|
||||
if FJQC.formatJSON:
|
||||
printLine('{'+f'"User": "{user}", "spreadsheetId": "{spreadsheetId}", "JSON": {json.dumps(result, ensure_ascii=False, sort_keys=False)}'+'}')
|
||||
baserow = {'User': user, 'spreadsheetId': spreadsheetId}
|
||||
if showSheetNames:
|
||||
baserow['spreadsheetName'] = spreadsheetName
|
||||
baserow['JSON'] = result
|
||||
printLine(json.dumps(baserow, ensure_ascii=False, sort_keys=False)+'\n')
|
||||
continue
|
||||
printEntity([Ent.SPREADSHEET, spreadsheetId], j, jcount)
|
||||
if showSheetNames:
|
||||
printEntity([Ent.SPREADSHEET, f'{spreadsheetName}({spreadsheetId})'], j, jcount)
|
||||
else:
|
||||
printEntity([Ent.SPREADSHEET, spreadsheetId], j, jcount)
|
||||
Ind.Increment()
|
||||
if 'spreadsheetUrl' in result:
|
||||
printKeyValueList(['spreadsheetUrl', result['spreadsheetUrl']])
|
||||
@@ -67074,12 +67134,15 @@ def infoPrintShowSheets(users):
|
||||
Ind.Decrement()
|
||||
Ind.Decrement()
|
||||
else:
|
||||
row = flattenJSON(result, flattened={'User': user, 'spreadsheetId': spreadsheetId})
|
||||
baserow = {'User': user, 'spreadsheetId': spreadsheetId}
|
||||
if showSheetNames:
|
||||
baserow['spreadsheetName'] = spreadsheetName
|
||||
row = flattenJSON(result, flattened=baserow.copy())
|
||||
if not FJQC.formatJSON:
|
||||
csvPF.WriteRowTitles(row)
|
||||
elif csvPF.CheckRowTitles(row):
|
||||
csvPF.WriteRowNoFilter({'User': user, 'spreadsheetId': spreadsheetId,
|
||||
'JSON': json.dumps(result, ensure_ascii=False, sort_keys=False)})
|
||||
baserow['JSON'] = json.dumps(cleanJSON(result), ensure_ascii=False, sort_keys=False)
|
||||
csvPF.WriteRowNoFilter(baserow)
|
||||
except (GAPI.notFound, GAPI.forbidden, GAPI.permissionDenied,
|
||||
GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.badRequest,
|
||||
GAPI.invalid, GAPI.invalidArgument, GAPI.failedPrecondition) as e:
|
||||
|
||||
Reference in New Issue
Block a user