mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-28 18:01:36 +00:00
Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4677585bb | ||
|
|
3a1437872c | ||
|
|
602dce2f5a | ||
|
|
8ce930f01b | ||
|
|
9631882be0 | ||
|
|
32d2858e4b | ||
|
|
98370925e7 | ||
|
|
1ef5d030f6 | ||
|
|
d50b5fb61e | ||
|
|
e070e92be2 | ||
|
|
b3b6fff2f1 | ||
|
|
fea94fcc1c | ||
|
|
a0cd228110 | ||
|
|
acfcd8b723 | ||
|
|
a26494e5c6 | ||
|
|
5605e5d1b6 | ||
|
|
e0fdac6e17 | ||
|
|
53dc8e3265 | ||
|
|
993a0b403e | ||
|
|
2d7d118d32 | ||
|
|
f2bc704fd6 | ||
|
|
46e0c85308 | ||
|
|
9221d075fe | ||
|
|
12b84a5fcf | ||
|
|
6d411972ac | ||
|
|
d665a66d3e | ||
|
|
b2a340d99d | ||
|
|
c76164fbef | ||
|
|
3d22891052 | ||
|
|
48de06613f | ||
|
|
4d1879a9a8 | ||
|
|
454caa5a76 | ||
|
|
12ffa7e823 | ||
|
|
8fc41cbc64 | ||
|
|
dd16c29ee7 | ||
|
|
1a24b4c855 | ||
|
|
f9dfc7d094 | ||
|
|
bc64a292c3 | ||
|
|
524ef0df55 | ||
|
|
38f7f39b44 | ||
|
|
183e40ef4e | ||
|
|
ba43c4ea5f | ||
|
|
70c88dacf3 | ||
|
|
cc883b6bb7 | ||
|
|
4c320110b3 | ||
|
|
fe7c46e04d | ||
|
|
5b1c3a3a46 | ||
|
|
ce728a991f | ||
|
|
502bda4fe9 | ||
|
|
3f3d882c74 | ||
|
|
a1948eb3ca | ||
|
|
f0fb6336d1 | ||
|
|
71e5ef2399 | ||
|
|
9d9698a669 | ||
|
|
eeb180f1f2 | ||
|
|
6079ab20b3 | ||
|
|
6189ca92ab | ||
|
|
33b60c4b14 | ||
|
|
0c5f747c36 | ||
|
|
826619857c | ||
|
|
9a2880e411 | ||
|
|
95caeaba5e | ||
|
|
d8ad1b27a4 | ||
|
|
fefeae7c60 | ||
|
|
65f7b82d53 |
102
.github/workflows/build.yml
vendored
102
.github/workflows/build.yml
vendored
@@ -41,78 +41,101 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
jid: 1
|
jid: 1
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
name: Build Intel Ubuntu Jammy
|
name: Build Intel Ubuntu Jammy
|
||||||
- os: ubuntu-24.04
|
- os: ubuntu-24.04
|
||||||
jid: 2
|
jid: 2
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
name: Build Intel Ubuntu Noble
|
name: Build Intel Ubuntu Noble
|
||||||
- os: ubuntu-24.04-arm
|
- os: ubuntu-24.04-arm
|
||||||
jid: 3
|
jid: 3
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
name: Build Arm Ubuntu Noble
|
name: Build Arm Ubuntu Noble
|
||||||
- os: ubuntu-22.04-arm
|
- os: ubuntu-22.04-arm
|
||||||
jid: 4
|
jid: 4
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
name: Build Arm Ubuntu Jammy
|
name: Build Arm Ubuntu Jammy
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
jid: 5
|
jid: 5
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
staticx: yes
|
staticx: yes
|
||||||
name: Build Intel StaticX Legacy
|
name: Build Intel StaticX Legacy
|
||||||
- os: ubuntu-22.04-arm
|
- os: ubuntu-22.04-arm
|
||||||
jid: 6
|
jid: 6
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
staticx: yes
|
staticx: yes
|
||||||
name: Build Arm StaticX Legacy
|
name: Build Arm StaticX Legacy
|
||||||
- os: macos-13
|
- os: macos-13
|
||||||
jid: 7
|
jid: 7
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
name: Build Intel MacOS
|
name: Build Intel MacOS
|
||||||
- os: macos-14
|
- os: macos-14
|
||||||
jid: 8
|
jid: 8
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
name: Build Arm MacOS 14
|
name: Build Arm MacOS 14
|
||||||
- os: macos-15
|
- os: macos-15
|
||||||
jid: 9
|
jid: 9
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
name: Build Arm MacOS 15
|
name: Build Arm MacOS 15
|
||||||
- os: macos-15-intel
|
- os: macos-15-intel
|
||||||
jid: 10
|
jid: 10
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
name: Build x86_64 macOS 15
|
name: Build x86_64 macOS 15
|
||||||
- os: macos-26
|
- os: macos-26
|
||||||
jid: 11
|
jid: 11
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
name: Build Arm MacOS 26
|
name: Build Arm MacOS 26
|
||||||
- os: windows-2025
|
- os: windows-2025
|
||||||
jid: 12
|
jid: 12
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
name: Build Intel Windows
|
name: Build Intel Windows
|
||||||
- os: windows-11-arm
|
- os: windows-11-arm
|
||||||
jid: 13
|
jid: 13
|
||||||
|
freethreaded: false
|
||||||
goal: build
|
goal: build
|
||||||
name: Build Arm Windows
|
name: Build Arm Windows
|
||||||
- os: ubuntu-24.04
|
- os: ubuntu-24.04
|
||||||
goal: test
|
goal: test
|
||||||
python: "3.10"
|
python: "3.10"
|
||||||
|
freethreaded: false
|
||||||
jid: 14
|
jid: 14
|
||||||
name: Test Python 3.10
|
name: Test Python 3.10
|
||||||
- os: ubuntu-24.04
|
- os: ubuntu-24.04
|
||||||
goal: test
|
goal: test
|
||||||
python: "3.11"
|
python: "3.11"
|
||||||
|
freethreaded: false
|
||||||
jid: 15
|
jid: 15
|
||||||
name: Test Python 3.11
|
name: Test Python 3.11
|
||||||
#- os: ubuntu-24.04
|
- os: ubuntu-24.04
|
||||||
# goal: test
|
goal: test
|
||||||
# python: "3.12"
|
python: "3.12"
|
||||||
# jid: 16
|
freethreaded: false
|
||||||
# name: Test Python 3.12
|
jid: 16
|
||||||
#- os: ubuntu-24.04
|
name: Test Python 3.12
|
||||||
# goal: test
|
- os: ubuntu-24.04
|
||||||
# python: "3.14-dev"
|
goal: test
|
||||||
# jid: 16
|
python: "3.14-dev"
|
||||||
# name: Test Python 3.14-dev
|
freethreaded: false
|
||||||
|
jid: 17
|
||||||
|
name: Test Python 3.14-dev
|
||||||
|
- os: ubuntu-24.04
|
||||||
|
goal: test
|
||||||
|
python: "3.14-dev"
|
||||||
|
freethreaded: true
|
||||||
|
jid: 18
|
||||||
|
name: Test Python 3.14-dev freethread
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
@@ -135,7 +158,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
cache.tar.xz
|
cache.tar.xz
|
||||||
key: gam-${{ matrix.jid }}-20250922
|
key: gam-${{ matrix.jid }}-20251002
|
||||||
|
|
||||||
- name: Untar Cache archive
|
- name: Untar Cache archive
|
||||||
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'
|
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'
|
||||||
@@ -145,17 +168,19 @@ jobs:
|
|||||||
|
|
||||||
- name: Use pre-compiled Python for testing
|
- name: Use pre-compiled Python for testing
|
||||||
if: matrix.python != ''
|
if: matrix.python != ''
|
||||||
uses: actions/setup-python@3d1e2d2ca0a067f27da6fec484fce7f5256def85 # v5.6.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python }}
|
python-version: ${{ matrix.python }}
|
||||||
allow-prereleases: true
|
allow-prereleases: true
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
freethreaded: ${{ matrix.freethreaded }}
|
||||||
|
|
||||||
- name: common variables for all runs
|
- name: common variables for all runs
|
||||||
env:
|
env:
|
||||||
JID: ${{ matrix.jid }}
|
JID: ${{ matrix.jid }}
|
||||||
ACTIONS_CACHE: ${{ steps.cache-python-ssl.outputs.cache-hit }}
|
ACTIONS_CACHE: ${{ steps.cache-python-ssl.outputs.cache-hit }}
|
||||||
ACTIONS_GOAL: ${{ matrix.goal }}
|
ACTIONS_GOAL: ${{ matrix.goal }}
|
||||||
|
freethreaded: ${{ matrix.freethreaded }}
|
||||||
run: |
|
run: |
|
||||||
case $RUNNER_ARCH in
|
case $RUNNER_ARCH in
|
||||||
X64)
|
X64)
|
||||||
@@ -169,6 +194,12 @@ jobs:
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
echo "JID=${JID}" >> $GITHUB_ENV
|
echo "JID=${JID}" >> $GITHUB_ENV
|
||||||
|
echo "freethreaded=${freethreaded}" >> $GITHUB_ENV
|
||||||
|
if "$freethreaded"; then
|
||||||
|
# Hush some warnings while we test
|
||||||
|
export PYTHON_GIL=0
|
||||||
|
echo "PYTHON_GIL=${PYTHON_GIL}" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
echo "ACTIONS_CACHE=${ACTIONS_CACHE}" >> $GITHUB_ENV
|
echo "ACTIONS_CACHE=${ACTIONS_CACHE}" >> $GITHUB_ENV
|
||||||
echo "ACTIONS_GOAL=${ACTIONS_GOAL}" >> $GITHUB_ENV
|
echo "ACTIONS_GOAL=${ACTIONS_GOAL}" >> $GITHUB_ENV
|
||||||
curl_version=$(curl --version | head -n 1 | awk '{ print $2 }')
|
curl_version=$(curl --version | head -n 1 | awk '{ print $2 }')
|
||||||
@@ -194,13 +225,9 @@ jobs:
|
|||||||
if: matrix.goal == 'test'
|
if: matrix.goal == 'test'
|
||||||
run: |
|
run: |
|
||||||
export PYTHON=$(which python3)
|
export PYTHON=$(which python3)
|
||||||
export PIP=$(which pip3)
|
|
||||||
export gam="${PYTHON} -m gam"
|
|
||||||
export gampath="$(readlink -e .)/gam"
|
export gampath="$(readlink -e .)/gam"
|
||||||
echo -e "PYTHON: ${PYTHON}\nPIP: ${PIP}\gam: ${gam}\ngampath: ${gampath}"
|
echo -e "PYTHON: ${PYTHON}\ngam: ${gam}\ngampath: ${gampath}"
|
||||||
echo "PYTHON=${PYTHON}" >> $GITHUB_ENV
|
echo "PYTHON=${PYTHON}" >> $GITHUB_ENV
|
||||||
echo "PIP=${PIP}" >> $GITHUB_ENV
|
|
||||||
echo "gam=${gam}" >> $GITHUB_ENV
|
|
||||||
echo "gampath=${gampath}" >> $GITHUB_ENV
|
echo "gampath=${gampath}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Install necessary Github-hosted Linux packages
|
- name: Install necessary Github-hosted Linux packages
|
||||||
@@ -261,14 +288,15 @@ jobs:
|
|||||||
MAKEOPT=""
|
MAKEOPT=""
|
||||||
PERL="c:\strawberry\perl\bin\perl.exe"
|
PERL="c:\strawberry\perl\bin\perl.exe"
|
||||||
if [[ "$RUNNER_ARCH" == "ARM64" ]]; then
|
if [[ "$RUNNER_ARCH" == "ARM64" ]]; then
|
||||||
PYEXTERNALS_PATH="arm64"
|
PYEXTERNALS_ARCH="arm64"
|
||||||
WIX_ARCH="arm64"
|
WIX_ARCH="arm64"
|
||||||
elif [[ "$RUNNER_ARCH" == "X64" ]]; then
|
elif [[ "$RUNNER_ARCH" == "X64" ]]; then
|
||||||
PYEXTERNALS_PATH="amd64"
|
PYEXTERNALS_ARCH="amd64"
|
||||||
WIX_ARCH="x64"
|
WIX_ARCH="x64"
|
||||||
fi
|
fi
|
||||||
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_PATH}"
|
PYEXTERNALS_PATH=$(cygpath -u "${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_ARCH}")
|
||||||
echo "PYTHON=${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_PATH}/python.exe" >> $GITHUB_ENV
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${PYEXTERNALS_PATH}"
|
||||||
|
echo "PYTHON=${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_ARCH}/python.exe" >> $GITHUB_ENV
|
||||||
echo "WIX_ARCH=${WIX_ARCH}" >> $GITHUB_ENV
|
echo "WIX_ARCH=${WIX_ARCH}" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
echo "We'll run make with: ${MAKEOPT}"
|
echo "We'll run make with: ${MAKEOPT}"
|
||||||
@@ -457,15 +485,36 @@ jobs:
|
|||||||
"$PYTHON" get-pip.py
|
"$PYTHON" get-pip.py
|
||||||
"$PYTHON" -m pip install --upgrade pip
|
"$PYTHON" -m pip install --upgrade pip
|
||||||
"$PYTHON" -m pip install --upgrade wheel
|
"$PYTHON" -m pip install --upgrade wheel
|
||||||
"$PYTHON" -m pip install setuptools
|
"$PYTHON" -m pip install --upgrade setuptools
|
||||||
"$PYTHON" -m pip install --upgrade importlib-metadata
|
"$PYTHON" -m pip install --upgrade importlib-metadata
|
||||||
"$PYTHON" -m pip install --upgrade setuptools-scm
|
"$PYTHON" -m pip install --upgrade setuptools-scm
|
||||||
"$PYTHON" -m pip list
|
"$PYTHON" -m pip list
|
||||||
|
|
||||||
|
- name: Create and use Python venv
|
||||||
|
run: |
|
||||||
|
cd "$GITHUB_WORKSPACE"
|
||||||
|
"$PYTHON" -m venv venv
|
||||||
|
if [[ "$RUNNER_OS" == "Windows" ]]; then
|
||||||
|
# hack till pyscard has a wheel for win arm64
|
||||||
|
"$PYTHON" -m pip install --upgrade --force-reinstall pyscard
|
||||||
|
export PYTHON="${GITHUB_WORKSPACE}/venv/scripts/python.exe"
|
||||||
|
else
|
||||||
|
export PYTHON="${GITHUB_WORKSPACE}/venv/bin/python3"
|
||||||
|
fi
|
||||||
|
echo "PYTHON=${PYTHON}" >> $GITHUB_ENV
|
||||||
|
if [[ "$ACTIONS_GOAL" == "test" ]]; then
|
||||||
|
export gam="${PYTHON} gam.py"
|
||||||
|
echo "gam=${gam}" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Install pip requirements
|
- name: Install pip requirements
|
||||||
run: |
|
run: |
|
||||||
echo "before anything..."
|
echo "before anything..."
|
||||||
"$PYTHON" -m pip list
|
"$PYTHON" -m pip list
|
||||||
|
echo "--info--"
|
||||||
|
"$PYTHON" -m pip cache info
|
||||||
|
echo "--list--"
|
||||||
|
"$PYTHON" -m pip cache list
|
||||||
"$PYTHON" -m pip install --upgrade ..[yubikey]
|
"$PYTHON" -m pip install --upgrade ..[yubikey]
|
||||||
echo "after everything..."
|
echo "after everything..."
|
||||||
"$PYTHON" -m pip list
|
"$PYTHON" -m pip list
|
||||||
@@ -894,11 +943,11 @@ jobs:
|
|||||||
$gam calendar $gam_user printevents after -0d
|
$gam calendar $gam_user printevents after -0d
|
||||||
$gam config enable_dasa false save
|
$gam config enable_dasa false save
|
||||||
matterid=uid:$($gam create vaultmatter name "GHA matter $newbase" description "test matter" 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 create vaulthold matter $matterid name "GHA hold ${newbase}" corpus mail ou "$newou"
|
||||||
$gam print vaultmatters matterstate open
|
$gam print vaultmatters matterstate open
|
||||||
$gam print vaultholds matter $matterid
|
$gam print vaultholds matter $matterid
|
||||||
$gam print vaultcount matter $matterid corpus mail everyone todrive tdnobrowser
|
$gam print vaultcount matter $matterid corpus mail everyone todrive tdnobrowser
|
||||||
$gam create vaultexport matter $matterid name "GHA export $newbase" corpus mail accounts $newuser
|
$gam create vaultexport matter $matterid name "GHA export $newbase" corpus mail ou "$newou"
|
||||||
$gam print exports matter $matterid | $gam csv - gam info export $matterid id:~~id~~
|
$gam print exports matter $matterid | $gam csv - gam info export $matterid id:~~id~~
|
||||||
$gam config enable_dasa true save
|
$gam config enable_dasa true save
|
||||||
$gam csv sample.csv gam user ~email add calendar id:$newresource
|
$gam csv sample.csv gam user ~email add calendar id:$newresource
|
||||||
@@ -978,7 +1027,8 @@ jobs:
|
|||||||
else
|
else
|
||||||
tar_folders="bin/"
|
tar_folders="bin/"
|
||||||
fi
|
fi
|
||||||
tar cJvvf cache.tar.xz $tar_folders
|
echo '.git*' > ./excludes.txt
|
||||||
|
tar cJvvf cache.tar.xz --exclude-from=excludes.txt $tar_folders
|
||||||
|
|
||||||
merge:
|
merge:
|
||||||
if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
|
if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
|
||||||
@@ -1028,7 +1078,7 @@ jobs:
|
|||||||
echo "dateversion=${dateversion}" >> $GITHUB_OUTPUT
|
echo "dateversion=${dateversion}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Publish draft release
|
- name: Publish draft release
|
||||||
uses: softprops/action-gh-release@fbadcc90e88ecface60a0a0d123795b784ceb239 # v2.3.2
|
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
prerelease: false
|
prerelease: false
|
||||||
|
|||||||
2
.github/workflows/pypi.yml
vendored
2
.github/workflows/pypi.yml
vendored
@@ -30,6 +30,6 @@ jobs:
|
|||||||
python -m build
|
python -m build
|
||||||
|
|
||||||
- name: Publish package distributions to PyPI
|
- name: Publish package distributions to PyPI
|
||||||
uses: pypa/gh-action-pypi-publish@release/v1
|
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
|
||||||
with:
|
with:
|
||||||
attestation: true
|
attestation: true
|
||||||
|
|||||||
@@ -368,6 +368,7 @@ If an item contains spaces, it should be surrounded by ".
|
|||||||
## Named items
|
## Named items
|
||||||
|
|
||||||
<AccessToken> ::= <String>
|
<AccessToken> ::= <String>
|
||||||
|
<AdminAssigneeType> ::= group|user|serviceaccount|unknown
|
||||||
<AlertID> ::= <String>
|
<AlertID> ::= <String>
|
||||||
<APIScopeURL> ::= <String>
|
<APIScopeURL> ::= <String>
|
||||||
<APPID> ::= <String>
|
<APPID> ::= <String>
|
||||||
@@ -691,6 +692,7 @@ If an item contains spaces, it should be surrounded by ".
|
|||||||
|
|
||||||
## Lists of basic items
|
## Lists of basic items
|
||||||
|
|
||||||
|
<AdminAssigneeTypeList> ::= "<AdminAssigneeType>(,<AdminAssigneeType>)*"
|
||||||
<APIScopeURLList> ::= "<APIScopeURL>(,<APIScopeURL>)*"
|
<APIScopeURLList> ::= "<APIScopeURL>(,<APIScopeURL>)*"
|
||||||
<ASPIDList> ::= "<ASPID>(,<ASPID>)*"
|
<ASPIDList> ::= "<ASPID>(,<ASPID>)*"
|
||||||
<AssetTagList> ::= "<AssetTag>(,<AssetTag>)*"
|
<AssetTagList> ::= "<AssetTag>(,<AssetTag>)*"
|
||||||
@@ -1552,10 +1554,13 @@ gam create|add admin <EmailAddress>|<UniqueID> <RoleItem> customer|(org_unit <Or
|
|||||||
gam delete admin <RoleAssignmentId>
|
gam delete admin <RoleAssignmentId>
|
||||||
|
|
||||||
gam print admins [todrive <ToDriveAttribute>*]
|
gam print admins [todrive <ToDriveAttribute>*]
|
||||||
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition]
|
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
|
||||||
[privileges] [oneitemperrow]
|
[types <AdminAssigneeTypeList>]
|
||||||
|
[recursive] [condition] [privileges] [oneitemperrow]
|
||||||
gam show admins
|
gam show admins
|
||||||
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [privileges]
|
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
|
||||||
|
[types <AdminAssigneeTypeList>]
|
||||||
|
[recursive] [condition] [privileges]
|
||||||
|
|
||||||
# Alert Center
|
# Alert Center
|
||||||
|
|
||||||
@@ -1932,12 +1937,12 @@ gam calendar|calendars <CalendarEntity> info events [<EventEntity>] [maxinstance
|
|||||||
[formatjson]
|
[formatjson]
|
||||||
gam calendar|calendars <CalendarEntity> show events [<EventEntity>] <EventDisplayProperty>*
|
gam calendar|calendars <CalendarEntity> show events [<EventEntity>] <EventDisplayProperty>*
|
||||||
[fields <EventFieldNameList>] [showdayofweek]
|
[fields <EventFieldNameList>] [showdayofweek]
|
||||||
[countsonly]
|
[countsonly|formatjson]
|
||||||
[formatjson]
|
|
||||||
gam calendar|calendars <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>*
|
gam calendar|calendars <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>*
|
||||||
[fields <EventFieldNameList>] [showdayofweek]
|
[fields <EventFieldNameList>] [showdayofweek]
|
||||||
[countsonly [eventrowfilter]]
|
(addcsvdata <FieldName> <String>)*
|
||||||
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
|
[eventrowfilter]
|
||||||
|
[countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
|
||||||
|
|
||||||
gam calendar <CalendarEntity> addevent <EventAttribute>+ [<EventNotificationAttribute>]
|
gam calendar <CalendarEntity> addevent <EventAttribute>+ [<EventNotificationAttribute>]
|
||||||
[showdayofweek]
|
[showdayofweek]
|
||||||
@@ -3383,6 +3388,7 @@ gam print course-materials [todrive <ToDriveAttribute>*]
|
|||||||
(orderby <CourseMaterialOrderByFieldName> [ascending|descending])*)
|
(orderby <CourseMaterialOrderByFieldName> [ascending|descending])*)
|
||||||
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
|
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
|
||||||
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||||
|
[oneitemperrow]
|
||||||
[countsonly] [formatjson [quotechar <Character>]]
|
[countsonly] [formatjson [quotechar <Character>]]
|
||||||
gam print course-submissions [todrive <ToDriveAttribute>*]
|
gam print course-submissions [todrive <ToDriveAttribute>*]
|
||||||
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
|
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
|
||||||
@@ -3404,6 +3410,7 @@ gam print course-works [todrive <ToDriveAttribute>*]
|
|||||||
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseWorkFieldNameList>]
|
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseWorkFieldNameList>]
|
||||||
[showstudentsaslist [<Boolean>]] [delimiter <Character>]
|
[showstudentsaslist [<Boolean>]] [delimiter <Character>]
|
||||||
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||||
|
[oneitemperrow]
|
||||||
[countsonly] [formatjson [quotechar <Character>]]
|
[countsonly] [formatjson [quotechar <Character>]]
|
||||||
|
|
||||||
# Classroom - Student Groups
|
# Classroom - Student Groups
|
||||||
@@ -3743,16 +3750,14 @@ gam print domaincontacts|peoplecontacts [todrive <ToDriveAttribute>*]
|
|||||||
[sources <PeopleSourceName>]
|
[sources <PeopleSourceName>]
|
||||||
[query <String>]
|
[query <String>]
|
||||||
[mergesources <PeopleMergeSourceName>]
|
[mergesources <PeopleMergeSourceName>]
|
||||||
[coountsonly]
|
|
||||||
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
||||||
[formatjson [quotechar <Character>]]
|
[coountsonly|(formatjson [quotechar <Character>])]
|
||||||
gam show domaincontacts|peoplecontacts
|
gam show domaincontacts|peoplecontacts
|
||||||
[sources <PeopleSourceName>]
|
[sources <PeopleSourceName>]
|
||||||
[query <String>]
|
[query <String>]
|
||||||
[mergesources <PeopleMergeSourceName>]
|
[mergesources <PeopleMergeSourceName>]
|
||||||
[coountsonly]
|
|
||||||
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
||||||
[formatjson]
|
[coountsonly|formatjson]
|
||||||
|
|
||||||
gam info people|peopleprofile <PeopleResourceNameEntity>
|
gam info people|peopleprofile <PeopleResourceNameEntity>
|
||||||
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
||||||
@@ -3760,15 +3765,13 @@ gam info people|peopleprofile <PeopleResourceNameEntity>
|
|||||||
gam print people|peopleprofile [todrive <ToDriveAttribute>*]
|
gam print people|peopleprofile [todrive <ToDriveAttribute>*]
|
||||||
[query <String>]
|
[query <String>]
|
||||||
[mergesources <PeopleMergeSourceName>]
|
[mergesources <PeopleMergeSourceName>]
|
||||||
[coountsonly]
|
|
||||||
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
||||||
[formatjson [quotechar <Character>]]
|
[coountsonly|(formatjson [quotechar <Character>])]
|
||||||
gam show people|peopleprofile
|
gam show people|peopleprofile
|
||||||
[query <String>]
|
[query <String>]
|
||||||
[mergesources <PeopleMergeSourceName>]
|
[mergesources <PeopleMergeSourceName>]
|
||||||
[coountsonly]
|
|
||||||
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
||||||
[formatjson]
|
[coountsonly|formatjson]
|
||||||
|
|
||||||
# Email Audit Monitor
|
# Email Audit Monitor
|
||||||
|
|
||||||
@@ -6313,12 +6316,11 @@ gam <UserTypeEntity> info events <UserCalendarEntity> [<EventEntity>] [maxinstan
|
|||||||
[formatjson]
|
[formatjson]
|
||||||
gam <UserTypeEntity> show events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
|
gam <UserTypeEntity> show events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
|
||||||
[fields <EventFieldNameList>] [showdayofweek]
|
[fields <EventFieldNameList>] [showdayofweek]
|
||||||
[countsonly]
|
[countsonly|formatjson]
|
||||||
[formatjson]
|
|
||||||
gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
|
gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
|
||||||
[fields <EventFieldNameList>] [showdayofweek]
|
[fields <EventFieldNameList>] [showdayofweek]
|
||||||
[countsonly [eventrowfilter]]
|
[eventrowfilter]]
|
||||||
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
|
[countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
|
||||||
|
|
||||||
gam <UserTypeEntity> update calattendees <UserCalendarEntity> <EventEntity> [anyorganizer]
|
gam <UserTypeEntity> update calattendees <UserCalendarEntity> <EventEntity> [anyorganizer]
|
||||||
[<EventNotificationAttribute>] [splitupdate] [dryrun|doit]
|
[<EventNotificationAttribute>] [splitupdate] [dryrun|doit]
|
||||||
@@ -8342,13 +8344,13 @@ gam <UserTypeEntity> info contacts
|
|||||||
gam <UserTypeEntity> show contacts
|
gam <UserTypeEntity> show contacts
|
||||||
<PeoplePrintShowUserContactSelection>
|
<PeoplePrintShowUserContactSelection>
|
||||||
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
||||||
[countsonly|allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
|
[allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
|
||||||
[formatjson]
|
[countsonly|formatjson]
|
||||||
gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*]
|
||||||
<PeoplePrintShowUserContactSelection>
|
<PeoplePrintShowUserContactSelection>
|
||||||
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
||||||
[countsonly|allfields|(fields <PeopleFieldNameList>)] [[showgroups|showgroupnameslist] showmetadata]
|
[allfields|(fields <PeopleFieldNameList>)] [[showgroups|showgroupnameslist] showmetadata]
|
||||||
[formatjson [quotechar <Character>]]
|
[countsonly|(formatjson [quotechar <Character>])]
|
||||||
|
|
||||||
<OtherContactsFieldName> ::=
|
<OtherContactsFieldName> ::=
|
||||||
emailaddresses|
|
emailaddresses|
|
||||||
@@ -8582,7 +8584,7 @@ gam <UserTypeEntity> info tasklist <TasklistEntity>
|
|||||||
gam <UserTypeEntity> show tasklists
|
gam <UserTypeEntity> show tasklists
|
||||||
[countsonly|formatjson]
|
[countsonly|formatjson]
|
||||||
gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
|
||||||
[countsonly | (formatjson [quotechar <Character>])]
|
[countsonly|(formatjson [quotechar <Character>])]
|
||||||
|
|
||||||
# Users - Shared Drives
|
# Users - Shared Drives
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,51 @@
|
|||||||
|
7.23.06
|
||||||
|
|
||||||
|
Added option `types <AdminAssigneeTypeList>` to `gam print|show admins` that allows filtering
|
||||||
|
of admin assignments by the type of the assignee; by default, all assignee types are displayed.
|
||||||
|
```
|
||||||
|
<AdminAssigneeType> ::= group|user|serviceaccount|unknown
|
||||||
|
<AdminAssigneeTypeList> ::= "<AdminAssigneeType>(,<AdminAssigneeType>)*"
|
||||||
|
```
|
||||||
|
|
||||||
|
7.23.05
|
||||||
|
|
||||||
|
Added option `recursive` that will display assignments to the members
|
||||||
|
of security groups assigned to roles; the security group membership is recursively expanded.
|
||||||
|
|
||||||
|
7.23.04
|
||||||
|
|
||||||
|
Added option `addcsvdata <FieldName> <String>` to `gam <UserTypeEntity> print events`
|
||||||
|
and `gam calendars <CalendarEntity> print events` that adds additional columns of data to the CSV file output.
|
||||||
|
An example would be to get the calendar name in addition to the calendar ID when printing events.
|
||||||
|
```
|
||||||
|
gam redirect csv ./Resources.csv print resources fields email,name
|
||||||
|
gam redirect csv ./ResourceEventCounts.csv multiprocess redirect stderr - multiprocess csv Resources.csv gam calendar "~resourceEmail" print events starttime -1y countsonly addcsvdata calendarName "~resourceName"
|
||||||
|
```
|
||||||
|
|
||||||
|
Upgraded to OpenSSL 3.6.0.
|
||||||
|
|
||||||
|
7.23.03
|
||||||
|
|
||||||
|
Upgraded to OpenSSL 3.5.4.
|
||||||
|
|
||||||
|
7.23.02
|
||||||
|
|
||||||
|
Added option `oneitemperrow` to 'gam print course-materials|course-work` to have each of a
|
||||||
|
course's materials displayed on a separate row with all of the other course fields.
|
||||||
|
This produces a CSV file that can be used in subsequent commands to process the materials without further script processing.
|
||||||
|
|
||||||
|
7.23.00
|
||||||
|
|
||||||
|
Added `chat_max_results` variable to `gam.cfg`.
|
||||||
|
```
|
||||||
|
chat_max_results
|
||||||
|
When retrieving lists of Chat items from API,
|
||||||
|
how many should be retrieved in each API call
|
||||||
|
Default: 100
|
||||||
|
Range: 1 - 1000
|
||||||
|
```
|
||||||
|
Previously, this vaule was always set to 1000 which could cause errors.
|
||||||
|
|
||||||
7.22.07
|
7.22.07
|
||||||
|
|
||||||
Added options `showdetails` and `returnidonly` to `gam create|copy vaultquery`.
|
Added options `showdetails` and `returnidonly` to `gam create|copy vaultquery`.
|
||||||
@@ -101,7 +149,7 @@ GAM now builds on macOS 26 Tahoe and properly identifies the OS.
|
|||||||
|
|
||||||
A custom build of the cryptography library is no longer needed for Windows arm64 builds as the project now releases their own build for the OS.
|
A custom build of the cryptography library is no longer needed for Windows arm64 builds as the project now releases their own build for the OS.
|
||||||
|
|
||||||
Upgrade to OpenSSL 3.5.3 latest
|
Upgraded to OpenSSL 3.5.3.
|
||||||
|
|
||||||
7.21.01
|
7.21.01
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
|
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
|
||||||
__version__ = '7.22.07'
|
__version__ = '7.23.06'
|
||||||
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||||
|
|
||||||
#pylint: disable=wrong-import-position
|
#pylint: disable=wrong-import-position
|
||||||
@@ -7868,6 +7868,13 @@ class CSVPrintFile():
|
|||||||
if title not in self.titlesSet:
|
if title not in self.titlesSet:
|
||||||
self.AddTitle(title)
|
self.AddTitle(title)
|
||||||
|
|
||||||
|
def InsertTitles(self, position, titles):
|
||||||
|
for title in titles if isinstance(titles, list) else [titles]:
|
||||||
|
if title not in self.titlesSet:
|
||||||
|
self.titlesSet.add(title)
|
||||||
|
self.titlesList.insert(position, title)
|
||||||
|
position += 1
|
||||||
|
|
||||||
def SetTitles(self, titles):
|
def SetTitles(self, titles):
|
||||||
self.titlesSet = set()
|
self.titlesSet = set()
|
||||||
self.titlesList = []
|
self.titlesList = []
|
||||||
@@ -16983,21 +16990,38 @@ def doDeleteAdmin():
|
|||||||
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
||||||
ClientAPIAccessDeniedExit(str(e))
|
ClientAPIAccessDeniedExit(str(e))
|
||||||
|
|
||||||
ASSIGNEE_EMAILTYPE_TOFIELD_MAP = {
|
ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP = {
|
||||||
'user': 'assignedToUser',
|
'user': 'assignedToUser',
|
||||||
'group': 'assignedToGroup',
|
'group': 'assignedToGroup',
|
||||||
'serviceaccount': 'assignedToServiceAccount',
|
'serviceaccount': 'assignedToServiceAccount',
|
||||||
|
'unknown': 'assignedToUnknown',
|
||||||
}
|
}
|
||||||
PRINT_ADMIN_FIELDS = ['roleAssignmentId', 'roleId', 'assignedTo', 'scopeType', 'orgUnitId']
|
ALL_ASSIGNEE_TYPES = ['user', 'group', 'serviceaccount']
|
||||||
|
|
||||||
|
PRINT_ADMIN_FIELDS = ['roleAssignmentId', 'roleId', 'assignedTo', 'scopeType', 'orgUnitId', 'assigneeType']
|
||||||
PRINT_ADMIN_TITLES = ['roleAssignmentId', 'roleId', 'role',
|
PRINT_ADMIN_TITLES = ['roleAssignmentId', 'roleId', 'role',
|
||||||
'assignedTo', 'assignedToUser', 'assignedToGroup', 'assignedToServiceAccount', 'assignedToUnknown',
|
'assignedTo', 'assignedToUser', 'assignedToGroup', 'assignedToServiceAccount', 'assignedToUnknown',
|
||||||
'scopeType', 'orgUnitId', 'orgUnit']
|
'scopeType', 'orgUnitId', 'orgUnit']
|
||||||
|
|
||||||
|
def getAssigneeTypes(myarg, typesSet):
|
||||||
|
if myarg in {'type', 'types'}:
|
||||||
|
for gtype in getString(Cmd.OB_ADMIN_ASSIGNEE_TYPE_LIST).lower().replace(',', ' ').split():
|
||||||
|
if gtype in ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP:
|
||||||
|
typesSet.add(ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP[gtype])
|
||||||
|
else:
|
||||||
|
invalidChoiceExit(gtype, ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP, True)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
# gam print admins [todrive <ToDriveAttribute>*]
|
# gam print admins [todrive <ToDriveAttribute>*]
|
||||||
# [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition]
|
# [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
|
||||||
# [privileges] [oneitemperrow]
|
# [types <AdminAssigneeTypeList>]
|
||||||
|
# [recursive] [condition] [privileges] [oneitemperrow]
|
||||||
# gam show admins
|
# gam show admins
|
||||||
# [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [privileges]
|
# [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
|
||||||
|
# [types <AdminAssigneeTypeList>]
|
||||||
|
# [recursive] [condition] [privileges]
|
||||||
def doPrintShowAdmins():
|
def doPrintShowAdmins():
|
||||||
def _getPrivileges(admin):
|
def _getPrivileges(admin):
|
||||||
if showPrivileges:
|
if showPrivileges:
|
||||||
@@ -17024,19 +17048,18 @@ def doPrintShowAdmins():
|
|||||||
def _setNamesFromIds(admin, privileges):
|
def _setNamesFromIds(admin, privileges):
|
||||||
admin['role'] = role_from_roleid(admin['roleId'])
|
admin['role'] = role_from_roleid(admin['roleId'])
|
||||||
assignedTo = admin['assignedTo']
|
assignedTo = admin['assignedTo']
|
||||||
admin['assignedToUnknown'] = False
|
|
||||||
if assignedTo not in assignedToIdEmailMap:
|
if assignedTo not in assignedToIdEmailMap:
|
||||||
assigneeType = admin.get('assigneeType')
|
|
||||||
assignedToField = ASSIGNEE_EMAILTYPE_TOFIELD_MAP.get(assigneeType, None)
|
|
||||||
assigneeEmail, assigneeType = convertUIDtoEmailAddressWithType(f'uid:{assignedTo}', cd, sal,
|
assigneeEmail, assigneeType = convertUIDtoEmailAddressWithType(f'uid:{assignedTo}', cd, sal,
|
||||||
emailTypes=list(ASSIGNEE_EMAILTYPE_TOFIELD_MAP.keys()))
|
emailTypes=ALL_ASSIGNEE_TYPES if admin.get('assigneeType') != 'group' else ['group'])
|
||||||
if not assignedToField and assigneeType in ASSIGNEE_EMAILTYPE_TOFIELD_MAP:
|
if assigneeType in ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP:
|
||||||
assignedToField = ASSIGNEE_EMAILTYPE_TOFIELD_MAP[assigneeType]
|
assignedToField = ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP[assigneeType]
|
||||||
if assigneeType == 'unknown':
|
else:
|
||||||
assignedToField = 'assignedToUnknown'
|
assignedToField = 'assignedToUnknown'
|
||||||
|
if assignedToField == 'assignedToUnknown':
|
||||||
assigneeEmail = True
|
assigneeEmail = True
|
||||||
assignedToIdEmailMap[assignedTo] = {'assignedToField': assignedToField, 'assigneeEmail': assigneeEmail}
|
assignedToIdEmailMap[assignedTo] = {'assignedToField': assignedToField, 'assigneeEmail': assigneeEmail}
|
||||||
admin[assignedToIdEmailMap[assignedTo]['assignedToField']] = assignedToIdEmailMap[assignedTo]['assigneeEmail']
|
admin[assignedToIdEmailMap[assignedTo]['assignedToField']] = assignedToIdEmailMap[assignedTo]['assigneeEmail']
|
||||||
|
admin['assignedToField'] = assignedToIdEmailMap[assignedTo]['assignedToField']
|
||||||
if privileges is not None:
|
if privileges is not None:
|
||||||
admin.update(privileges)
|
admin.update(privileges)
|
||||||
if 'orgUnitId' in admin:
|
if 'orgUnitId' in admin:
|
||||||
@@ -17052,7 +17075,8 @@ def doPrintShowAdmins():
|
|||||||
csvPF = CSVPrintFile(PRINT_ADMIN_TITLES) if Act.csvFormat() else None
|
csvPF = CSVPrintFile(PRINT_ADMIN_TITLES) if Act.csvFormat() else None
|
||||||
roleId = None
|
roleId = None
|
||||||
userKey = None
|
userKey = None
|
||||||
oneItemPerRow = showPrivileges = False
|
oneItemPerRow = recursive = showPrivileges = False
|
||||||
|
typesSet = set()
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
rolePrivileges = {}
|
rolePrivileges = {}
|
||||||
fieldsList = PRINT_ADMIN_FIELDS
|
fieldsList = PRINT_ADMIN_FIELDS
|
||||||
@@ -17065,6 +17089,17 @@ def doPrintShowAdmins():
|
|||||||
userKey = kwargs['userKey'] = getEmailAddress()
|
userKey = kwargs['userKey'] = getEmailAddress()
|
||||||
elif myarg == 'role':
|
elif myarg == 'role':
|
||||||
_, roleId = getRoleId()
|
_, roleId = getRoleId()
|
||||||
|
elif getAssigneeTypes(myarg, typesSet):
|
||||||
|
pass
|
||||||
|
elif myarg == 'recursive':
|
||||||
|
recursive = True
|
||||||
|
allGroupRoles = ','.join(sorted(ALL_GROUP_ROLES))
|
||||||
|
memberOptions = initMemberOptions()
|
||||||
|
memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP] = True
|
||||||
|
memberOptions[MEMBEROPTION_DISPLAYMATCH] = False
|
||||||
|
memberDisplayOptions = initIPSGMGroupMemberDisplayOptions()
|
||||||
|
for role in [Ent.ROLE_MEMBER, Ent.ROLE_MANAGER, Ent.ROLE_OWNER]:
|
||||||
|
memberDisplayOptions[role]['show'] = True
|
||||||
elif myarg == 'condition':
|
elif myarg == 'condition':
|
||||||
fieldsList.append('condition')
|
fieldsList.append('condition')
|
||||||
if csvPF:
|
if csvPF:
|
||||||
@@ -17078,13 +17113,15 @@ def doPrintShowAdmins():
|
|||||||
if roleId and not kwargs:
|
if roleId and not kwargs:
|
||||||
kwargs['roleId'] = roleId
|
kwargs['roleId'] = roleId
|
||||||
roleId = None
|
roleId = None
|
||||||
|
if not typesSet:
|
||||||
|
typesSet = set(ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP.values())
|
||||||
fields = getItemFieldsFromFieldsList('items', fieldsList)
|
fields = getItemFieldsFromFieldsList('items', fieldsList)
|
||||||
printGettingAllAccountEntities(Ent.ADMIN_ROLE_ASSIGNMENT)
|
printGettingAllAccountEntities(Ent.ADMIN_ROLE_ASSIGNMENT)
|
||||||
try:
|
try:
|
||||||
admins = callGAPIpages(cd.roleAssignments(), 'list', 'items',
|
admins = callGAPIpages(cd.roleAssignments(), 'list', 'items',
|
||||||
pageMessage=getPageMessage(),
|
pageMessage=getPageMessage(),
|
||||||
throwReasons=[GAPI.INVALID, GAPI.USER_NOT_FOUND,
|
throwReasons=[GAPI.INVALID, GAPI.USER_NOT_FOUND,
|
||||||
GAPI.FORBIDDEN, GAPI.SERVICE_NOT_AVAILABLE,
|
GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.SERVICE_NOT_AVAILABLE,
|
||||||
GAPI.BAD_REQUEST, GAPI.CUSTOMER_NOT_FOUND,
|
GAPI.BAD_REQUEST, GAPI.CUSTOMER_NOT_FOUND,
|
||||||
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
@@ -17092,39 +17129,77 @@ def doPrintShowAdmins():
|
|||||||
except (GAPI.invalid, GAPI.userNotFound):
|
except (GAPI.invalid, GAPI.userNotFound):
|
||||||
entityUnknownWarning(Ent.ADMINISTRATOR, userKey)
|
entityUnknownWarning(Ent.ADMINISTRATOR, userKey)
|
||||||
return
|
return
|
||||||
except (GAPI.serviceNotAvailable) as e:
|
except GAPI.notFound as e:
|
||||||
entityActionFailedExit([Ent.ADMINISTRATOR, userKey, Ent.ADMIN_ROLE, roleId], str(e))
|
entityActionFailedExit([Ent.ADMIN_ROLE, kwargs['roleId']], str(e))
|
||||||
|
except (GAPI.forbidden, GAPI.serviceNotAvailable) as e:
|
||||||
|
entityActionFailedExit([Ent.ADMINISTRATOR, userKey], str(e))
|
||||||
except (GAPI.badRequest, GAPI.customerNotFound):
|
except (GAPI.badRequest, GAPI.customerNotFound):
|
||||||
accessErrorExit(cd)
|
accessErrorExit(cd)
|
||||||
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
||||||
ClientAPIAccessDeniedExit(str(e))
|
ClientAPIAccessDeniedExit(str(e))
|
||||||
|
count = len(admins)
|
||||||
|
groupMembers = {}
|
||||||
|
expandedAdmins = []
|
||||||
|
i = 0
|
||||||
|
for admin in admins:
|
||||||
|
i += 1
|
||||||
|
if roleId and roleId != admin['roleId']:
|
||||||
|
continue
|
||||||
|
assignedTo = admin['assignedTo']
|
||||||
|
if admin['assigneeType'] != 'group' or not recursive:
|
||||||
|
_setNamesFromIds(admin, _getPrivileges(admin))
|
||||||
|
if admin['assignedToField'] in typesSet:
|
||||||
|
expandedAdmins.append(admin)
|
||||||
|
continue
|
||||||
|
if assignedTo not in groupMembers:
|
||||||
|
membersList = []
|
||||||
|
membersSet = set()
|
||||||
|
level = 0
|
||||||
|
getGroupMembers(cd, assignedTo, allGroupRoles, membersList, membersSet, i, count,
|
||||||
|
memberOptions, memberDisplayOptions, level, {Ent.TYPE_USER})
|
||||||
|
groupMembers[assignedTo] = membersList[:]
|
||||||
|
_setNamesFromIds(admin, _getPrivileges(admin))
|
||||||
|
if admin[assignedToIdEmailMap[assignedTo]['assignedToField']] not in typesSet:
|
||||||
|
continue
|
||||||
|
expandedAdmins.append(admin)
|
||||||
|
if not groupMembers[assignedTo]:
|
||||||
|
expandedAdmins.append(admin)
|
||||||
|
continue
|
||||||
|
admin['assigneeType'] = 'user'
|
||||||
|
admin['assignedToGroup'] = assignedToIdEmailMap[assignedTo]['assigneeEmail']
|
||||||
|
for member in groupMembers[assignedTo]:
|
||||||
|
userAdmin = admin.copy()
|
||||||
|
userAdmin['assignedTo'] = member['id']
|
||||||
|
_setNamesFromIds(userAdmin, _getPrivileges(admin))
|
||||||
|
expandedAdmins.append(userAdmin)
|
||||||
|
admins = expandedAdmins
|
||||||
|
count = len(expandedAdmins)
|
||||||
if not csvPF:
|
if not csvPF:
|
||||||
count = len(admins)
|
|
||||||
performActionNumItems(count, Ent.ADMIN_ROLE_ASSIGNMENT)
|
performActionNumItems(count, Ent.ADMIN_ROLE_ASSIGNMENT)
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
i = 0
|
i = 0
|
||||||
for admin in admins:
|
for admin in expandedAdmins:
|
||||||
i += 1
|
i += 1
|
||||||
if roleId and roleId != admin['roleId']:
|
|
||||||
continue
|
|
||||||
_setNamesFromIds(admin, _getPrivileges(admin))
|
|
||||||
printEntity([Ent.ADMIN_ROLE_ASSIGNMENT, admin['roleAssignmentId']], i, count)
|
printEntity([Ent.ADMIN_ROLE_ASSIGNMENT, admin['roleAssignmentId']], i, count)
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
for field in PRINT_ADMIN_TITLES:
|
for field in PRINT_ADMIN_TITLES:
|
||||||
if field in admin:
|
if field in admin:
|
||||||
if field == 'roleAssignmentId':
|
if field == 'roleAssignmentId':
|
||||||
continue
|
continue
|
||||||
if field != 'rolePrivileges':
|
printKeyValueList([field, admin[field]])
|
||||||
printKeyValueList([field, admin[field]])
|
if showPrivileges:
|
||||||
else:
|
rolePrivileges = admin.get('rolePrivileges', [])
|
||||||
showJSON(None, admin[field])
|
jcount = len(rolePrivileges)
|
||||||
|
if jcount > 0:
|
||||||
|
printKeyValueList(['rolePrivileges', jcount])
|
||||||
|
Ind.Increment()
|
||||||
|
showJSON(None, rolePrivileges)
|
||||||
|
Ind.Decrement()
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
else:
|
else:
|
||||||
for admin in admins:
|
for admin in expandedAdmins:
|
||||||
if roleId and roleId != admin['roleId']:
|
admin.pop('assignedToField')
|
||||||
continue
|
|
||||||
_setNamesFromIds(admin, _getPrivileges(admin))
|
|
||||||
if not oneItemPerRow or 'rolePrivileges' not in admin:
|
if not oneItemPerRow or 'rolePrivileges' not in admin:
|
||||||
csvPF.WriteRowTitles(flattenJSON(admin))
|
csvPF.WriteRowTitles(flattenJSON(admin))
|
||||||
else:
|
else:
|
||||||
@@ -22429,12 +22504,12 @@ def infoUserPeopleContacts(users):
|
|||||||
|
|
||||||
# gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*] <PeoplePrintShowUserContactSelection>
|
# gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*] <PeoplePrintShowUserContactSelection>
|
||||||
# [showgroups|showgroupnameslist] [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
# [showgroups|showgroupnameslist] [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
||||||
# [countsonly|allfields|fields <PeopleFieldNameList>] [showmetadata]
|
# [allfields|fields <PeopleFieldNameList>] [showmetadata]
|
||||||
# [formatjson [quotechar <Character>]]
|
# [countsonly|(formatjson [quotechar <Character>])]
|
||||||
# gam <UserTypeEntity> show contacts <PeoplePrintShowUserContactSelection>
|
# gam <UserTypeEntity> show contacts <PeoplePrintShowUserContactSelection>
|
||||||
# [showgroups] [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
# [showgroups] [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
||||||
# [countsonly|allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
||||||
# [formatjson]
|
# [countsonly|formatjson]
|
||||||
def printShowUserPeopleContacts(users):
|
def printShowUserPeopleContacts(users):
|
||||||
entityType = Ent.USER
|
entityType = Ent.USER
|
||||||
entityTypeName = Ent.Singular(entityType)
|
entityTypeName = Ent.Singular(entityType)
|
||||||
@@ -22473,6 +22548,8 @@ def printShowUserPeopleContacts(users):
|
|||||||
else:
|
else:
|
||||||
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
||||||
if countsOnly:
|
if countsOnly:
|
||||||
|
if csvPF:
|
||||||
|
csvPF.SetFormatJSON(False)
|
||||||
fieldsList = ['emailAddresses']
|
fieldsList = ['emailAddresses']
|
||||||
if contactQuery['mainContacts']:
|
if contactQuery['mainContacts']:
|
||||||
fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
|
fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
|
||||||
@@ -22710,11 +22787,11 @@ def processUserPeopleOtherContacts(users):
|
|||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
|
|
||||||
# gam <UserTypeEntity> print othercontacts [todrive <ToDriveAttribute>*] <OtherContactSelection>
|
# gam <UserTypeEntity> print othercontacts [todrive <ToDriveAttribute>*] <OtherContactSelection>
|
||||||
# [countsonly|allfields|(fields <OtherContactFieldNameList>)] [showmetadata]
|
# [allfields|(fields <OtherContactFieldNameList>)] [showmetadata]
|
||||||
# [formatjson [quotechar <Character>]]
|
# [countsonly|(formatjson [quotechar <Character>])]
|
||||||
# gam <UserTypeEntity> show othercontacts <OtherContactSelection>
|
# gam <UserTypeEntity> show othercontacts <OtherContactSelection>
|
||||||
# [countsonly|allfields|(fields <OtherContactFieldNameList>)] [showmetadata]
|
# [allfields|(fields <OtherContactFieldNameList>)] [showmetadata]
|
||||||
# [formatjson]
|
# [countsonly|formatjson]
|
||||||
def printShowUserPeopleOtherContacts(users):
|
def printShowUserPeopleOtherContacts(users):
|
||||||
entityType = Ent.USER
|
entityType = Ent.USER
|
||||||
entityTypeName = Ent.Singular(entityType)
|
entityTypeName = Ent.Singular(entityType)
|
||||||
@@ -22744,6 +22821,8 @@ def printShowUserPeopleOtherContacts(users):
|
|||||||
else:
|
else:
|
||||||
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
||||||
if countsOnly:
|
if countsOnly:
|
||||||
|
if csvPF:
|
||||||
|
csvPF.SetFormatJSON(False)
|
||||||
fieldsList = ['emailAddresses']
|
fieldsList = ['emailAddresses']
|
||||||
fields = _getPersonFields(PEOPLE_OTHER_CONTACTS_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
|
fields = _getPersonFields(PEOPLE_OTHER_CONTACTS_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
|
||||||
i, count, users = getEntityArgument(users)
|
i, count, users = getEntityArgument(users)
|
||||||
@@ -22813,6 +22892,8 @@ def _printShowPeople(source):
|
|||||||
function = 'searchDirectoryPeople'
|
function = 'searchDirectoryPeople'
|
||||||
else:
|
else:
|
||||||
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
||||||
|
if countsOnly and csvPF:
|
||||||
|
csvPF.SetFormatJSON(False)
|
||||||
fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
|
fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
|
||||||
printGettingAllEntityItemsForWhom(peopleEntityType, GC.Values[GC.DOMAIN], query=kwargs.get('query'))
|
printGettingAllEntityItemsForWhom(peopleEntityType, GC.Values[GC.DOMAIN], query=kwargs.get('query'))
|
||||||
try:
|
try:
|
||||||
@@ -22850,29 +22931,24 @@ def doInfoDomainPeopleContacts():
|
|||||||
# gam print people|peopleprofile [todrive <ToDriveAttribute>*]
|
# gam print people|peopleprofile [todrive <ToDriveAttribute>*]
|
||||||
# [query <String>]
|
# [query <String>]
|
||||||
# [mergesources <PeopleMergeSourceName>]
|
# [mergesources <PeopleMergeSourceName>]
|
||||||
# [countsonly]
|
|
||||||
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
||||||
# [formatjson [quotechar <Character>]]
|
# [countsonly|(formatjson [quotechar <Character>])]
|
||||||
# gam show people|peopleprofile
|
# gam show people|peopleprofile
|
||||||
# [query <String>]
|
# [query <String>]
|
||||||
# [mergesources <PeopleMergeSourceName>]
|
# [mergesources <PeopleMergeSourceName>]
|
||||||
# [countsonly]
|
|
||||||
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
||||||
# [formatjson]
|
# [countsonlyformatjson]
|
||||||
# gam print domaincontacts|peoplecontacts [todrive <ToDriveAttribute>*]
|
# gam print domaincontacts|peoplecontacts [todrive <ToDriveAttribute>*]
|
||||||
# [sources <PeopleSourceName>]
|
# [sources <PeopleSourceName>]
|
||||||
# [query <String>]
|
# [query <String>]
|
||||||
# [mergesources <PeopleMergeSourceName>]
|
# [mergesources <PeopleMergeSourceName>]
|
||||||
# [countsonly]
|
|
||||||
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
||||||
# [formatjson [quotechar <Character>]]
|
# [countsonly|(formatjson [quotechar <Character>])]
|
||||||
# gam show domaincontacts|peoplecontacts
|
# gam show domaincontacts|peoplecontacts
|
||||||
# [sources <PeopleSourceName>]
|
# [sources <PeopleSourceName>]
|
||||||
# [query <String>]
|
# [query <String>]
|
||||||
# [mergesources <PeopleMergeSourceName>]
|
# [mergesources <PeopleMergeSourceName>]
|
||||||
# [countsonly]
|
# [countsonlyformatjson]
|
||||||
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
|
|
||||||
# [formatjson]
|
|
||||||
def doPrintShowDomainPeopleProfiles():
|
def doPrintShowDomainPeopleProfiles():
|
||||||
_printShowPeople('profile')
|
_printShowPeople('profile')
|
||||||
|
|
||||||
@@ -26579,7 +26655,7 @@ def printShowChatEmojis(users):
|
|||||||
pageMessage=_getChatPageMessage(Ent.CHAT_EMOJI, user, i, count, pfilter),
|
pageMessage=_getChatPageMessage(Ent.CHAT_EMOJI, user, i, count, pfilter),
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
pageSize=CHAT_PAGE_SIZE, filter=pfilter)
|
pageSize=GC.Values[GC.CHAT_MAX_RESULTS], filter=pfilter)
|
||||||
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
|
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
|
||||||
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
|
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
|
||||||
continue
|
continue
|
||||||
@@ -26649,7 +26725,14 @@ def getChatSpaceParameters(myarg, body, typeChoicesMap, updateMask):
|
|||||||
|
|
||||||
CHAT_MEMBER_ROLE_MAP = {
|
CHAT_MEMBER_ROLE_MAP = {
|
||||||
'member': 'ROLE_MEMBER',
|
'member': 'ROLE_MEMBER',
|
||||||
'manager': 'ROLE_MANAGER'
|
'manager': 'ROLE_MANAGER',
|
||||||
|
'owner': 'ROLE_OWNER',
|
||||||
|
}
|
||||||
|
|
||||||
|
CHAT_ROLE_ENTITY_TYPE_MAP = {
|
||||||
|
'ROLE_MEMBER': Ent.CHAT_MEMBER_USER,
|
||||||
|
'ROLE_MANAGER': Ent.CHAT_MANAGER_USER,
|
||||||
|
'ROLE_OWNER': Ent.CHAT_OWNER_USER,
|
||||||
}
|
}
|
||||||
|
|
||||||
CHAT_MEMBER_TYPE_MAP = {
|
CHAT_MEMBER_TYPE_MAP = {
|
||||||
@@ -27006,7 +27089,6 @@ def _getChatSpaceSearchParms(myarg, queries, queryTimes, OBY):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
CHAT_PAGE_SIZE = 1000
|
|
||||||
CHAT_SPACES_ADMIN_ORDERBY_CHOICE_MAP = {
|
CHAT_SPACES_ADMIN_ORDERBY_CHOICE_MAP = {
|
||||||
'createtime': 'createTime',
|
'createtime': 'createTime',
|
||||||
'lastactivetime': 'lastActiveTime',
|
'lastactivetime': 'lastActiveTime',
|
||||||
@@ -27086,7 +27168,7 @@ def printShowChatSpaces(users):
|
|||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
|
||||||
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargsCS)
|
fields=fields, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargsCS)
|
||||||
if showAccessSettings:
|
if showAccessSettings:
|
||||||
for space in spaces:
|
for space in spaces:
|
||||||
if space['spaceType'] == 'SPACE':
|
if space['spaceType'] == 'SPACE':
|
||||||
@@ -27152,7 +27234,7 @@ def _getChatSpaceMembers(cd, chatSpace, ciGroupName):
|
|||||||
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, 0, 0, qfilter),
|
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, 0, 0, qfilter),
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
parent=chatSpace, fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargsUAA)
|
parent=chatSpace, fields=fields, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargsUAA)
|
||||||
for member in members:
|
for member in members:
|
||||||
_getChatMemberEmail(cd, member)
|
_getChatMemberEmail(cd, member)
|
||||||
gmember = {}
|
gmember = {}
|
||||||
@@ -27231,7 +27313,7 @@ def createChatMember(users):
|
|||||||
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.NOT_FOUND, GAPI.INVALID, GAPI.INVALID_ARGUMENT,
|
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.NOT_FOUND, GAPI.INVALID, GAPI.INVALID_ARGUMENT,
|
||||||
GAPI.INTERNAL_ERROR, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
GAPI.INTERNAL_ERROR, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
||||||
parent=parent, body=body, **kwargsUAA)
|
parent=parent, body=body, **kwargsUAA)
|
||||||
if role != 'ROLE_MEMBER' and entityType == Ent.CHAT_MANAGER_USER:
|
if role != 'ROLE_MEMBER' and entityType in (Ent.CHAT_MANAGER_USER, Ent.CHAT_OWNER_USER):
|
||||||
member = callGAPI(chat.spaces().members(), 'patch',
|
member = callGAPI(chat.spaces().members(), 'patch',
|
||||||
bailOnInternalError=True,
|
bailOnInternalError=True,
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
|
||||||
@@ -27289,7 +27371,7 @@ def createChatMember(users):
|
|||||||
missingArgumentExit('space')
|
missingArgumentExit('space')
|
||||||
if not userList and not groupList:
|
if not userList and not groupList:
|
||||||
missingArgumentExit('user|members|group|groups')
|
missingArgumentExit('user|members|group|groups')
|
||||||
userEntityType = Ent.CHAT_MEMBER_USER if role == 'ROLE_MEMBER' else Ent.CHAT_MANAGER_USER
|
userEntityType = CHAT_ROLE_ENTITY_TYPE_MAP[role]
|
||||||
userMembers = []
|
userMembers = []
|
||||||
for user in userList:
|
for user in userList:
|
||||||
userMembers.append({'member': {'name': f'users/{user}', 'type': mtype}})
|
userMembers.append({'member': {'name': f'users/{user}', 'type': mtype}})
|
||||||
@@ -27546,7 +27628,7 @@ def syncChatMembers(users):
|
|||||||
unknownArgumentExit()
|
unknownArgumentExit()
|
||||||
if not parent:
|
if not parent:
|
||||||
missingArgumentExit('space')
|
missingArgumentExit('space')
|
||||||
userEntityType = Ent.CHAT_MEMBER_USER if role == 'ROLE_MEMBER' else Ent.CHAT_MANAGER_USER
|
userEntityType = CHAT_ROLE_ENTITY_TYPE_MAP[role]
|
||||||
userMembers = {}
|
userMembers = {}
|
||||||
syncUsersSet = set()
|
syncUsersSet = set()
|
||||||
for user in userList:
|
for user in userList:
|
||||||
@@ -27576,7 +27658,7 @@ def syncChatMembers(users):
|
|||||||
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, i, count, qfilter),
|
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, i, count, qfilter),
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
parent=parent, showGroups=groupsSpecified, pageSize=CHAT_PAGE_SIZE, **kwargs, **kwargsUAA)
|
parent=parent, showGroups=groupsSpecified, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargs, **kwargsUAA)
|
||||||
for member in members:
|
for member in members:
|
||||||
if 'member' in member:
|
if 'member' in member:
|
||||||
if member['member']['type'] == mtype and member['role'] == role:
|
if member['member']['type'] == mtype and member['role'] == role:
|
||||||
@@ -27777,7 +27859,7 @@ def printShowChatMembers(users):
|
|||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
|
||||||
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=CHAT_PAGE_SIZE,
|
fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=GC.Values[GC.CHAT_MAX_RESULTS],
|
||||||
**kwargsCS)
|
**kwargsCS)
|
||||||
for space in sorted(spaces, key=lambda k: k[sortName]):
|
for space in sorted(spaces, key=lambda k: k[sortName]):
|
||||||
if space['spaceType'] == 'SPACE' and 'membershipCount' in space:
|
if space['spaceType'] == 'SPACE' and 'membershipCount' in space:
|
||||||
@@ -27794,7 +27876,7 @@ def printShowChatMembers(users):
|
|||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
|
||||||
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=CHAT_PAGE_SIZE,
|
fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=GC.Values[GC.CHAT_MAX_RESULTS],
|
||||||
**kwargsCS)
|
**kwargsCS)
|
||||||
for space in sorted(spaces, key=lambda k: k[sortName]):
|
for space in sorted(spaces, key=lambda k: k[sortName]):
|
||||||
# if 'membershipCount' in space:
|
# if 'membershipCount' in space:
|
||||||
@@ -27825,7 +27907,7 @@ def printShowChatMembers(users):
|
|||||||
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, j, jcount, qfilter),
|
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, j, jcount, qfilter),
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
parent=parentName, fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargs, **kwargsUAA)
|
parent=parentName, fields=fields, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargs, **kwargsUAA)
|
||||||
for member in members:
|
for member in members:
|
||||||
_getChatMemberEmail(cd, member)
|
_getChatMemberEmail(cd, member)
|
||||||
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
|
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
|
||||||
@@ -28139,7 +28221,7 @@ def printShowChatMessages(users):
|
|||||||
pageMessage=_getChatPageMessage(Ent.CHAT_MESSAGE, user, i, count, qfilter),
|
pageMessage=_getChatPageMessage(Ent.CHAT_MESSAGE, user, i, count, qfilter),
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
pageSize=CHAT_PAGE_SIZE, parent=parentName, filter=pfilter, showDeleted=showDeleted,
|
pageSize=GC.Values[GC.CHAT_MAX_RESULTS], parent=parentName, filter=pfilter, showDeleted=showDeleted,
|
||||||
fields=fields)
|
fields=fields)
|
||||||
for message in messages:
|
for message in messages:
|
||||||
if 'sender' in message:
|
if 'sender' in message:
|
||||||
@@ -28257,7 +28339,7 @@ def printShowChatEvents(users):
|
|||||||
pageMessage=_getChatPageMessage(Ent.CHAT_EVENT, user, i, count, qfilter),
|
pageMessage=_getChatPageMessage(Ent.CHAT_EVENT, user, i, count, qfilter),
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
pageSize=CHAT_PAGE_SIZE, parent=parentName, filter=pfilter)
|
pageSize=GC.Values[GC.CHAT_MAX_RESULTS], parent=parentName, filter=pfilter)
|
||||||
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
|
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
|
||||||
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
|
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
|
||||||
continue
|
continue
|
||||||
@@ -40119,7 +40201,7 @@ def _createCalendarEvents(user, origCal, function, calIds, count, body, paramete
|
|||||||
else:
|
else:
|
||||||
if parameters['showDayOfWeek']:
|
if parameters['showDayOfWeek']:
|
||||||
_getEventDaysOfWeek(event)
|
_getEventDaysOfWeek(event)
|
||||||
_printCalendarEvent(user, calId, event, parameters['csvPF'], parameters['FJQC'])
|
_printCalendarEvent(user, calId, event, parameters['csvPF'], parameters['FJQC'], {})
|
||||||
except (GAPI.invalid, GAPI.required, GAPI.timeRangeEmpty, GAPI.eventDurationExceedsLimit,
|
except (GAPI.invalid, GAPI.required, GAPI.timeRangeEmpty, GAPI.eventDurationExceedsLimit,
|
||||||
GAPI.requiredAccessLevel, GAPI.participantIsNeitherOrganizerNorAttendee,
|
GAPI.requiredAccessLevel, GAPI.participantIsNeitherOrganizerNorAttendee,
|
||||||
GAPI.malformedWorkingLocationEvent, GAPI.badRequest) as e:
|
GAPI.malformedWorkingLocationEvent, GAPI.badRequest) as e:
|
||||||
@@ -40223,7 +40305,7 @@ def _updateCalendarEvents(origUser, user, origCal, calIds, count, calendarEventE
|
|||||||
else:
|
else:
|
||||||
if parameters['showDayOfWeek']:
|
if parameters['showDayOfWeek']:
|
||||||
_getEventDaysOfWeek(event)
|
_getEventDaysOfWeek(event)
|
||||||
_printCalendarEvent(user, calId, event, parameters['csvPF'], parameters['FJQC'])
|
_printCalendarEvent(user, calId, event, parameters['csvPF'], parameters['FJQC'], {})
|
||||||
except (GAPI.notFound, GAPI.deleted) as e:
|
except (GAPI.notFound, GAPI.deleted) as e:
|
||||||
if not checkCalendarExists(cal, calId, j, jcount):
|
if not checkCalendarExists(cal, calId, j, jcount):
|
||||||
entityUnknownWarning(Ent.CALENDAR, calId, j, jcount)
|
entityUnknownWarning(Ent.CALENDAR, calId, j, jcount)
|
||||||
@@ -40520,10 +40602,12 @@ def _showCalendarEvent(primaryEmail, calId, eventEntityType, event, k, kcount, F
|
|||||||
showJSON(None, event, skipObjects)
|
showJSON(None, event, skipObjects)
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
|
|
||||||
def _printCalendarEvent(user, calId, event, csvPF, FJQC):
|
def _printCalendarEvent(user, calId, event, csvPF, FJQC, addCSVData):
|
||||||
row = {'calendarId': calId, 'id': event['id']}
|
row = {'calendarId': calId, 'id': event['id']}
|
||||||
if user:
|
if user:
|
||||||
row['primaryEmail'] = user
|
row['primaryEmail'] = user
|
||||||
|
if addCSVData:
|
||||||
|
row.update(addCSVData)
|
||||||
flattenJSON(event, flattened=row, timeObjects=EVENT_TIME_OBJECTS)
|
flattenJSON(event, flattened=row, timeObjects=EVENT_TIME_OBJECTS)
|
||||||
if not FJQC.formatJSON:
|
if not FJQC.formatJSON:
|
||||||
csvPF.WriteRowTitles(row)
|
csvPF.WriteRowTitles(row)
|
||||||
@@ -40536,7 +40620,7 @@ def _printCalendarEvent(user, calId, event, csvPF, FJQC):
|
|||||||
csvPF.WriteRowNoFilter(row)
|
csvPF.WriteRowNoFilter(row)
|
||||||
|
|
||||||
def _printShowCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity,
|
def _printShowCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity,
|
||||||
csvPF, FJQC, fieldsList):
|
csvPF, FJQC, fieldsList, addCSVData):
|
||||||
i = 0
|
i = 0
|
||||||
for calId in calIds:
|
for calId in calIds:
|
||||||
i += 1
|
i += 1
|
||||||
@@ -40562,7 +40646,7 @@ def _printShowCalendarEvents(origUser, user, origCal, calIds, count, calendarEve
|
|||||||
for event in events:
|
for event in events:
|
||||||
if calendarEventEntity['showDayOfWeek']:
|
if calendarEventEntity['showDayOfWeek']:
|
||||||
_getEventDaysOfWeek(event)
|
_getEventDaysOfWeek(event)
|
||||||
_printCalendarEvent(user, calId, event, csvPF, FJQC)
|
_printCalendarEvent(user, calId, event, csvPF, FJQC, addCSVData)
|
||||||
elif GC.Values[GC.CSV_OUTPUT_USERS_AUDIT] and user:
|
elif GC.Values[GC.CSV_OUTPUT_USERS_AUDIT] and user:
|
||||||
csvPF.WriteRowNoFilter({'calendarId': calId, 'primaryEmail': user, 'id': ''})
|
csvPF.WriteRowNoFilter({'calendarId': calId, 'primaryEmail': user, 'id': ''})
|
||||||
else:
|
else:
|
||||||
@@ -40580,6 +40664,8 @@ def _printShowCalendarEvents(origUser, user, origCal, calIds, count, calendarEve
|
|||||||
row = {'calendarId': calId}
|
row = {'calendarId': calId}
|
||||||
if user:
|
if user:
|
||||||
row['primaryEmail'] = user
|
row['primaryEmail'] = user
|
||||||
|
if addCSVData:
|
||||||
|
row.update(addCSVData)
|
||||||
row['events'] = jcount
|
row['events'] = jcount
|
||||||
if not calendarEventEntity['eventRowFilter']:
|
if not calendarEventEntity['eventRowFilter']:
|
||||||
csvPF.WriteRow(row)
|
csvPF.WriteRow(row)
|
||||||
@@ -40810,6 +40896,8 @@ def _getCalendarPrintShowEventOptions(calendarEventEntity, entityType):
|
|||||||
csvPF = CSVPrintFile(['primaryEmail', 'calendarId', 'id'] if entityType == Ent.USER else ['calendarId', 'id'], 'sortall', indexedTitles=EVENT_INDEXED_TITLES) if Act.csvFormat() else None
|
csvPF = CSVPrintFile(['primaryEmail', 'calendarId', 'id'] if entityType == Ent.USER else ['calendarId', 'id'], 'sortall', indexedTitles=EVENT_INDEXED_TITLES) if Act.csvFormat() else None
|
||||||
FJQC = FormatJSONQuoteChar(csvPF)
|
FJQC = FormatJSONQuoteChar(csvPF)
|
||||||
fieldsList = []
|
fieldsList = []
|
||||||
|
addCSVData = {}
|
||||||
|
addCSVDataLoc = 2 if entityType == Ent.USER else 1
|
||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
myarg = getArgument()
|
myarg = getArgument()
|
||||||
if csvPF and myarg == 'todrive':
|
if csvPF and myarg == 'todrive':
|
||||||
@@ -40818,6 +40906,9 @@ def _getCalendarPrintShowEventOptions(calendarEventEntity, entityType):
|
|||||||
pass
|
pass
|
||||||
elif myarg == 'fields':
|
elif myarg == 'fields':
|
||||||
_getEventFields(fieldsList)
|
_getEventFields(fieldsList)
|
||||||
|
elif csvPF and myarg == 'addcsvdata':
|
||||||
|
k = getString(Cmd.OB_STRING)
|
||||||
|
addCSVData[k] = getString(Cmd.OB_STRING, minLen=0)
|
||||||
elif myarg == 'countsonly':
|
elif myarg == 'countsonly':
|
||||||
calendarEventEntity['countsOnly'] = True
|
calendarEventEntity['countsOnly'] = True
|
||||||
elif myarg == 'showdayofweek':
|
elif myarg == 'showdayofweek':
|
||||||
@@ -40830,27 +40921,35 @@ def _getCalendarPrintShowEventOptions(calendarEventEntity, entityType):
|
|||||||
fieldsList = ['id']
|
fieldsList = ['id']
|
||||||
if csvPF:
|
if csvPF:
|
||||||
if calendarEventEntity['countsOnly']:
|
if calendarEventEntity['countsOnly']:
|
||||||
|
csvPF.SetFormatJSON(False)
|
||||||
csvPF.RemoveTitles(['id'])
|
csvPF.RemoveTitles(['id'])
|
||||||
|
if addCSVData:
|
||||||
|
csvPF.InsertTitles(addCSVDataLoc, sorted(addCSVData.keys()))
|
||||||
csvPF.AddTitles(['events'])
|
csvPF.AddTitles(['events'])
|
||||||
|
csvPF.SetSortAllTitles()
|
||||||
calendarEventEntity['countsOnlyTitles'] = csvPF.titlesList[:]
|
calendarEventEntity['countsOnlyTitles'] = csvPF.titlesList[:]
|
||||||
elif not FJQC.formatJSON and not fieldsList:
|
else:
|
||||||
csvPF.AddSortTitles(EVENT_PRINT_ORDER)
|
if addCSVData:
|
||||||
|
csvPF.InsertTitles(addCSVDataLoc, sorted(addCSVData.keys()))
|
||||||
|
if not FJQC.formatJSON and not fieldsList:
|
||||||
|
csvPF.AddTitles(EVENT_PRINT_ORDER)
|
||||||
|
csvPF.SetSortAllTitles()
|
||||||
_addEventEntitySelectFields(calendarEventEntity, fieldsList)
|
_addEventEntitySelectFields(calendarEventEntity, fieldsList)
|
||||||
return (csvPF, FJQC, fieldsList)
|
return (csvPF, FJQC, fieldsList, addCSVData)
|
||||||
|
|
||||||
# gam calendars <CalendarEntity> print events <EventEntity> <EventDisplayProperties>*
|
# gam calendars <CalendarEntity> print events <EventEntity> <EventDisplayProperties>*
|
||||||
# [fields <EventFieldNameList>] [showdayofweek]
|
# [fields <EventFieldNameList>] [showdayofweek]
|
||||||
# [countsonly [eventrowfilter]]
|
# (addcsvdata <FieldName> <String>)*
|
||||||
# [formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
|
# [eventrowfilter]
|
||||||
|
# [countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
|
||||||
# gam calendars <CalendarEntity> show events <EventEntity> <EventDisplayProperties>*
|
# gam calendars <CalendarEntity> show events <EventEntity> <EventDisplayProperties>*
|
||||||
# [fields <EventFieldNameList>] [showdayofweek]
|
# [fields <EventFieldNameList>] [showdayofweek]
|
||||||
# [countsonly]
|
# [countsonly|formatjson]
|
||||||
# [formatjson]
|
|
||||||
def doCalendarsPrintShowEvents(calIds):
|
def doCalendarsPrintShowEvents(calIds):
|
||||||
calendarEventEntity = getCalendarEventEntity()
|
calendarEventEntity = getCalendarEventEntity()
|
||||||
csvPF, FJQC, fieldsList = _getCalendarPrintShowEventOptions(calendarEventEntity, Ent.CALENDAR)
|
csvPF, FJQC, fieldsList, addCSVData = _getCalendarPrintShowEventOptions(calendarEventEntity, Ent.CALENDAR)
|
||||||
_printShowCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity,
|
_printShowCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity,
|
||||||
csvPF, FJQC, fieldsList)
|
csvPF, FJQC, fieldsList, addCSVData)
|
||||||
if csvPF:
|
if csvPF:
|
||||||
if calendarEventEntity['countsOnly'] and calendarEventEntity['eventRowFilter']:
|
if calendarEventEntity['countsOnly'] and calendarEventEntity['eventRowFilter']:
|
||||||
csvPF.SetTitles(calendarEventEntity['countsOnlyTitles'])
|
csvPF.SetTitles(calendarEventEntity['countsOnlyTitles'])
|
||||||
@@ -48857,13 +48956,15 @@ def _doInfoCourses(courseIdList):
|
|||||||
|
|
||||||
# gam info courses <CourseEntity> [owneraccess]
|
# gam info courses <CourseEntity> [owneraccess]
|
||||||
# [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly]
|
# [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly]
|
||||||
# [fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>] [formatjson]
|
# [fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>]
|
||||||
|
# [formatjson]
|
||||||
def doInfoCourses():
|
def doInfoCourses():
|
||||||
_doInfoCourses(getEntityList(Cmd.OB_COURSE_ENTITY, shlexSplit=True))
|
_doInfoCourses(getEntityList(Cmd.OB_COURSE_ENTITY, shlexSplit=True))
|
||||||
|
|
||||||
# gam info course <CourseID> [owneraccess]
|
# gam info course <CourseID> [owneraccess]
|
||||||
# [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly]
|
# [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly]
|
||||||
# [fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>] [formatjson]
|
# [fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>]
|
||||||
|
# [formatjson]
|
||||||
def doInfoCourse():
|
def doInfoCourse():
|
||||||
_doInfoCourses(getStringReturnInList(Cmd.OB_COURSE_ID))
|
_doInfoCourses(getStringReturnInList(Cmd.OB_COURSE_ID))
|
||||||
|
|
||||||
@@ -49181,7 +49282,7 @@ COURSE_ANNOUNCEMENTS_INDEXED_TITLES = ['materials']
|
|||||||
# (orderby <CourseAnnouncementOrderByFieldName> [ascending|descending])*)
|
# (orderby <CourseAnnouncementOrderByFieldName> [ascending|descending])*)
|
||||||
# [showcreatoremails|creatoremail] [fields <CourseAnnouncementFieldNameList>]
|
# [showcreatoremails|creatoremail] [fields <CourseAnnouncementFieldNameList>]
|
||||||
# [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
# [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||||
# [countsonly] [formatjson [quotechar <Character>]]
|
# [countsonly|(formatjson [quotechar <Character>])]
|
||||||
def doPrintCourseAnnouncements():
|
def doPrintCourseAnnouncements():
|
||||||
def _printCourseAnnouncement(course, courseAnnouncement, i, count):
|
def _printCourseAnnouncement(course, courseAnnouncement, i, count):
|
||||||
if applyCourseItemFilter and not _courseItemPassesFilter(courseAnnouncement, courseItemFilter):
|
if applyCourseItemFilter and not _courseItemPassesFilter(courseAnnouncement, courseItemFilter):
|
||||||
@@ -49237,6 +49338,8 @@ def doPrintCourseAnnouncements():
|
|||||||
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties)
|
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties)
|
||||||
if coursesInfo is None:
|
if coursesInfo is None:
|
||||||
return
|
return
|
||||||
|
if countsOnly:
|
||||||
|
csvPF.SetFormatJSON(False)
|
||||||
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
|
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
|
||||||
if showCreatorEmail and fieldsList:
|
if showCreatorEmail and fieldsList:
|
||||||
fieldsList.append('creatorUserId')
|
fieldsList.append('creatorUserId')
|
||||||
@@ -49293,7 +49396,7 @@ COURSE_TOPICS_SORT_TITLES = ['courseId', 'courseName', 'topicId', 'name', 'updat
|
|||||||
# (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
|
# (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
|
||||||
# [topicids <CourseTopicIDEntity>]
|
# [topicids <CourseTopicIDEntity>]
|
||||||
# [timefilter updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
# [timefilter updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||||
# [countsonly] [formatjson [quotechar <Character>]]
|
# [countsonly|(formatjson [quotechar <Character>])]
|
||||||
def doPrintCourseTopics():
|
def doPrintCourseTopics():
|
||||||
def _printCourseTopic(course, courseTopic):
|
def _printCourseTopic(course, courseTopic):
|
||||||
if applyCourseItemFilter and not _courseItemPassesFilter(courseTopic, courseItemFilter):
|
if applyCourseItemFilter and not _courseItemPassesFilter(courseTopic, courseItemFilter):
|
||||||
@@ -49334,6 +49437,8 @@ def doPrintCourseTopics():
|
|||||||
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties)
|
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties)
|
||||||
if coursesInfo is None:
|
if coursesInfo is None:
|
||||||
return
|
return
|
||||||
|
if countsOnly:
|
||||||
|
csvPF.SetFormatJSON(False)
|
||||||
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
|
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
|
||||||
courseTopicIdsLists = courseTopicIds if isinstance(courseTopicIds, dict) else None
|
courseTopicIdsLists = courseTopicIds if isinstance(courseTopicIds, dict) else None
|
||||||
i = 0
|
i = 0
|
||||||
@@ -49467,6 +49572,16 @@ def doPrintCourseWM(entityIDType, entityStateType):
|
|||||||
pass
|
pass
|
||||||
return topicNames
|
return topicNames
|
||||||
|
|
||||||
|
def _printCourseWMrow(course, courseWM):
|
||||||
|
row = flattenJSON(courseWM, flattened={'courseId': course['id'], 'courseName': course['name']}, timeObjects=TimeObjects,
|
||||||
|
simpleLists=['studentIds'] if showStudentsAsList else None, delimiter=delimiter)
|
||||||
|
if not FJQC.formatJSON:
|
||||||
|
csvPF.WriteRowTitles(row)
|
||||||
|
elif csvPF.CheckRowTitles(row):
|
||||||
|
csvPF.WriteRowNoFilter({'courseId': course['id'], 'courseName': course['name'],
|
||||||
|
'JSON': json.dumps(cleanJSON(courseWM, timeObjects=TimeObjects),
|
||||||
|
ensure_ascii=False, sort_keys=True)})
|
||||||
|
|
||||||
def _printCourseWM(course, courseWM, i, count):
|
def _printCourseWM(course, courseWM, i, count):
|
||||||
if applyCourseItemFilter and not _courseItemPassesFilter(courseWM, courseItemFilter):
|
if applyCourseItemFilter and not _courseItemPassesFilter(courseWM, courseItemFilter):
|
||||||
return
|
return
|
||||||
@@ -49478,14 +49593,13 @@ def doPrintCourseWM(entityIDType, entityStateType):
|
|||||||
topicId = courseWM.get('topicId')
|
topicId = courseWM.get('topicId')
|
||||||
if topicId:
|
if topicId:
|
||||||
courseWM['topicName'] = topicNames.get(topicId, topicId)
|
courseWM['topicName'] = topicNames.get(topicId, topicId)
|
||||||
row = flattenJSON(courseWM, flattened={'courseId': course['id'], 'courseName': course['name']}, timeObjects=TimeObjects,
|
if not oneItemPerRow or not courseWM.get('materials', []):
|
||||||
simpleLists=['studentIds'] if showStudentsAsList else None, delimiter=delimiter)
|
_printCourseWMrow(course, courseWM)
|
||||||
if not FJQC.formatJSON:
|
else:
|
||||||
csvPF.WriteRowTitles(row)
|
courseMaterials = courseWM.pop('materials')
|
||||||
elif csvPF.CheckRowTitles(row):
|
for courseMaterial in courseMaterials:
|
||||||
csvPF.WriteRowNoFilter({'courseId': course['id'], 'courseName': course['name'],
|
courseWM['materials'] = courseMaterial
|
||||||
'JSON': json.dumps(cleanJSON(courseWM, timeObjects=TimeObjects),
|
_printCourseWMrow(course, courseWM)
|
||||||
ensure_ascii=False, sort_keys=True)})
|
|
||||||
|
|
||||||
croom = buildGAPIObject(API.CLASSROOM)
|
croom = buildGAPIObject(API.CLASSROOM)
|
||||||
if entityIDType == Ent.COURSE_WORK_ID:
|
if entityIDType == Ent.COURSE_WORK_ID:
|
||||||
@@ -49523,7 +49637,7 @@ def doPrintCourseWM(entityIDType, entityStateType):
|
|||||||
courseShowProperties = _initCourseShowProperties(['name'])
|
courseShowProperties = _initCourseShowProperties(['name'])
|
||||||
OBY = OrderBy(OrderbyChoiceMap)
|
OBY = OrderBy(OrderbyChoiceMap)
|
||||||
creatorEmails = {}
|
creatorEmails = {}
|
||||||
showCreatorEmail = showTopicNames = False
|
oneItemPerRow = showCreatorEmail = showTopicNames = False
|
||||||
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
|
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
|
||||||
countsOnly = showStudentsAsList = False
|
countsOnly = showStudentsAsList = False
|
||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
@@ -49540,6 +49654,9 @@ def doPrintCourseWM(entityIDType, entityStateType):
|
|||||||
pass
|
pass
|
||||||
elif myarg == 'orderby':
|
elif myarg == 'orderby':
|
||||||
OBY.GetChoice()
|
OBY.GetChoice()
|
||||||
|
elif myarg == 'oneitemperrow':
|
||||||
|
oneItemPerRow = True
|
||||||
|
csvPF.RemoveIndexedTitles('materials')
|
||||||
elif myarg in {'showcreatoremails', 'creatoremail'}:
|
elif myarg in {'showcreatoremails', 'creatoremail'}:
|
||||||
showCreatorEmail = True
|
showCreatorEmail = True
|
||||||
elif myarg == 'showtopicnames':
|
elif myarg == 'showtopicnames':
|
||||||
@@ -49566,6 +49683,8 @@ def doPrintCourseWM(entityIDType, entityStateType):
|
|||||||
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties)
|
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties)
|
||||||
if coursesInfo is None:
|
if coursesInfo is None:
|
||||||
return
|
return
|
||||||
|
if countsOnly:
|
||||||
|
csvPF.SetFormatJSON(False)
|
||||||
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
|
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
|
||||||
courseWMIds = courseWMSelectionParameters['courseWMIds']
|
courseWMIds = courseWMSelectionParameters['courseWMIds']
|
||||||
courseWMIdsLists = courseWMIds if isinstance(courseWMIds, dict) else {}
|
courseWMIdsLists = courseWMIds if isinstance(courseWMIds, dict) else {}
|
||||||
@@ -49620,7 +49739,8 @@ def doPrintCourseWM(entityIDType, entityStateType):
|
|||||||
# (orderby <CourseMaterialsOrderByFieldName> [ascending|descending])*)
|
# (orderby <CourseMaterialsOrderByFieldName> [ascending|descending])*)
|
||||||
# [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
|
# [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
|
||||||
# [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
# [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||||
# [countsonly] [formatjson [quotechar <Character>]]
|
# [oneitemperrow]
|
||||||
|
# [countsonly|(formatjson [quotechar <Character>])]
|
||||||
def doPrintCourseMaterials():
|
def doPrintCourseMaterials():
|
||||||
doPrintCourseWM(Ent.COURSE_MATERIAL_ID, Ent.COURSE_MATERIAL_STATE)
|
doPrintCourseWM(Ent.COURSE_MATERIAL_ID, Ent.COURSE_MATERIAL_STATE)
|
||||||
|
|
||||||
@@ -49631,7 +49751,8 @@ def doPrintCourseMaterials():
|
|||||||
# [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseWorkFieldNameList>]
|
# [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseWorkFieldNameList>]
|
||||||
# [showstudentsaslist [<Boolean>]] [delimiter <Character>]
|
# [showstudentsaslist [<Boolean>]] [delimiter <Character>]
|
||||||
# [timefilter creationtime|updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
# [timefilter creationtime|updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||||
# [countsonly] [formatjson [quotechar <Character>]]
|
# [oneitemperrow]
|
||||||
|
# [countsonly|(formatjson [quotechar <Character>])]
|
||||||
def doPrintCourseWork():
|
def doPrintCourseWork():
|
||||||
doPrintCourseWM(Ent.COURSE_WORK_ID, Ent.COURSE_WORK_STATE)
|
doPrintCourseWM(Ent.COURSE_WORK_ID, Ent.COURSE_WORK_STATE)
|
||||||
|
|
||||||
@@ -49675,7 +49796,7 @@ def _gettingCourseSubmissionQuery(courseSubmissionStates, late, userId):
|
|||||||
# (submissionids <CourseSubmissionIDEntity>)|((submissionstates <CourseSubmissionStateList>)*) [late|notlate]
|
# (submissionids <CourseSubmissionIDEntity>)|((submissionstates <CourseSubmissionStateList>)*) [late|notlate]
|
||||||
# [fields <CourseSubmissionFieldNameList>] [showuserprofile]
|
# [fields <CourseSubmissionFieldNameList>] [showuserprofile]
|
||||||
# [timefilter creationtime|updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
# [timefilter creationtime|updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||||
# [countsonly] [formatjson [quotechar <Character>]]
|
# [countsonly|(formatjson [quotechar <Character>])]
|
||||||
def doPrintCourseSubmissions():
|
def doPrintCourseSubmissions():
|
||||||
def _printCourseSubmission(course, courseSubmission):
|
def _printCourseSubmission(course, courseSubmission):
|
||||||
if applyCourseItemFilter and not _courseItemPassesFilter(courseSubmission, courseItemFilter):
|
if applyCourseItemFilter and not _courseItemPassesFilter(courseSubmission, courseItemFilter):
|
||||||
@@ -49757,6 +49878,8 @@ def doPrintCourseSubmissions():
|
|||||||
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties, getOwnerId=True)
|
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties, getOwnerId=True)
|
||||||
if coursesInfo is None:
|
if coursesInfo is None:
|
||||||
return
|
return
|
||||||
|
if countsOnly:
|
||||||
|
csvPF.SetFormatJSON(False)
|
||||||
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
|
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
|
||||||
courseWorkIds = courseWMSelectionParameters['courseWMIds']
|
courseWorkIds = courseWMSelectionParameters['courseWMIds']
|
||||||
courseWorkIdsLists = courseWorkIds if isinstance(courseWorkIds, dict) else {}
|
courseWorkIdsLists = courseWorkIds if isinstance(courseWorkIds, dict) else {}
|
||||||
@@ -53503,16 +53626,16 @@ def infoCalendarEvents(users):
|
|||||||
|
|
||||||
# gam <UserTypeEntity> print events <UserCalendarEntity> <EventEntity> <EventDisplayProperties>*
|
# gam <UserTypeEntity> print events <UserCalendarEntity> <EventEntity> <EventDisplayProperties>*
|
||||||
# [fields <EventFieldNameList>] [showdayofweek]
|
# [fields <EventFieldNameList>] [showdayofweek]
|
||||||
# [countsonly [eventrowfilter]]
|
# (addcsvdata <FieldName> <String>)*
|
||||||
# [formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
|
# [eventrowfilter]
|
||||||
|
# [countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
|
||||||
# gam <UserTypeEntity> show events <UserCalendarEntity> <EventEntity> <EventDisplayProperties>*
|
# gam <UserTypeEntity> show events <UserCalendarEntity> <EventEntity> <EventDisplayProperties>*
|
||||||
# [fields <EventFieldNameList>] [showdayofweek]
|
# [fields <EventFieldNameList>] [showdayofweek]
|
||||||
# [countsonly]]
|
# ~[countsonly|formatjson]
|
||||||
# [formatjson]
|
|
||||||
def printShowCalendarEvents(users):
|
def printShowCalendarEvents(users):
|
||||||
calendarEntity = getUserCalendarEntity()
|
calendarEntity = getUserCalendarEntity()
|
||||||
calendarEventEntity = getCalendarEventEntity()
|
calendarEventEntity = getCalendarEventEntity()
|
||||||
csvPF, FJQC, fieldsList = _getCalendarPrintShowEventOptions(calendarEventEntity, Ent.USER)
|
csvPF, FJQC, fieldsList, addCSVData = _getCalendarPrintShowEventOptions(calendarEventEntity, Ent.USER)
|
||||||
i, count, users = getEntityArgument(users)
|
i, count, users = getEntityArgument(users)
|
||||||
for user in users:
|
for user in users:
|
||||||
i += 1
|
i += 1
|
||||||
@@ -53523,7 +53646,7 @@ def printShowCalendarEvents(users):
|
|||||||
continue
|
continue
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
_printShowCalendarEvents(origUser, user, cal, calIds, jcount, calendarEventEntity,
|
_printShowCalendarEvents(origUser, user, cal, calIds, jcount, calendarEventEntity,
|
||||||
csvPF, FJQC, fieldsList)
|
csvPF, FJQC, fieldsList, addCSVData)
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
if csvPF:
|
if csvPF:
|
||||||
if calendarEventEntity['countsOnly'] and calendarEventEntity['eventRowFilter']:
|
if calendarEventEntity['countsOnly'] and calendarEventEntity['eventRowFilter']:
|
||||||
@@ -53967,7 +54090,7 @@ def printShowStatusEvent(users, eventType):
|
|||||||
for event in events:
|
for event in events:
|
||||||
if showDayOfWeek:
|
if showDayOfWeek:
|
||||||
_getEventDaysOfWeek(event)
|
_getEventDaysOfWeek(event)
|
||||||
_printCalendarEvent(user, calId, event, csvPF, FJQC)
|
_printCalendarEvent(user, calId, event, csvPF, FJQC, {})
|
||||||
if 'pdelta' in wlDate:
|
if 'pdelta' in wlDate:
|
||||||
first = first.shift(**wlDate['pdelta'])
|
first = first.shift(**wlDate['pdelta'])
|
||||||
last = last.shift(**wlDate['pdelta'])
|
last = last.shift(**wlDate['pdelta'])
|
||||||
@@ -77218,7 +77341,7 @@ TASK_QUERY_STATE_MAP = {
|
|||||||
# [updatedmin <Time>]
|
# [updatedmin <Time>]
|
||||||
# [showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
|
# [showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
|
||||||
# [orderby completed|due|updated]
|
# [orderby completed|due|updated]
|
||||||
# [countsonly | (formatjson [quotechar <Character>])]
|
# [countsonly|(formatjson [quotechar <Character>])]
|
||||||
def printShowTasks(users):
|
def printShowTasks(users):
|
||||||
def _showTaskAndChildren(tasklist, taskId, k, compact):
|
def _showTaskAndChildren(tasklist, taskId, k, compact):
|
||||||
if taskId in taskParentsProcessed:
|
if taskId in taskParentsProcessed:
|
||||||
@@ -77285,8 +77408,11 @@ def printShowTasks(users):
|
|||||||
csvPF.SetTitles(['User', CSVTitle])
|
csvPF.SetTitles(['User', CSVTitle])
|
||||||
else:
|
else:
|
||||||
FJQC.GetFormatJSONQuoteChar(myarg, False)
|
FJQC.GetFormatJSONQuoteChar(myarg, False)
|
||||||
if csvPF and FJQC.formatJSON:
|
if csvPF:
|
||||||
csvPF.SetJSONTitles(['User', 'tasklistId', 'id', 'taskId', 'title', 'JSON'])
|
if countsOnly:
|
||||||
|
csvPF.SetFormatJSON(False)
|
||||||
|
elif FJQC.formatJSON:
|
||||||
|
csvPF.SetJSONTitles(['User', 'tasklistId', 'id', 'taskId', 'title', 'JSON'])
|
||||||
i, count, users = getEntityArgument(users)
|
i, count, users = getEntityArgument(users)
|
||||||
for user in users:
|
for user in users:
|
||||||
i += 1
|
i += 1
|
||||||
@@ -77485,7 +77611,7 @@ def processTasklists(users):
|
|||||||
# gam <UserTypeEntity> show tasklists
|
# gam <UserTypeEntity> show tasklists
|
||||||
# [countsonly|formatjson]
|
# [countsonly|formatjson]
|
||||||
# gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
|
# gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
|
||||||
# [countsonly | (formatjson [quotechar <Character>])]
|
# [countsonly|(formatjson [quotechar <Character>])]
|
||||||
def printShowTasklists(users):
|
def printShowTasklists(users):
|
||||||
csvPF = CSVPrintFile(['User', 'id', 'title']) if Act.csvFormat() else None
|
csvPF = CSVPrintFile(['User', 'id', 'title']) if Act.csvFormat() else None
|
||||||
if csvPF:
|
if csvPF:
|
||||||
@@ -77503,6 +77629,8 @@ def printShowTasklists(users):
|
|||||||
csvPF.SetTitles(['User', CSVTitle])
|
csvPF.SetTitles(['User', CSVTitle])
|
||||||
else:
|
else:
|
||||||
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
||||||
|
if countsOnly and csvPF:
|
||||||
|
csvPF.SetFormatJSON(False)
|
||||||
i, count, users = getEntityArgument(users)
|
i, count, users = getEntityArgument(users)
|
||||||
for user in users:
|
for user in users:
|
||||||
i += 1
|
i += 1
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ CACHE_DISCOVERY_ONLY = 'cache_discovery_only'
|
|||||||
CHANNEL_CUSTOMER_ID = 'channel_customer_id'
|
CHANNEL_CUSTOMER_ID = 'channel_customer_id'
|
||||||
# Character set of batch, csv, data files
|
# Character set of batch, csv, data files
|
||||||
CHARSET = 'charset'
|
CHARSET = 'charset'
|
||||||
|
# When retrieving lists of Chat items from API, how many should be retrieved in each chunk
|
||||||
|
CHAT_MAX_RESULTS = 'chat_max_results'
|
||||||
# When retrieving lists of Google Classroom items from API, how many should be retrieved in each chunk
|
# When retrieving lists of Google Classroom items from API, how many should be retrieved in each chunk
|
||||||
CLASSROOM_MAX_RESULTS = 'classroom_max_results'
|
CLASSROOM_MAX_RESULTS = 'classroom_max_results'
|
||||||
# Path to client_secrets.json
|
# Path to client_secrets.json
|
||||||
@@ -335,6 +337,7 @@ Defaults = {
|
|||||||
CACHE_DISCOVERY_ONLY: TRUE,
|
CACHE_DISCOVERY_ONLY: TRUE,
|
||||||
CHARSET: DEFAULT_CHARSET,
|
CHARSET: DEFAULT_CHARSET,
|
||||||
CHANNEL_CUSTOMER_ID: '',
|
CHANNEL_CUSTOMER_ID: '',
|
||||||
|
CHAT_MAX_RESULTS: '100',
|
||||||
CLASSROOM_MAX_RESULTS: '0',
|
CLASSROOM_MAX_RESULTS: '0',
|
||||||
CLIENT_SECRETS_JSON: FN_CLIENT_SECRETS_JSON,
|
CLIENT_SECRETS_JSON: FN_CLIENT_SECRETS_JSON,
|
||||||
CLOCK_SKEW_IN_SECONDS: '10',
|
CLOCK_SKEW_IN_SECONDS: '10',
|
||||||
@@ -502,6 +505,7 @@ VAR_INFO = {
|
|||||||
CACHE_DISCOVERY_ONLY: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'allcache.txt', VAR_SFFT: (TRUE, FALSE)},
|
CACHE_DISCOVERY_ONLY: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'allcache.txt', VAR_SFFT: (TRUE, FALSE)},
|
||||||
CHARSET: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GAM_CHARSET', VAR_LIMITS: (1, None)},
|
CHARSET: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GAM_CHARSET', VAR_LIMITS: (1, None)},
|
||||||
CHANNEL_CUSTOMER_ID: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
|
CHANNEL_CUSTOMER_ID: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
|
||||||
|
CHAT_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
|
||||||
CLASSROOM_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 1000)},
|
CLASSROOM_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 1000)},
|
||||||
CLIENT_SECRETS_JSON: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'CLIENTSECRETS', VAR_ACCESS: os.R_OK},
|
CLIENT_SECRETS_JSON: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'CLIENTSECRETS', VAR_ACCESS: os.R_OK},
|
||||||
CLOCK_SKEW_IN_SECONDS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 3600)},
|
CLOCK_SKEW_IN_SECONDS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 3600)},
|
||||||
|
|||||||
@@ -1138,6 +1138,7 @@ class GamCLArgs():
|
|||||||
OB_ARGUMENT = 'argument'
|
OB_ARGUMENT = 'argument'
|
||||||
OB_ASP_ID_LIST = 'ASPIDList'
|
OB_ASP_ID_LIST = 'ASPIDList'
|
||||||
OB_ASSET_ID = 'AssetID'
|
OB_ASSET_ID = 'AssetID'
|
||||||
|
OB_ADMIN_ASSIGNEE_TYPE_LIST = 'AdminAssigneeTypeList'
|
||||||
OB_BROWSER_ENROLLEMNT_TOKEN_ID = 'BrowserEnrollmentTokenID'
|
OB_BROWSER_ENROLLEMNT_TOKEN_ID = 'BrowserEnrollmentTokenID'
|
||||||
OB_BROWSER_ENTITY = 'BrowserEntity'
|
OB_BROWSER_ENTITY = 'BrowserEntity'
|
||||||
OB_BUILDING_ID = 'BuildingID'
|
OB_BUILDING_ID = 'BuildingID'
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ class GamEntity():
|
|||||||
CHAT_MEMBER_USER = 'chmu'
|
CHAT_MEMBER_USER = 'chmu'
|
||||||
CHAT_MESSAGE = 'chms'
|
CHAT_MESSAGE = 'chms'
|
||||||
CHAT_MESSAGE_ID = 'chmi'
|
CHAT_MESSAGE_ID = 'chmi'
|
||||||
|
CHAT_OWNER_USER = 'chou'
|
||||||
CHAT_SPACE = 'chsp'
|
CHAT_SPACE = 'chsp'
|
||||||
CHAT_THREAD = 'chth'
|
CHAT_THREAD = 'chth'
|
||||||
CHILD_ORGANIZATIONAL_UNIT = 'corg'
|
CHILD_ORGANIZATIONAL_UNIT = 'corg'
|
||||||
@@ -462,6 +463,7 @@ class GamEntity():
|
|||||||
CHAT_MEMBER: ['Chat Members', 'Chat Member'],
|
CHAT_MEMBER: ['Chat Members', 'Chat Member'],
|
||||||
CHAT_MEMBER_GROUP: ['Chat Group Members', 'Chat Group Member'],
|
CHAT_MEMBER_GROUP: ['Chat Group Members', 'Chat Group Member'],
|
||||||
CHAT_MEMBER_USER: ['Chat User Members', 'Chat User Member'],
|
CHAT_MEMBER_USER: ['Chat User Members', 'Chat User Member'],
|
||||||
|
CHAT_OWNER_USER: ['Chat User Owners', 'Chat User Owner'],
|
||||||
CHAT_SPACE: ['Chat Spaces', 'Chat Space'],
|
CHAT_SPACE: ['Chat Spaces', 'Chat Space'],
|
||||||
CHAT_THREAD: ['Chat Threads', 'Chat Thread'],
|
CHAT_THREAD: ['Chat Threads', 'Chat Thread'],
|
||||||
CHILD_ORGANIZATIONAL_UNIT: ['Child Organizational Units', 'Child Organizational Unit'],
|
CHILD_ORGANIZATIONAL_UNIT: ['Child Organizational Units', 'Child Organizational Unit'],
|
||||||
|
|||||||
@@ -1475,16 +1475,20 @@ gam delete admin <RoleAssignmentId>
|
|||||||
## Display administrators
|
## Display administrators
|
||||||
```
|
```
|
||||||
gam print admins [todrive <ToDriveAttribute>*]
|
gam print admins [todrive <ToDriveAttribute>*]
|
||||||
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition]
|
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
|
||||||
[privileges] [oneitemperrow]
|
[recursive] [condition] [privileges] [oneitemperrow]
|
||||||
gam show admins
|
gam show admins
|
||||||
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [privileges]
|
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
|
||||||
|
[recursive] [condition] [privileges]
|
||||||
```
|
```
|
||||||
By default, all administrators and roles are displayed; choose from the following
|
By default, all administrators and roles are displayed; choose from the following
|
||||||
options to limit the display:
|
options to limit the display:
|
||||||
* `user <UserItem>` - Display only this administrator
|
* `user|group <EmailAddress>|<UniqueID>` - Display assignments to this administrator
|
||||||
* `role <RoleItem>` - Display only administrators with this role
|
* `role <RoleItem>` - Display only administrators with this role
|
||||||
|
|
||||||
|
By default, assignments to security groups are shown as a single item; use `recursive`
|
||||||
|
to display assignments to the members of the security groups; the security group membershop is recursively expanded.
|
||||||
|
|
||||||
* `condition` - Display any conditions associated with a role assignment
|
* `condition` - Display any conditions associated with a role assignment
|
||||||
* `privileges` - Display privileges associated with each role assignment
|
* `privileges` - Display privileges associated with each role assignment
|
||||||
|
|
||||||
|
|||||||
@@ -567,7 +567,7 @@ By default, Gam displays the information as an indented list of keys and values.
|
|||||||
```
|
```
|
||||||
gam calendar <CalendarEntity> show events [<EventEntity>] <EventDisplayProperty>*
|
gam calendar <CalendarEntity> show events [<EventEntity>] <EventDisplayProperty>*
|
||||||
[fields <EventFieldNameList>] [showdayofweek]
|
[fields <EventFieldNameList>] [showdayofweek]
|
||||||
[countsly] [formatjson]
|
[countsly|formatjson]
|
||||||
```
|
```
|
||||||
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
|
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
|
||||||
|
|
||||||
@@ -586,8 +586,9 @@ By default, Gam displays event details, use `countsonly` to display only the num
|
|||||||
```
|
```
|
||||||
gam calendar <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>*
|
gam calendar <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>*
|
||||||
[fields <EventFieldNameList>] [showdayofweek]
|
[fields <EventFieldNameList>] [showdayofweek]
|
||||||
[countsonly [eventrowfilter]]
|
(addcsvdata <FieldName> <String>)*
|
||||||
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
|
[eventrowfilter]
|
||||||
|
[countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
|
||||||
```
|
```
|
||||||
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
|
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
|
||||||
|
|
||||||
@@ -598,6 +599,9 @@ option `singleevents` to display all instances of a recurring event.
|
|||||||
|
|
||||||
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
|
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
|
||||||
|
|
||||||
|
Add additional columns of data from the command line to the output after the calendarId.
|
||||||
|
* `addcsvdata <FieldName> <String>`
|
||||||
|
|
||||||
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
|
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
|
||||||
* `formatjson` - Display the fields in JSON format.
|
* `formatjson` - Display the fields in JSON format.
|
||||||
|
|
||||||
|
|||||||
@@ -570,6 +570,7 @@ gam print course-materials [todrive <ToDriveAttribute>*]
|
|||||||
(orderby <CourseMaterialOrderByFieldName> [ascending|descending])*)
|
(orderby <CourseMaterialOrderByFieldName> [ascending|descending])*)
|
||||||
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
|
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
|
||||||
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||||
|
[oneitemperrow]
|
||||||
[countsonly] [formatjson [quotechar <Character>]]
|
[countsonly] [formatjson [quotechar <Character>]]
|
||||||
```
|
```
|
||||||
By default, the `print course-materials` command displays course materials information for all courses.
|
By default, the `print course-materials` command displays course materials information for all courses.
|
||||||
@@ -600,6 +601,10 @@ By default, all course materials fields are displayed; use the following options
|
|||||||
* `showtopicnames` - Display topic names; requires and additional API call per course.
|
* `showtopicnames` - Display topic names; requires and additional API call per course.
|
||||||
* `fields <CourseMaterialsFieldNameList>` - Select specific fields to display.
|
* `fields <CourseMaterialsFieldNameList>` - Select specific fields to display.
|
||||||
|
|
||||||
|
With `print course-materials`, the materials selected for display are all output on one row/line as a repeating item with the other course fields.
|
||||||
|
When `oneitemperrow` is specified, each material is output on a separate row/line with the other course fields.
|
||||||
|
This simplifies processing the materials in the CSV file with subsequent Gam commands.
|
||||||
|
|
||||||
Use the `countsonly` option to display the number of course materials in a course but not their details.
|
Use the `countsonly` option to display the number of course materials in a course but not their details.
|
||||||
|
|
||||||
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
|
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
|
||||||
@@ -662,6 +667,7 @@ gam print course-work [todrive <ToDriveAttribute>*]
|
|||||||
[showcreatoremails] [showtopicnames] [fields <CourseWorkFieldNameList>]
|
[showcreatoremails] [showtopicnames] [fields <CourseWorkFieldNameList>]
|
||||||
[showstudentsaslist [<Boolean>]] [delimiter <Character>]
|
[showstudentsaslist [<Boolean>]] [delimiter <Character>]
|
||||||
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||||
|
[oneitemperrow]
|
||||||
[countsonly] [formatjson [quotechar <Character>]]
|
[countsonly] [formatjson [quotechar <Character>]]
|
||||||
```
|
```
|
||||||
By default, the `print course-work` command displays course work information for all courses.
|
By default, the `print course-work` command displays course work information for all courses.
|
||||||
@@ -695,6 +701,10 @@ By default, all course work fields are displayed; use the following options to m
|
|||||||
By default, when course work is assigned to individual students, the student IDs are displayed in multiple indexed columns.
|
By default, when course work is assigned to individual students, the student IDs are displayed in multiple indexed columns.
|
||||||
Use options `showstudentsaslist [<Boolean>]` and `delimiter <Character>` to display the student IDs is a single column as a delimited list.
|
Use options `showstudentsaslist [<Boolean>]` and `delimiter <Character>` to display the student IDs is a single column as a delimited list.
|
||||||
|
|
||||||
|
With `print course-work`, any materials are all output on one row/line as a repeating item with the other course fields.
|
||||||
|
When `oneitemperrow` is specified, each material is output on a separate row/line with the other course fields.
|
||||||
|
This simplifies processing the materials in the CSV file with subsequent Gam commands.
|
||||||
|
|
||||||
Use the `countsonly` option to display the number of course works in a course but not their details.
|
Use the `countsonly` option to display the number of course works in a course but not their details.
|
||||||
|
|
||||||
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
|
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
- [Delete duplicate email addresses from contacts](#delete-duplicate-email-addresses-from-contacts)
|
- [Delete duplicate email addresses from contacts](#delete-duplicate-email-addresses-from-contacts)
|
||||||
- [Manage domain contact photos](#manage-domain-contact-photos)
|
- [Manage domain contact photos](#manage-domain-contact-photos)
|
||||||
- [Display domain shared contacts](#display-domain-shared-contacts)
|
- [Display domain shared contacts](#display-domain-shared-contacts)
|
||||||
- [Display global address list](#display-global-address-list)
|
- [Display global address list](#Global-Address-List)
|
||||||
|
|
||||||
## API documentation
|
## API documentation
|
||||||
* [Domain Shared Contacts API](https://developers.google.com/admin-sdk/domain-shared-contacts)
|
* [Domain Shared Contacts API](https://developers.google.com/admin-sdk/domain-shared-contacts)
|
||||||
|
|||||||
@@ -25,14 +25,14 @@ start a new terminal session and reissue the command from above.
|
|||||||
## Executable, Manual
|
## Executable, Manual
|
||||||
|
|
||||||
* Executable Archive, Manual, Linux/Google Cloud Shell
|
* Executable Archive, Manual, Linux/Google Cloud Shell
|
||||||
- `gam-7.wx.yz-linux-x86_64-glibc2.35.tar.xz`
|
- `gam-7.wx.yz-linux-x86_64-glibc2.36.tar.xz`
|
||||||
- `gam-7.wx.yz-linux-x86_64-glibc2.39.tar.xz`
|
- `gam-7.wx.yz-linux-x86_64-glibc2.39.tar.xz`
|
||||||
- `gam-7.wx.yz-linux-x86_64-legacy.tar.xz`
|
- `gam-7.wx.yz-linux-x86_64-legacy.tar.xz`
|
||||||
- Download the archive, extract the contents into some directory.
|
- Download the archive, extract the contents into some directory.
|
||||||
- Start a terminal session.
|
- Start a terminal session.
|
||||||
|
|
||||||
* Executable Archive, Manual, Raspberry Pi/ChromeOS ARM devices
|
* Executable Archive, Manual, Raspberry Pi/ChromeOS ARM devices
|
||||||
- `gam-7.wx.yz-linux-arm64-glibc2.35.tar.xz`
|
- `gam-7.wx.yz-linux-arm64-glibc2.36.tar.xz`
|
||||||
- `gam-7.wx.yz-linux-arm64-glibc2.39.tar.xz`
|
- `gam-7.wx.yz-linux-arm64-glibc2.39.tar.xz`
|
||||||
- `gam-7.wx.yz-linux-arm64-legacy.tar.xz`
|
- `gam-7.wx.yz-linux-arm64-legacy.tar.xz`
|
||||||
- Download the archive, extract the contents into some directory.
|
- Download the archive, extract the contents into some directory.
|
||||||
@@ -43,16 +43,26 @@ start a new terminal session and reissue the command from above.
|
|||||||
- Download the archive, extract the contents into some directory.
|
- Download the archive, extract the contents into some directory.
|
||||||
- Start a terminal session.
|
- Start a terminal session.
|
||||||
|
|
||||||
* Executable Archive, Manual, Mac OS versions Sequoia - M3
|
* Executable Archive, Manual, Mac OS versions Sequoia - M2/M3
|
||||||
- `gam-7.wx.yz-macos15.4-arm64.tar.xz`
|
- `gam-7.wx.yz-macos15.6-arm64.tar.xz`
|
||||||
- Download the archive, extract the contents into some directory.
|
- Download the archive, extract the contents into some directory.
|
||||||
- Start a terminal session.
|
- Start a terminal session.
|
||||||
|
|
||||||
* Executable Archive, Manual, Mac OS, versions Ventura, Sonoma, Sequoia - Intel
|
* Executable Archive, Manual, Mac OS versions Tahoe - M2/M3/M4
|
||||||
|
- `gam-7.wx.yz-macos26.0-arm64.tar.xz`
|
||||||
|
- Download the archive, extract the contents into some directory.
|
||||||
|
- Start a terminal session.
|
||||||
|
|
||||||
|
* Executable Archive, Manual, Mac OS, versions Ventura, Sonoma - Intel
|
||||||
- `gam-7.wx.yz-macos13.7-x86_64.tar.xz`
|
- `gam-7.wx.yz-macos13.7-x86_64.tar.xz`
|
||||||
- Download the archive, extract the contents into some directory.
|
- Download the archive, extract the contents into some directory.
|
||||||
- Start a terminal session.
|
- Start a terminal session.
|
||||||
|
|
||||||
|
* Executable Archive, Manual, Mac OS, versions Sequoia, Tahoe - Intel
|
||||||
|
- `gam-7.wx.yz-macos15.6-x86_64.tar.xz`
|
||||||
|
- Download the archive, extract the contents into some directory.
|
||||||
|
- Start a terminal session.
|
||||||
|
|
||||||
* Executable Archive, Manual, Windows 64 bit
|
* Executable Archive, Manual, Windows 64 bit
|
||||||
- `gam-7.wx.yz-windows-x86_64.zip`
|
- `gam-7.wx.yz-windows-x86_64.zip`
|
||||||
- Download the archive, extract the contents into some directory.
|
- Download the archive, extract the contents into some directory.
|
||||||
|
|||||||
@@ -10,6 +10,51 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
|
|||||||
|
|
||||||
See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
|
See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
|
||||||
|
|
||||||
|
### 7.23.05
|
||||||
|
|
||||||
|
Added option `recursive` to `gam print|show admins` that will display assignments to the members
|
||||||
|
of security groups assigned to roles; the security group membership is recursively expanded.
|
||||||
|
|
||||||
|
### 7.23.04
|
||||||
|
|
||||||
|
Added option `addcsvdata <FieldName> <String>` to `gam <UserTypeEntity> print events`
|
||||||
|
and `gam calendars <CalendarEntity> print events` that adds additional columns of data to the CSV file output.
|
||||||
|
An example would be to get the calendar name in addition to the calendar ID when printing events.
|
||||||
|
```
|
||||||
|
gam redirect csv ./Resources.csv print resources fields email,name
|
||||||
|
gam redirect csv ./ResourceEventCounts.csv multiprocess redirect stderr - multiprocess csv Resources.csv gam calendar "~resourceEmail" print events starttime -1y countsonly addcsvdata calendarName "~resourceName"
|
||||||
|
```
|
||||||
|
|
||||||
|
Upgraded to OpenSSL 3.6.0.
|
||||||
|
|
||||||
|
### 7.23.03
|
||||||
|
|
||||||
|
Upgraded to OpenSSL 3.5.4.
|
||||||
|
|
||||||
|
### 7.23.02
|
||||||
|
|
||||||
|
Added option `oneitemperrow` to 'gam print course-materials|course-work` to have each of a
|
||||||
|
course's materials displayed on a separate row with all of the other course fields.
|
||||||
|
This produces a CSV file that can be used in subsequent commands to process the materials without further script processing.
|
||||||
|
|
||||||
|
### 7.23.00
|
||||||
|
|
||||||
|
Added `chat_max_results` variable to `gam.cfg`.
|
||||||
|
```
|
||||||
|
chat_max_results
|
||||||
|
When retrieving lists of Chat items from API,
|
||||||
|
how many should be retrieved in each API call
|
||||||
|
Default: 100
|
||||||
|
Range: 1 - 1000
|
||||||
|
```
|
||||||
|
Previously, this vaule was always set to 1000 which could cause errors.
|
||||||
|
|
||||||
|
### 7.22.07
|
||||||
|
|
||||||
|
Added options `showdetails` and `returnidonly` to `gam create|copy vaultquery`.
|
||||||
|
|
||||||
|
Added option `<JSONData>` to `gam create vaultexport|vaultquery and `gam print vaultcounts``.
|
||||||
|
|
||||||
### 7.22.06
|
### 7.22.06
|
||||||
|
|
||||||
Added commands to create, copy and delete Vault saved queries.
|
Added commands to create, copy and delete Vault saved queries.
|
||||||
|
|||||||
@@ -252,10 +252,10 @@ writes the credentials into the file oauth2.txt.
|
|||||||
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
|
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
|
||||||
admin@server:/Users/admin$ gam version
|
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
|
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
|
||||||
GAM 7.22.06 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.23.05 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.13.7 64-bit final
|
Python 3.13.7 64-bit final
|
||||||
MacOS Sequoia 15.6.1 x86_64
|
macOS Tahoe 26.0.1 x86_64
|
||||||
Path: /Users/admin/bin/gam7
|
Path: /Users/admin/bin/gam7
|
||||||
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||||
|
|
||||||
|
|||||||
@@ -378,7 +378,7 @@ Select the users for whom information is desired.
|
|||||||
* `showorgunit` - Add a column labelled `orgUnitPath` to the output; an additional API call is made to get the email addresses of the users in `<OrgUnitPath>`
|
* `showorgunit` - Add a column labelled `orgUnitPath` to the output; an additional API call is made to get the email addresses of the users in `<OrgUnitPath>`
|
||||||
* `select <UserTypeEntity>` - A selected collection of users, e.g., `select group staff@domain.com`; there is one API call per user
|
* `select <UserTypeEntity>` - A selected collection of users, e.g., `select group staff@domain.com`; there is one API call per user
|
||||||
|
|
||||||
By default, when `user all` is specified (or no user specification in supplied), GAM backs up looking for data with a (basically) random user. If the randaom
|
By default, when `user all` is specified (or no user specification in supplied), GAM backs up looking for data with a (basically) random user. If the random
|
||||||
doesn't have any data, the command reports that no data was found. Use `allverifyuser <UserItem>` to specify a specific user to use to search for data.
|
doesn't have any data, the command reports that no data was found. Use `allverifyuser <UserItem>` to specify a specific user to use to search for data.
|
||||||
|
|
||||||
Specify the report date; the default is today's date.
|
Specify the report date; the default is today's date.
|
||||||
|
|||||||
@@ -653,7 +653,7 @@ By default, Gam displays the information as an indented list of keys and values.
|
|||||||
```
|
```
|
||||||
gam <UserTypeEntity> show events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
|
gam <UserTypeEntity> show events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
|
||||||
[fields <EventFieldNameList>] [showdayofweek]
|
[fields <EventFieldNameList>] [showdayofweek]
|
||||||
[countsonly] [formatjson]
|
[countsonly|formatjson]
|
||||||
```
|
```
|
||||||
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
|
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
|
||||||
|
|
||||||
@@ -672,8 +672,8 @@ By default, Gam displays event details, use `countsonly` to display only the num
|
|||||||
```
|
```
|
||||||
gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
|
gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
|
||||||
[fields <EventFieldNameList>] [showdayofweek]
|
[fields <EventFieldNameList>] [showdayofweek]
|
||||||
[countsonly]
|
(addcsvdata <FieldName> <String>)*
|
||||||
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
|
[eventrowfilter] [countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
|
||||||
```
|
```
|
||||||
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
|
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
|
||||||
|
|
||||||
@@ -684,6 +684,9 @@ option `singleevents` to display all instances of a recurring event.
|
|||||||
|
|
||||||
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
|
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
|
||||||
|
|
||||||
|
Add additional columns of data from the command line to the output after the calendarId.
|
||||||
|
* `addcsvdata <FieldName> <String>`
|
||||||
|
|
||||||
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
|
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
|
||||||
* `formatjson` - Display the fields in JSON format.
|
* `formatjson` - Display the fields in JSON format.
|
||||||
|
|
||||||
|
|||||||
@@ -398,8 +398,8 @@ By default, Gam displays the information as an indented list of keys and values.
|
|||||||
gam <UserTypeEntity> show contacts
|
gam <UserTypeEntity> show contacts
|
||||||
<PeoplePrintShowUserContactSelection>
|
<PeoplePrintShowUserContactSelection>
|
||||||
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
||||||
[countsonly|allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
|
[allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
|
||||||
[formatjson]
|
[countsonly|formatjson]
|
||||||
```
|
```
|
||||||
By default, Gam displays all of a user's people contacts.
|
By default, Gam displays all of a user's people contacts.
|
||||||
* `query <String>` - Display contacts based on the data in their fields
|
* `query <String>` - Display contacts based on the data in their fields
|
||||||
@@ -416,8 +416,8 @@ By default, Gam displays the information as an indented list of keys and values.
|
|||||||
gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*]
|
||||||
<PeoplePrintShowUserContactSelection>
|
<PeoplePrintShowUserContactSelection>
|
||||||
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
|
||||||
[countsonly|allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
|
[allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
|
||||||
[formatjson [quotechar <Character>]]
|
[countsonly|(formatjson [quotechar <Character>])]
|
||||||
```
|
```
|
||||||
By default, Gam displays all of a user's people contacts.
|
By default, Gam displays all of a user's people contacts.
|
||||||
* `query <String>` - Display contacts based on the data in their fields
|
* `query <String>` - Display contacts based on the data in their fields
|
||||||
@@ -547,8 +547,8 @@ User: user@domain.com, Delete maximum of 15 Other Contacts
|
|||||||
```
|
```
|
||||||
gam <UserTypeEntity> show othercontacts
|
gam <UserTypeEntity> show othercontacts
|
||||||
[<OtherContactsSelection>]
|
[<OtherContactsSelection>]
|
||||||
[countsonly|allfields|(fields <OtherContactsFieldNameList>)] [showmetadata]
|
[allfields|(fields <OtherContactsFieldNameList>)] [showmetadata]
|
||||||
[formatjson]
|
[countsonly|formatjson]
|
||||||
```
|
```
|
||||||
By default, Gam displays all of a user's Other Contacts; use
|
By default, Gam displays all of a user's Other Contacts; use
|
||||||
`<OtherContactsSelection>` to display a selection of Other Contacts.
|
`<OtherContactsSelection>` to display a selection of Other Contacts.
|
||||||
@@ -563,8 +563,8 @@ By default, Gam displays the information as an indented list of keys and values.
|
|||||||
```
|
```
|
||||||
gam <UserTypeEntity> print othercontacts [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print othercontacts [todrive <ToDriveAttribute>*]
|
||||||
[<OtherContactsSelection>]
|
[<OtherContactsSelection>]
|
||||||
[countsonly|allfields|(fields <OtherContactsFieldNameList>)] [showmetadata]
|
[allfields|(fields <OtherContactsFieldNameList>)] [showmetadata]
|
||||||
[formatjson [quotechar <Character>]]
|
[countsonly|(formatjson [quotechar <Character>])]
|
||||||
```
|
```
|
||||||
By default, Gam displays all of a user's Other Contacts; use
|
By default, Gam displays all of a user's Other Contacts; use
|
||||||
`<OtherContactsSelection>` to display a selection of Other Contacts.
|
`<OtherContactsSelection>` to display a selection of Other Contacts.
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ gam <UserTypeEntity> show tasks [tasklists <TasklistEntity>]
|
|||||||
[updatedmin <Time>]
|
[updatedmin <Time>]
|
||||||
[showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
|
[showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
|
||||||
[orderby completed|due|updated]
|
[orderby completed|due|updated]
|
||||||
[countsonly|compact|formatjson]
|
[compact|countsonly|formatjson]
|
||||||
```
|
```
|
||||||
The API only supports dates in `duemin` and `duemax' but you must supply a null time:
|
The API only supports dates in `duemin` and `duemax' but you must supply a null time:
|
||||||
* `duemin YYYY-MM-DDT00:00:00Z` - Specify the starting due date
|
* `duemin YYYY-MM-DDT00:00:00Z` - Specify the starting due date
|
||||||
@@ -152,7 +152,7 @@ gam <UserTypeEntity> print tasks [tasklists <TasklistEntity>] [todrive <ToDriveA
|
|||||||
[updatedmin <Time>]
|
[updatedmin <Time>]
|
||||||
[showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
|
[showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
|
||||||
[orderby completed|due|updated]
|
[orderby completed|due|updated]
|
||||||
[countsonly | (formatjson [quotechar <Character>])]
|
[countsonly|(formatjson [quotechar <Character>])]
|
||||||
```
|
```
|
||||||
The API only supports dates in `duemin` and `duemax' but you must supply a null time:
|
The API only supports dates in `duemin` and `duemax' but you must supply a null time:
|
||||||
* `duemin YYYY-MM-DDT00:00:00Z` - Specify the starting due date
|
* `duemin YYYY-MM-DDT00:00:00Z` - Specify the starting due date
|
||||||
@@ -230,7 +230,7 @@ By default, Gam displays the task lists as an indented list of keys and values.
|
|||||||
|
|
||||||
```
|
```
|
||||||
gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
|
||||||
[countsonly | (formatjson [quotechar <Character>])]
|
[countsonly|(formatjson [quotechar <Character>])]
|
||||||
```
|
```
|
||||||
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
|
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
|
||||||
* `formatjson` - Display the fields in JSON format.
|
* `formatjson` - Display the fields in JSON format.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
- [Query documentation](#query-documentation)
|
- [Query documentation](#query-documentation)
|
||||||
- [Python Regular Expressions](Python-Regular-Expressions) Match function
|
- [Python Regular Expressions](Python-Regular-Expressions) Match function
|
||||||
- [Definitions](#definitions)
|
- [Definitions](#definitions)
|
||||||
|
- [Special quoting](#special-quoting)
|
||||||
- [Vault Matters](#vault-matters)
|
- [Vault Matters](#vault-matters)
|
||||||
- [Create Vault Matters](#create-vault-matters)
|
- [Create Vault Matters](#create-vault-matters)
|
||||||
- [Manage Vault Matters](#manage-vault-matters)
|
- [Manage Vault Matters](#manage-vault-matters)
|
||||||
@@ -57,6 +58,7 @@
|
|||||||
<EmailAddressList> ::= "<EmailAddess>(,<EmailAddress>)*"
|
<EmailAddressList> ::= "<EmailAddess>(,<EmailAddress>)*"
|
||||||
<EmailAddressEntity> ::= <EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
|
<EmailAddressEntity> ::= <EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
|
||||||
See: https://github.com/GAM-team/GAM/wiki/Collections-of-Items
|
See: https://github.com/GAM-team/GAM/wiki/Collections-of-Items
|
||||||
|
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
|
||||||
<TimeZone> ::= <String>
|
<TimeZone> ::= <String>
|
||||||
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||||
<UniqueID> ::= id:<String>
|
<UniqueID> ::= id:<String>
|
||||||
@@ -76,6 +78,7 @@
|
|||||||
<ExportStatusList> ::= "<ExportStatus>(,<ExportStatus>)*"
|
<ExportStatusList> ::= "<ExportStatus>(,<ExportStatus>)*"
|
||||||
<HoldItem> ::= <UniqueID>|<String>
|
<HoldItem> ::= <UniqueID>|<String>
|
||||||
<MatterItem> ::= <UniqueID>|<String>
|
<MatterItem> ::= <UniqueID>|<String>
|
||||||
|
<MatterItemList> ::= "<MatterItem>(,<MatterItem>)*"
|
||||||
<MatterState> ::= open|closed|deleted
|
<MatterState> ::= open|closed|deleted
|
||||||
<MatterStateList> ::= "<MatterState>(,<MatterState>)*"
|
<MatterStateList> ::= "<MatterState>(,<MatterState>)*"
|
||||||
<QueryItem> ::= <UniqueID>|<String>
|
<QueryItem> ::= <UniqueID>|<String>
|
||||||
@@ -141,9 +144,29 @@
|
|||||||
<VaultQueryFieldNameList> ::= "<VaultQueryFieldName>(,<VaultQueryFieldName>)*"
|
<VaultQueryFieldNameList> ::= "<VaultQueryFieldName>(,<VaultQueryFieldName>)*"
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You specify matters, exports and holds by ID (`<UniqueID>`) or name (`<String>`). The API requires an ID, so if you specify a name,
|
You specify matters, exports and holds by ID (`<UniqueID>`) or name (`<String>`). The API requires an ID, so if you specify a name,
|
||||||
GAM has to make additional API calls to convert the name to an ID.
|
GAM has to make additional API calls to convert the name to an ID.
|
||||||
|
|
||||||
|
## Special quoting
|
||||||
|
You specify a single matter with `matter <MatterItem>` and a list of matters with `matters <MatterItemList>`.
|
||||||
|
|
||||||
|
As matter names can contain spaces, some care must be used when entering `<MatterItem>` and `<MatterItemList>` with names.
|
||||||
|
|
||||||
|
Suppose you have a matter `Foo Bar`. To get information about a specific export: `gam info vaultexport "Foo Bar" <ExportItem>`
|
||||||
|
|
||||||
|
The shell strips the `"` leaving a single argument `Foo Bar`; gam correctly processes the argument.
|
||||||
|
|
||||||
|
Suppose you enter the command: `gam show vaultexports matters "Foo Bar"`
|
||||||
|
|
||||||
|
The shell strips the `"` leaving a single argument `Foo Bar`; gam splits the argument on space leaving two items and then tries to process `Foo` and `Bar`, not what you want.
|
||||||
|
|
||||||
|
You must enter: `gam info show vaultexports matters "'Foo Bar'"`
|
||||||
|
|
||||||
|
The shell strips the `"` leaving a single argument `'Foo Bar'`; gam splits the argument on space while honoring the `'` leaving one item `Foo Bar` and correctly processes the item.
|
||||||
|
|
||||||
|
For quoting rules, see: [List Quoting Rules](Command-Line-Parsing)
|
||||||
|
|
||||||
## Vault Matters
|
## Vault Matters
|
||||||
## Create Vault Matters
|
## Create Vault Matters
|
||||||
Create a Google Vault matter.
|
Create a Google Vault matter.
|
||||||
@@ -232,12 +255,13 @@ gam print vaultcounts [todrive <ToDriveAttributes>*]
|
|||||||
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone|entireorg
|
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone|entireorg
|
||||||
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
|
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
|
||||||
[excludedrafts <Boolean>]
|
[excludedrafts <Boolean>]
|
||||||
|
[<JSONData>]
|
||||||
[wait <Integer>]
|
[wait <Integer>]
|
||||||
```
|
```
|
||||||
Specify the search method, this is optional:
|
Specify the search method, this is optional:
|
||||||
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
|
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
|
||||||
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>`
|
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>`
|
||||||
* `everyone` - Search for all accounts in the organization
|
* `everyone|entireorg` - Search for all accounts in the organization
|
||||||
|
|
||||||
For `corpus mail|group`, you can specify search terms to limit the search.
|
For `corpus mail|group`, you can specify search terms to limit the search.
|
||||||
* `terms <String>` - [Vault search](https://support.google.com/vault/answer/2474474)
|
* `terms <String>` - [Vault search](https://support.google.com/vault/answer/2474474)
|
||||||
@@ -246,6 +270,8 @@ For `corpus mail|group`, you can specify time limits on the search:
|
|||||||
* `start|starttime <Date>|<Time>` - The start time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
|
* `start|starttime <Date>|<Time>` - The start time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
|
||||||
* `end|endtime <Date>|<Time>` - The end time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
|
* `end|endtime <Date>|<Time>` - The end time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
|
||||||
|
|
||||||
|
You can specify query options with `<JSONData>`.
|
||||||
|
|
||||||
Check the status of a previous count operation with the name from a previous command.
|
Check the status of a previous count operation with the name from a previous command.
|
||||||
```
|
```
|
||||||
gam print vaultcounts [todrive <ToDriveAttributes>*]
|
gam print vaultcounts [todrive <ToDriveAttributes>*]
|
||||||
@@ -283,6 +309,7 @@ gam create vaultexport|export matter <MatterItem> [name <String>]
|
|||||||
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
|
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
|
||||||
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
|
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
|
||||||
(covereddata calllogs|textmessages|voicemails)*
|
(covereddata calllogs|textmessages|voicemails)*
|
||||||
|
[<JSONData>]
|
||||||
[driveclientsideencryption any|encrypted|unencrypted]
|
[driveclientsideencryption any|encrypted|unencrypted]
|
||||||
[includeaccessinfo <Boolean>]
|
[includeaccessinfo <Boolean>]
|
||||||
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
|
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
|
||||||
@@ -308,7 +335,7 @@ Specify the corpus of data, this option is required:
|
|||||||
Specify the search method, this option is required:
|
Specify the search method, this option is required:
|
||||||
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
|
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
|
||||||
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>`
|
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>`
|
||||||
* `everyone` - Search for all accounts in the organization
|
* `everyone|entireorg` - Search for all accounts in the organization
|
||||||
* `documentids <DriveFileIDList>` - Search for all drive files specified in `<DriveFileIDList>`
|
* `documentids <DriveFileIDList>` - Search for all drive files specified in `<DriveFileIDList>`
|
||||||
* `documentids select <FileSelector>|<CSVFileSelector>` - Search for all drive files specified in `<FileSelector>|<CSVFileSelector>`
|
* `documentids select <FileSelector>|<CSVFileSelector>` - Search for all drive files specified in `<FileSelector>|<CSVFileSelector>`
|
||||||
* `shareddrives|teamdrives <SharedDriveIDList>` - Search for all accounts in the Shared Drives specified in `<SharedDriveIDList>`
|
* `shareddrives|teamdrives <SharedDriveIDList>` - Search for all accounts in the Shared Drives specified in `<SharedDriveIDList>`
|
||||||
@@ -349,10 +376,6 @@ For `corpus calendar`, you can specify advanced search options:
|
|||||||
* Search the current version of the Calendar event, but export the contents of the last version saved before 12:00 AM UTC on the specified date.
|
* Search the current version of the Calendar event, but export the contents of the last version saved before 12:00 AM UTC on the specified date.
|
||||||
* Enter the date in UTC.
|
* Enter the date in UTC.
|
||||||
|
|
||||||
For `corpus calendar`, you can specify the format of the exported data:
|
|
||||||
* `format ics` - Export in ICS format, this is the default
|
|
||||||
* `format pst` - Export in PST format
|
|
||||||
|
|
||||||
For `corpus drive`, you can specify advanced search options:
|
For `corpus drive`, you can specify advanced search options:
|
||||||
* `driveversiondate <Date>|<Time>` - Search the versions of the Drive file as of the reference date. These timestamps are in GMT and rounded down to the given date.
|
* `driveversiondate <Date>|<Time>` - Search the versions of the Drive file as of the reference date. These timestamps are in GMT and rounded down to the given date.
|
||||||
* `includeshareddrives False` - Mapped to `sharedrivesoption included_if_account_is_not_a_member`
|
* `includeshareddrives False` - Mapped to `sharedrivesoption included_if_account_is_not_a_member`
|
||||||
@@ -360,6 +383,16 @@ For `corpus drive`, you can specify advanced search options:
|
|||||||
* `sharedrivesoption included` - Resources in shared drives are included in the search
|
* `sharedrivesoption included` - Resources in shared drives are included in the search
|
||||||
* `sharedrivesoption included_if_account_is_not_a_member` - Resources in shared drives where account is not a member are included in the search, this is the default
|
* `sharedrivesoption included_if_account_is_not_a_member` - Resources in shared drives where account is not a member are included in the search, this is the default
|
||||||
* `sharedrivesoption not_included` - Resources in shared drives are not included in the search
|
* `sharedrivesoption not_included` - Resources in shared drives are not included in the search
|
||||||
|
|
||||||
|
For `corpus hangouts_chat` you can specify advanced search options:
|
||||||
|
* `includerooms False` - Do not include rooms, this is the default
|
||||||
|
* `includerooms True` - Include rooms
|
||||||
|
|
||||||
|
You can specify query options with `<JSONData>`.
|
||||||
|
|
||||||
|
## Vault Export options
|
||||||
|
|
||||||
|
For `corpus drive`, you can specify advanced search options:
|
||||||
* `driveclientsideencryption any` - Include both client-side encrypted and unencrypted content in search, this is the default.
|
* `driveclientsideencryption any` - Include both client-side encrypted and unencrypted content in search, this is the default.
|
||||||
* `driveclientsideencryption encrypted` - Include client-side encrypted content only in search.
|
* `driveclientsideencryption encrypted` - Include client-side encrypted content only in search.
|
||||||
* `driveclientsideencryption unencrypted` - Include client-side unencrypted content only in search.
|
* `driveclientsideencryption unencrypted` - Include client-side unencrypted content only in search.
|
||||||
@@ -368,10 +401,6 @@ For `corpus drive`, you can specify whether to include access information for us
|
|||||||
* `includeaccessinfo False` - Do not include access information for users with indirect access, this is the default
|
* `includeaccessinfo False` - Do not include access information for users with indirect access, this is the default
|
||||||
* `includeaccessinfo True` - Include access information for users with indirect access
|
* `includeaccessinfo True` - Include access information for users with indirect access
|
||||||
|
|
||||||
For `corpus hangouts_chat` you can specify advanced search options:
|
|
||||||
* `includerooms False` - Do not include rooms, this is the default
|
|
||||||
* `includerooms True` - Include rooms
|
|
||||||
|
|
||||||
For `corpus mail`, you can specify advanced search options:
|
For `corpus mail`, you can specify advanced search options:
|
||||||
* `excludedrafts False` - Do not exclude drafts, this is the default
|
* `excludedrafts False` - Do not exclude drafts, this is the default
|
||||||
* `excludedrafts True` - Exclude drafts
|
* `excludedrafts True` - Exclude drafts
|
||||||
@@ -405,8 +434,7 @@ For `corpus groups`, `corpus hangouts_chat`, `corpus mail` and `corpus voice`, y
|
|||||||
* `format mbox` - Export in MBOX format, this is the default
|
* `format mbox` - Export in MBOX format, this is the default
|
||||||
* `format pst` - Export in PST format
|
* `format pst` - Export in PST format
|
||||||
|
|
||||||
For `corpus voice` you can specify the data covered by the export,
|
For `corpus voice` you can specify the data covered by the export, multiple values are allowed.:
|
||||||
multiple values are allowed.:
|
|
||||||
* `covereddata calllogs` - Call logs
|
* `covereddata calllogs` - Call logs
|
||||||
* `covereddata textmessages` - Voice text messages
|
* `covereddata textmessages` - Voice text messages
|
||||||
* `covereddata voicemail` - Voicemail
|
* `covereddata voicemail` - Voicemail
|
||||||
@@ -817,8 +845,10 @@ gam create vaultquery <MatterItem> [name <String>]
|
|||||||
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
|
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
|
||||||
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
|
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
|
||||||
(covereddata calllogs|textmessages|voicemails)*
|
(covereddata calllogs|textmessages|voicemails)*
|
||||||
[shownames] [formatjson]
|
[<JSONData>]
|
||||||
```
|
[shownames]
|
||||||
|
[showdetails|returnidonly|formatjson]
|
||||||
|
``
|
||||||
|
|
||||||
If `name <String>` is omitted, the query is named `GAM <corpus> Query - <Time>`
|
If `name <String>` is omitted, the query is named `GAM <corpus> Query - <Time>`
|
||||||
|
|
||||||
@@ -826,10 +856,17 @@ The `shownames` argument controls whether org unit and shared drive names are di
|
|||||||
|
|
||||||
See: [Vault Query options](#vault-query-options)
|
See: [Vault Query options](#vault-query-options)
|
||||||
|
|
||||||
|
Use the `showdetails` option to have the full details of the saved query displayed.
|
||||||
|
|
||||||
|
Use the `returnidonly` option to have only the saved query ID displayed.
|
||||||
|
|
||||||
|
Use the `formatjson` option to have only the saved query JSON displayed.
|
||||||
|
|
||||||
## Copy Vault Saved Queries
|
## Copy Vault Saved Queries
|
||||||
```
|
```
|
||||||
gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem>] [name <String>]
|
gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem>] [name <String>]
|
||||||
[shownames] [formatjson]
|
[shownames]
|
||||||
|
[showdetails|returnidonly|formatjson]
|
||||||
```
|
```
|
||||||
|
|
||||||
If `targetmatter <MatterItem>` is omitted, the query is copied in the source matter.
|
If `targetmatter <MatterItem>` is omitted, the query is copied in the source matter.
|
||||||
@@ -840,6 +877,12 @@ If `name <String>` is omitted:
|
|||||||
|
|
||||||
The `shownames` argument controls whether org unit and shared drive names are displayed in queries; additional API calls are required to get the names.
|
The `shownames` argument controls whether org unit and shared drive names are displayed in queries; additional API calls are required to get the names.
|
||||||
|
|
||||||
|
Use the `showdetails` option to have the full details of the saved query displayed.
|
||||||
|
|
||||||
|
Use the `returnidonly` option to have only the saved query ID displayed.
|
||||||
|
|
||||||
|
Use the `formatjson` option to have only the saved query JSON displayed.
|
||||||
|
|
||||||
## Delete Vault Saved Queries
|
## Delete Vault Saved Queries
|
||||||
```
|
```
|
||||||
gam delete vaultquery <QueryItem> matter <MatterItem>
|
gam delete vaultquery <QueryItem> matter <MatterItem>
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
Print the current version of Gam with details
|
Print the current version of Gam with details
|
||||||
```
|
```
|
||||||
gam version
|
gam version
|
||||||
GAM 7.22.06 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.23.05 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.13.7 64-bit final
|
Python 3.13.7 64-bit final
|
||||||
macOS Sequoia 15.7 x86_64
|
macOS Tahoe 26.0.1 x86_64
|
||||||
Path: /Users/Admin/bin/gam7
|
Path: /Users/Admin/bin/gam7
|
||||||
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||||
Time: 2023-06-02T21:10:00-07:00
|
Time: 2023-06-02T21:10:00-07:00
|
||||||
@@ -15,10 +15,10 @@ Time: 2023-06-02T21:10:00-07:00
|
|||||||
Print the current version of Gam with details and time offset information
|
Print the current version of Gam with details and time offset information
|
||||||
```
|
```
|
||||||
gam version timeoffset
|
gam version timeoffset
|
||||||
GAM 7.22.06 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.23.05 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.13.7 64-bit final
|
Python 3.13.7 64-bit final
|
||||||
macOS Sequoia 15.7 x86_64
|
macOS Tahoe 26.0.1 x86_64
|
||||||
Path: /Users/Admin/bin/gam7
|
Path: /Users/Admin/bin/gam7
|
||||||
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||||
Your system time differs from www.googleapis.com by less than 1 second
|
Your system time differs from www.googleapis.com by less than 1 second
|
||||||
@@ -27,10 +27,10 @@ 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
|
Print the current version of Gam with extended details and SSL information
|
||||||
```
|
```
|
||||||
gam version extended
|
gam version extended
|
||||||
GAM 7.22.06 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.23.05 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.13.7 64-bit final
|
Python 3.13.7 64-bit final
|
||||||
macOS Sequoia 15.7 x86_64
|
macOS Tahoe 26.0.1 x86_64
|
||||||
Path: /Users/Admin/bin/gam7
|
Path: /Users/Admin/bin/gam7
|
||||||
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||||
Time: 2023-06-02T21:10:00-07:00
|
Time: 2023-06-02T21:10:00-07:00
|
||||||
@@ -89,7 +89,7 @@ gam help
|
|||||||
GAM 7.22.00 - https://github.com/GAM-team/GAM
|
GAM 7.22.00 - https://github.com/GAM-team/GAM
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.13.7 64-bit final
|
Python 3.13.7 64-bit final
|
||||||
macOS Sequoia 15.7 x86_64
|
macOS Tahoe 26.0.1 x86_64
|
||||||
Path: /Users/Admin/bin/gam7
|
Path: /Users/Admin/bin/gam7
|
||||||
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||||
Time: 2023-06-02T21:10:00-07:00
|
Time: 2023-06-02T21:10:00-07:00
|
||||||
|
|||||||
@@ -109,6 +109,11 @@ charset
|
|||||||
Character set of gam batch, gam csv, gam loop files.
|
Character set of gam batch, gam csv, gam loop files.
|
||||||
Default: utf-8
|
Default: utf-8
|
||||||
Environment variable: GAM_CHARSET
|
Environment variable: GAM_CHARSET
|
||||||
|
chat_max_results
|
||||||
|
When retrieving lists of Chat items from API,
|
||||||
|
how many should be retrieved in each API call
|
||||||
|
Default: 100
|
||||||
|
Range: 1 - 1000
|
||||||
classroom_max_results
|
classroom_max_results
|
||||||
When retrieving lists of Google Classroom items from API,
|
When retrieving lists of Google Classroom items from API,
|
||||||
how many should be retrieved in each API call
|
how many should be retrieved in each API call
|
||||||
|
|||||||
Reference in New Issue
Block a user