mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-28 09:51:36 +00:00
Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84175ba80d | ||
|
|
56c2b77f25 | ||
|
|
dfe01e5272 | ||
|
|
e25c302616 | ||
|
|
1ca5b1a610 | ||
|
|
b9c81e2e24 | ||
|
|
9766fa42e7 | ||
|
|
7bd150e5bf | ||
|
|
063e0876b9 | ||
|
|
4743d12ea8 | ||
|
|
ad548cbe33 | ||
|
|
bb9d5b3cdc | ||
|
|
ee3bb42d19 | ||
|
|
7e8042a2f8 | ||
|
|
5ed0b9ffd2 | ||
|
|
db2a37f358 | ||
|
|
77ebeddaac | ||
|
|
f00e7ecdbb | ||
|
|
f75d7d78f6 | ||
|
|
75929117aa | ||
|
|
a06348c1c5 | ||
|
|
425286482f | ||
|
|
a162cf870b | ||
|
|
28a1048f57 | ||
|
|
def54f1513 | ||
|
|
4d86d44ec1 | ||
|
|
2c0136834b | ||
|
|
9cca97b12e | ||
|
|
f69d0b1427 | ||
|
|
abd39176d8 | ||
|
|
782eee45cc | ||
|
|
6450fb0c3d | ||
|
|
523bd45fa0 | ||
|
|
9e6122769a | ||
|
|
9dc427c47b | ||
|
|
023c81de93 | ||
|
|
a570e1f300 | ||
|
|
86881b58f4 | ||
|
|
1b8793df9b | ||
|
|
dfdc03ba28 | ||
|
|
0cafde359e | ||
|
|
9b2ca0dedd | ||
|
|
741a2e3b79 | ||
|
|
760963889d | ||
|
|
b0b572a5b2 | ||
|
|
ae9e329169 | ||
|
|
d997900955 | ||
|
|
699d95d7d7 |
90
.github/workflows/build.yml
vendored
90
.github/workflows/build.yml
vendored
@@ -165,7 +165,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
cache.tar.xz
|
cache.tar.xz
|
||||||
key: gam-${{ matrix.jid }}-20260416
|
key: gam-${{ matrix.jid }}-20260508
|
||||||
|
|
||||||
- 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'
|
||||||
@@ -200,6 +200,9 @@ jobs:
|
|||||||
echo "arch=${RUNNER_ARCH}" >> $GITHUB_ENV
|
echo "arch=${RUNNER_ARCH}" >> $GITHUB_ENV
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
# calculate with python because date on MacOS is just stupid
|
||||||
|
DEPS_CUTOFF=$(python3 -c "from datetime import datetime, timedelta, timezone; print((datetime.now(timezone.utc) - timedelta(days=14)).strftime('%Y-%m-%dT00:00:00Z'))")
|
||||||
|
echo "DEPS_CUTOFF=${DEPS_CUTOFF}" >> $GITHUB_ENV
|
||||||
echo "JID=${JID}" >> $GITHUB_ENV
|
echo "JID=${JID}" >> $GITHUB_ENV
|
||||||
echo "freethreaded=${freethreaded}" >> $GITHUB_ENV
|
echo "freethreaded=${freethreaded}" >> $GITHUB_ENV
|
||||||
if "$freethreaded"; then
|
if "$freethreaded"; then
|
||||||
@@ -506,19 +509,19 @@ jobs:
|
|||||||
"${PYTHON}" -VV
|
"${PYTHON}" -VV
|
||||||
"${PYTHON}" -c "import ssl; print(f'Using {ssl.OPENSSL_VERSION}')"
|
"${PYTHON}" -c "import ssl; print(f'Using {ssl.OPENSSL_VERSION}')"
|
||||||
|
|
||||||
- name: Create and use Python venv
|
- name: Create and use Python .venv
|
||||||
run: |
|
run: |
|
||||||
cd "$GITHUB_WORKSPACE"
|
cd "$GITHUB_WORKSPACE"
|
||||||
curl -o get-pip.py https://bootstrap.pypa.io/get-pip.py
|
curl -o get-pip.py https://bootstrap.pypa.io/get-pip.py
|
||||||
"$PYTHON" get-pip.py
|
"$PYTHON" get-pip.py
|
||||||
"$PYTHON" -m venv venv
|
"$PYTHON" -m venv .venv
|
||||||
if [[ "$RUNNER_OS" == "Windows" ]]; then
|
if [[ "$RUNNER_OS" == "Windows" ]]; then
|
||||||
# pyscard seems to build outside venv but not in it.
|
# pyscard seems to build outside venv but not in it.
|
||||||
# build it so it's cached.
|
# build it so it's cached.
|
||||||
"$PYTHON" -m pip install --upgrade --force-reinstall pyscard
|
"$PYTHON" -m pip install --upgrade pyscard
|
||||||
export PYTHON="${GITHUB_WORKSPACE}/venv/scripts/python.exe"
|
export PYTHON="${GITHUB_WORKSPACE}/.venv/scripts/python.exe"
|
||||||
else
|
else
|
||||||
export PYTHON="${GITHUB_WORKSPACE}/venv/bin/python3"
|
export PYTHON="${GITHUB_WORKSPACE}/.venv/bin/python3"
|
||||||
fi
|
fi
|
||||||
echo "PYTHON=${PYTHON}" >> $GITHUB_ENV
|
echo "PYTHON=${PYTHON}" >> $GITHUB_ENV
|
||||||
if [[ "$ACTIONS_GOAL" == "test" ]]; then
|
if [[ "$ACTIONS_GOAL" == "test" ]]; then
|
||||||
@@ -526,31 +529,22 @@ jobs:
|
|||||||
echo "gam=${gam}" >> $GITHUB_ENV
|
echo "gam=${gam}" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Upgrade pip, wheel, etc
|
#- name: Upgrade pip, wheel, etc
|
||||||
run: |
|
# run: |
|
||||||
curl $curl_retry -O https://bootstrap.pypa.io/get-pip.py
|
# curl $curl_retry -O https://bootstrap.pypa.io/get-pip.py
|
||||||
"$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 --upgrade 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 install --upgrade packaging
|
# "$PYTHON" -m pip install --upgrade packaging
|
||||||
"$PYTHON" -m pip list
|
# "$PYTHON" -m pip list
|
||||||
|
|
||||||
- name: Install pip requirements
|
- name: Install pip requirements
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
echo "before anything..."
|
|
||||||
"$PYTHON" -m pip list
|
|
||||||
echo "--info--"
|
|
||||||
"$PYTHON" -m pip cache info
|
|
||||||
echo "--list--"
|
|
||||||
"$PYTHON" -m pip cache list
|
|
||||||
echo "--pip debug verbose--"
|
|
||||||
"$PYTHON" -m pip debug --verbose
|
|
||||||
echo "--------"
|
|
||||||
if ([ "$RUNNER_OS" == "Windows" ] && [ "$RUNNER_ARCH" == "ARM64" ]); then
|
if ([ "$RUNNER_OS" == "Windows" ] && [ "$RUNNER_ARCH" == "ARM64" ]); then
|
||||||
# custom cryptography wheel for win arm64 since the project doesn't provide one:
|
# custom cryptography wheel for win arm64 since the project doesn't provide one:
|
||||||
# https://github.com/pyca/cryptography/issues/14293
|
# https://github.com/pyca/cryptography/issues/14293
|
||||||
@@ -558,24 +552,12 @@ jobs:
|
|||||||
"$PYTHON" -m pip install cryptography-*.whl
|
"$PYTHON" -m pip install cryptography-*.whl
|
||||||
fi
|
fi
|
||||||
"$PYTHON" -m pip install -vvv --upgrade ..[yubikey]
|
"$PYTHON" -m pip install -vvv --upgrade ..[yubikey]
|
||||||
echo "after everything..."
|
|
||||||
"$PYTHON" -m pip list
|
|
||||||
|
|
||||||
- name: Install PyInstaller
|
- name: Install PyInstaller
|
||||||
if: matrix.goal == 'build'
|
if: matrix.goal == 'build'
|
||||||
run: |
|
run: |
|
||||||
#git clone https://github.com/pyinstaller/pyinstaller.git
|
# Install latest version of PyInstaller *that's 2 weeks old*
|
||||||
#cd pyinstaller
|
# Calculate the exact timestamp for 14 days ago
|
||||||
#export latest_release=$(git tag --list | grep -v dev | grep -v rc | sort -Vr | head -n1)
|
|
||||||
#git checkout "${latest_release}"
|
|
||||||
# git checkout "v6.9.0"
|
|
||||||
# remove pre-compiled bootloaders so we fail if bootloader compile fails
|
|
||||||
#rm -rvf PyInstaller/bootloader/*-*/*
|
|
||||||
#cd bootloader
|
|
||||||
#"${PYTHON}" ./waf all
|
|
||||||
#cd ..
|
|
||||||
#echo "---- Installing PyInstaller ----"
|
|
||||||
#"${PYTHON}" -m pip install .
|
|
||||||
"$PYTHON" -m pip install --upgrade pyinstaller
|
"$PYTHON" -m pip install --upgrade pyinstaller
|
||||||
|
|
||||||
- name: Build GAM with PyInstaller
|
- name: Build GAM with PyInstaller
|
||||||
@@ -642,11 +624,9 @@ jobs:
|
|||||||
sudo apt-get -qq --yes update
|
sudo apt-get -qq --yes update
|
||||||
# arm64 needs to build a wheel and needs scons to build
|
# arm64 needs to build a wheel and needs scons to build
|
||||||
sudo apt-get -qq --yes install scons
|
sudo apt-get -qq --yes install scons
|
||||||
"${PYTHON}" -m pip install --upgrade patchelf-wrapper
|
"$PYTHON" -m pip install --upgrade patchelf-wrapper
|
||||||
"${PYTHON}" -m pip install --upgrade typing_extensions
|
"$PYTHON" -m pip install --upgrade typing_extensions
|
||||||
# "${PYTHON}" -m pip install --upgrade staticx
|
"$PYTHON" -m pip install --upgrade staticx
|
||||||
# install latest github src for staticx
|
|
||||||
"${PYTHON}" -m pip install --upgrade "git+https://github.com/JonathonReinhart/staticx"
|
|
||||||
|
|
||||||
- name: Make StaticX GAM build
|
- name: Make StaticX GAM build
|
||||||
if: matrix.staticx == 'yes'
|
if: matrix.staticx == 'yes'
|
||||||
@@ -733,16 +713,16 @@ jobs:
|
|||||||
write-host "sleeping during login..."
|
write-host "sleeping during login..."
|
||||||
Start-Sleep 10
|
Start-Sleep 10
|
||||||
|
|
||||||
# - name: Archive artifacts
|
- name: Archive artifacts
|
||||||
# uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0
|
||||||
# if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
# with:
|
with:
|
||||||
# archive: true
|
archive: true
|
||||||
# name: images-${{ matrix.os }}
|
name: images-${{ matrix.os }}
|
||||||
# if-no-files-found: ignore
|
if-no-files-found: ignore
|
||||||
# path: |
|
path: |
|
||||||
# ${{ github.workspace }}/*.png
|
${{ github.workspace }}/*.png
|
||||||
# ${{ github.workspace }}/*.log
|
${{ github.workspace }}/*.log
|
||||||
|
|
||||||
- name: Sign gam.exe
|
- name: Sign gam.exe
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
|
|||||||
144
.github/workflows/upgrade_deps.yml
vendored
Normal file
144
.github/workflows/upgrade_deps.yml
vendored
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
name: Daily Dependency Pinning (2-Week Buffer)
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# Runs every day at midnight UTC
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
workflow_dispatch: # Allows you to trigger it manually from the UI
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pin-deps:
|
||||||
|
runs-on: ubuntu-slim
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
|
||||||
|
with:
|
||||||
|
python-version: '3.14'
|
||||||
|
|
||||||
|
- name: Calculate and pin two-week old stable versions
|
||||||
|
shell: python
|
||||||
|
run: |
|
||||||
|
import json
|
||||||
|
import urllib.request
|
||||||
|
import re
|
||||||
|
import tomllib
|
||||||
|
from datetime import datetime, timedelta, timezone
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
toml_path = Path("pyproject.toml")
|
||||||
|
if not toml_path.exists():
|
||||||
|
print("pyproject.toml not found!")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
content = toml_path.read_text(encoding="utf-8")
|
||||||
|
parsed_toml = tomllib.loads(content)
|
||||||
|
|
||||||
|
target_deps = set()
|
||||||
|
|
||||||
|
# Standard [project.dependencies]
|
||||||
|
target_deps.update(parsed_toml.get("project", {}).get("dependencies", []))
|
||||||
|
|
||||||
|
# Optional [project.optional-dependencies]
|
||||||
|
for deps in parsed_toml.get("project", {}).get("optional-dependencies", {}).values():
|
||||||
|
target_deps.update(deps)
|
||||||
|
|
||||||
|
# Dev [dependency-groups] (uv / PEP 735 standard)
|
||||||
|
for deps in parsed_toml.get("dependency-groups", {}).values():
|
||||||
|
if isinstance(deps, list):
|
||||||
|
for d in deps:
|
||||||
|
if isinstance(d, str):
|
||||||
|
target_deps.add(d)
|
||||||
|
|
||||||
|
if not target_deps:
|
||||||
|
print("No dependencies found to process.")
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
updates = {}
|
||||||
|
two_weeks_ago = datetime.now(timezone.utc) - timedelta(days=14)
|
||||||
|
print(f"Evaluating dependencies against cutoff date: {two_weeks_ago.isoformat()}")
|
||||||
|
|
||||||
|
for dep in target_deps:
|
||||||
|
# Isolate base package name (e.g., "yubikey-manager>=5.6.1" -> "yubikey-manager")
|
||||||
|
pkg_name = re.split(r'[<>=!~;\s]', dep)[0].strip()
|
||||||
|
|
||||||
|
# Preserve environment markers if they exist
|
||||||
|
marker = ""
|
||||||
|
if ";" in dep:
|
||||||
|
marker = " ; " + dep.split(";", 1)[1].strip()
|
||||||
|
|
||||||
|
print(f"Fetching PyPI data for: {pkg_name}")
|
||||||
|
try:
|
||||||
|
url = f"https://pypi.org/pypi/{pkg_name}/json"
|
||||||
|
req = urllib.request.Request(url, headers={'User-Agent': 'GAM-CI-Script'})
|
||||||
|
with urllib.request.urlopen(req) as response:
|
||||||
|
data = json.loads(response.read().decode())
|
||||||
|
|
||||||
|
valid_versions = []
|
||||||
|
for ver, files in data.get("releases", {}).items():
|
||||||
|
if not files:
|
||||||
|
continue
|
||||||
|
|
||||||
|
upload_time_str = files[0].get("upload_time_iso_8601")
|
||||||
|
if not upload_time_str:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if upload_time_str.endswith('Z'):
|
||||||
|
upload_time_str = upload_time_str[:-1] + '+00:00'
|
||||||
|
|
||||||
|
upload_time = datetime.fromisoformat(upload_time_str)
|
||||||
|
|
||||||
|
# Filter: Must be older than 2 weeks and not a pre-release
|
||||||
|
if upload_time <= two_weeks_ago and not any(x in ver.lower() for x in ['a', 'b', 'rc', 'dev']):
|
||||||
|
valid_versions.append((upload_time, ver))
|
||||||
|
|
||||||
|
if valid_versions:
|
||||||
|
# Sort by upload time descending to get the newest valid option
|
||||||
|
valid_versions.sort(key=lambda x: x[0], reverse=True)
|
||||||
|
target_version = valid_versions[0][1]
|
||||||
|
|
||||||
|
pinned_dep = f"{pkg_name}=={target_version}{marker}"
|
||||||
|
if pinned_dep != dep:
|
||||||
|
updates[dep] = pinned_dep
|
||||||
|
print(f" -> Pinning: '{dep}' => '{pinned_dep}'")
|
||||||
|
else:
|
||||||
|
print(f" -> Already pinned correctly to {target_version}")
|
||||||
|
else:
|
||||||
|
print(f" -> No valid historical versions found.")
|
||||||
|
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
print(f" -> Package not found on PyPI or HTTP error: {e}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" -> Error processing {pkg_name}: {e}")
|
||||||
|
|
||||||
|
# 3. Replace the strings safely in the original file content
|
||||||
|
new_content = content
|
||||||
|
for old_dep, new_dep in updates.items():
|
||||||
|
# Regex targets the exact string inside either single or double quotes
|
||||||
|
# Using a lambda replacement ensures we don't trip over escape sequences in the new string
|
||||||
|
escaped_old = re.escape(old_dep)
|
||||||
|
pattern = r'([\'"])' + escaped_old + r'\1'
|
||||||
|
new_content = re.sub(pattern, lambda m: m.group(1) + new_dep + m.group(1), new_content)
|
||||||
|
|
||||||
|
# Write changes back to pyproject.toml
|
||||||
|
if content != new_content:
|
||||||
|
toml_path.write_text(new_content, encoding="utf-8")
|
||||||
|
print("\npyproject.toml updated successfully.")
|
||||||
|
else:
|
||||||
|
print("\nNo updates required.")
|
||||||
|
|
||||||
|
- name: Create Pull Request
|
||||||
|
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
commit-message: "chore: upgrade PyPi deps"
|
||||||
|
title: "Upgrade PyPi deps"
|
||||||
|
body: "Automated scan checking PyPI for package versions at least 2 weeks old."
|
||||||
|
branch: sys-deps-upgrade
|
||||||
|
force: false # Standard push, plays nice with rulesets
|
||||||
6
dep-overrides.txt
Normal file
6
dep-overrides.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# overrides uv.lock to force newer dependencies
|
||||||
|
# when old deps are vulnerable. These should be set
|
||||||
|
# to expire after 2 weeks when the fixed version will
|
||||||
|
# be automatically picked up anyway.
|
||||||
|
# Format: package_requirement | MM/DD/YYYY
|
||||||
|
urllib3>=2.7.0 | 05/22/2026
|
||||||
@@ -4,26 +4,24 @@ dynamic = [
|
|||||||
"version",
|
"version",
|
||||||
]
|
]
|
||||||
authors = [
|
authors = [
|
||||||
{ name="Jay Lee", email="jay0lee@gmail.com" },
|
{ name = "Jay Lee", email = "jay0lee@gmail.com" },
|
||||||
{ name="Ross Scroggs", email="Ross.Scroggs@gmail.com" },
|
{ name = "Ross Scroggs", email = "Ross.Scroggs@gmail.com" },
|
||||||
]
|
]
|
||||||
# notice that yubikey-manager remains optional further down since it is less command and adds
|
|
||||||
#significant compile dependencies.
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow>=1.3.0",
|
"arrow==1.4.0",
|
||||||
"chardet==5.2.0",
|
"chardet==7.4.3",
|
||||||
"cryptography>=46.0.5",
|
"cryptography==47.0.0",
|
||||||
"distro; sys_platform=='linux'",
|
"distro==1.9.0 ; sys_platform=='linux'",
|
||||||
"filelock>=3.18.0",
|
"filelock==3.29.0",
|
||||||
"google-api-python-client>=2.167.0",
|
"google-api-python-client==2.195.0",
|
||||||
"google-auth-httplib2>=0.2.0",
|
"google-auth-httplib2==0.3.1",
|
||||||
"google-auth-oauthlib>=1.2.2",
|
"google-auth-oauthlib==1.3.1",
|
||||||
"google-auth>=2.39.0",
|
"google-auth==2.50.0",
|
||||||
"httplib2>=0.31.0",
|
"httplib2==0.31.2",
|
||||||
"lxml>=5.4.0",
|
"lxml==6.1.0",
|
||||||
"passlib>=1.7.4",
|
"passlib==1.7.4",
|
||||||
"pathvalidate>=3.2.3",
|
"pathvalidate==3.3.1",
|
||||||
"pysocks>=1.7.1",
|
"pysocks==1.7.1",
|
||||||
]
|
]
|
||||||
description = "CLI tool to manage Google Workspace"
|
description = "CLI tool to manage Google Workspace"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@@ -38,11 +36,17 @@ classifiers = [
|
|||||||
"Programming Language :: Python :: 3.14",
|
"Programming Language :: Python :: 3.14",
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
]
|
]
|
||||||
license = {text = "Apache License (2.0)"}
|
license-files = [
|
||||||
license-files = ["LICEN[CS]E*"]
|
"LICEN[CS]E*",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.license]
|
||||||
|
text = "Apache License (2.0)"
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
yubikey = ["yubikey-manager>=5.6.1"]
|
yubikey = [
|
||||||
|
"yubikey-manager==5.9.1",
|
||||||
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
gam = "gam.__main__:main"
|
gam = "gam.__main__:main"
|
||||||
@@ -57,7 +61,9 @@ Chat = "https://git.io/gam-chat"
|
|||||||
path = "src/gam/__init__.py"
|
path = "src/gam/__init__.py"
|
||||||
|
|
||||||
[tool.hatch.build.targets.wheel]
|
[tool.hatch.build.targets.wheel]
|
||||||
packages = ["src/gam"]
|
packages = [
|
||||||
|
"src/gam",
|
||||||
|
]
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = [
|
requires = [
|
||||||
|
|||||||
@@ -560,9 +560,9 @@ If an item contains spaces, it should be surrounded by ".
|
|||||||
See: https://cloud.google.com/access-context-manager/docs/custom-access-level-spec
|
See: https://cloud.google.com/access-context-manager/docs/custom-access-level-spec
|
||||||
<QueryContact> ::= <String>
|
<QueryContact> ::= <String>
|
||||||
See: https://developers.google.com/google-apps/contacts/v3/reference#contacts-query-parameters-reference
|
See: https://developers.google.com/google-apps/contacts/v3/reference#contacts-query-parameters-reference
|
||||||
<QueryCrOS> ::= <String>
|
<QueryCrOS> ::= <String>:<String>
|
||||||
See: https://support.google.com/chrome/a/answer/1698333
|
See: https://support.google.com/chrome/a/answer/1698333
|
||||||
<QueryDevice> ::= <String>
|
<QueryDevice> ::= <String>:<String>
|
||||||
See: https://support.google.com/a/answer/7549103
|
See: https://support.google.com/a/answer/7549103
|
||||||
<QueryDriveFile> ::= <String>
|
<QueryDriveFile> ::= <String>
|
||||||
See: https://developers.google.com/drive/api/v3/search-files
|
See: https://developers.google.com/drive/api/v3/search-files
|
||||||
@@ -575,7 +575,7 @@ If an item contains spaces, it should be surrounded by ".
|
|||||||
<QueryItem> ::= <UniqueID>|<String>
|
<QueryItem> ::= <UniqueID>|<String>
|
||||||
<QueryMemberRestrictions> ::= <String>
|
<QueryMemberRestrictions> ::= <String>
|
||||||
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
|
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
|
||||||
<QueryMobile> ::= <String>
|
<QueryMobile> ::= <String>:<String>
|
||||||
See: https://support.google.com/a/answer/7549103
|
See: https://support.google.com/a/answer/7549103
|
||||||
<QueryTeamDrive> ::= <String>
|
<QueryTeamDrive> ::= <String>
|
||||||
See: https://developers.google.com/drive/api/v3/search-parameters
|
See: https://developers.google.com/drive/api/v3/search-parameters
|
||||||
@@ -1720,6 +1720,7 @@ gam calendar <CalendarEntity> printacl [todrive <ToDriveAttribute>*]
|
|||||||
|
|
||||||
<EventMatchProperty> ::=
|
<EventMatchProperty> ::=
|
||||||
(matchfield attendees <EmailAddressEntity>)|
|
(matchfield attendees <EmailAddressEntity>)|
|
||||||
|
(matchfield attendeesorganizer <Boolean> <EmailAddressEntity>)|
|
||||||
(matchfield attendeesonlydomainlist <DomainNameList>)|
|
(matchfield attendeesonlydomainlist <DomainNameList>)|
|
||||||
(matchfield attendeesdomainlist <DomainNameList>)|
|
(matchfield attendeesdomainlist <DomainNameList>)|
|
||||||
(matchfield attendeesnotdomainlist <DomainNameList>)|
|
(matchfield attendeesnotdomainlist <DomainNameList>)|
|
||||||
@@ -2468,9 +2469,9 @@ gam print chromehistory releases [todrive <ToDriveAttribute>*]
|
|||||||
pre_provisioned_reenable
|
pre_provisioned_reenable
|
||||||
|
|
||||||
gam update cros <CrOSEntity> action <CrOSAction> [acknowledge_device_touch_requirement]
|
gam update cros <CrOSEntity> action <CrOSAction> [acknowledge_device_touch_requirement]
|
||||||
[actionbatchsize <Integer>]
|
[actionbatchsize <Integer>] [maxtodeprov <Integer>]
|
||||||
gam <CrOSTypeEntity> update action <CrOSAction> [acknowledge_device_touch_requirement]
|
gam <CrOSTypeEntity> update action <CrOSAction> [acknowledge_device_touch_requirement]
|
||||||
[actionbatchsize <Integer>]
|
[actionbatchsize <Integer>] [maxtodeprov <Integer>]
|
||||||
|
|
||||||
<CrOSCommand>
|
<CrOSCommand>
|
||||||
reboot|
|
reboot|
|
||||||
@@ -5499,6 +5500,7 @@ gam print vaultcounts [todrive <ToDriveAttributes>*]
|
|||||||
[excludedrafts <Boolean>]
|
[excludedrafts <Boolean>]
|
||||||
[<JSONData>]
|
[<JSONData>]
|
||||||
[wait <Integer>]
|
[wait <Integer>]
|
||||||
|
[include_suspended_zeros [<Boolean>]]
|
||||||
gam print vaultcounts [todrive <ToDriveAttributes>*]
|
gam print vaultcounts [todrive <ToDriveAttributes>*]
|
||||||
matter <MatterItem> operation <String> [wait <Integer>]
|
matter <MatterItem> operation <String> [wait <Integer>]
|
||||||
|
|
||||||
@@ -7032,7 +7034,7 @@ gam <UserTypeEntity> untrash drivefile <DriveFileEntity> [shortcutandtarget [<Bo
|
|||||||
|
|
||||||
gam <UserTypeEntity> info drivefile <DriveFileEntity>
|
gam <UserTypeEntity> info drivefile <DriveFileEntity>
|
||||||
[returnidonly]
|
[returnidonly]
|
||||||
[filepath|fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
[filepath|fullpath] [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||||
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
||||||
[includepermissionsforview published]
|
[includepermissionsforview published]
|
||||||
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
@@ -7513,7 +7515,7 @@ gam <UserTypeEntity> collect orphans
|
|||||||
|
|
||||||
gam <UserTypeEntity> show fileinfo <DriveFileEntity>
|
gam <UserTypeEntity> show fileinfo <DriveFileEntity>
|
||||||
[returnidonly]
|
[returnidonly]
|
||||||
[filepath|fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
[filepath|fullpath] [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||||
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
||||||
[includepermissionsforview published]
|
[includepermissionsforview published]
|
||||||
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
@@ -7527,12 +7529,12 @@ gam <UserTypeEntity> show filepath <DriveFileEntity>
|
|||||||
[returnpathonly]
|
[returnpathonly]
|
||||||
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
[stripcrsfromname]
|
[stripcrsfromname]
|
||||||
[fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
[fullpath] [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||||
[followshortcuts [<Boolean>]]
|
[followshortcuts [<Boolean>]]
|
||||||
gam <UserTypeEntity> print filepath <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print filepath <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
||||||
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
[stripcrsfromname] [oneitemperrow]
|
[stripcrsfromname] [oneitemperrow]
|
||||||
[fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
[fullpath] [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||||
[followshortcuts [<Boolean>]]
|
[followshortcuts [<Boolean>]]
|
||||||
|
|
||||||
gam <UserTypeEntity> print filecounts [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print filecounts [todrive <ToDriveAttribute>*]
|
||||||
@@ -7635,7 +7637,7 @@ gam <UserTypeEntity> print filelist [todrive <ToDriveAttribute>*]
|
|||||||
[countsonly [summary none|only|plus] [summaryuser <String>]
|
[countsonly [summary none|only|plus] [summaryuser <String>]
|
||||||
[showsource] [showsize] [showsizeunits] [showmimetypesize]]
|
[showsource] [showsize] [showsizeunits] [showmimetypesize]]
|
||||||
[countsrowfilter]
|
[countsrowfilter]
|
||||||
[filepath|fullpath [folderpathonly [<Boolean>]] [pathdelimiter <Character>] [addpathstojson] [showdepth]] [buildtree]
|
[filepath|fullpath [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>] [addpathstojson] [showdepth]] [buildtree]
|
||||||
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
||||||
[showdrivename] [showshareddrivepermissions]
|
[showdrivename] [showshareddrivepermissions]
|
||||||
[(showlabels details|ids)|(includelabels <ClassificationLabelIDList>)]
|
[(showlabels details|ids)|(includelabels <ClassificationLabelIDList>)]
|
||||||
|
|||||||
@@ -1,6 +1,51 @@
|
|||||||
|
7.43.07
|
||||||
|
|
||||||
|
Improved validation of `<QueryCrOS>`, `<QueryDevice>` and `<QueryMobile>`.
|
||||||
|
|
||||||
|
7.43.06
|
||||||
|
|
||||||
|
Updated commands that use `<QueryCrOS>`, `<QueryDevice>` or `<QueryMobile>` to validate
|
||||||
|
that it is of the form `field:value` and that `value` does not contain a '?'.
|
||||||
|
Without validation, Google can return many more devices than are expected.
|
||||||
|
|
||||||
|
7.43.05
|
||||||
|
|
||||||
|
Added option `matchfield attendeesorganizer <Boolean> <EmailAddressEntity>` to `<EventMatchProperty>`
|
||||||
|
that is used in commands that process events. The match is true if all of the addresses in `<EmailAddressEntity>`
|
||||||
|
are present as attendees in the event and are an organizer or not based on `<Boolean>`.
|
||||||
|
|
||||||
|
Added option `max_to_deprov <Integer>` to `gam update cros <CrOSEntity> action <CrOSAction>`
|
||||||
|
that is used when `<CrOSAction>` is any of the following:
|
||||||
|
```
|
||||||
|
deprovision_different_model_replace|
|
||||||
|
deprovision_different_model_replacement|
|
||||||
|
deprovision_retiring_device|
|
||||||
|
deprovision_same_model_replace|
|
||||||
|
deprovision_same_model_replacement|
|
||||||
|
deprovision_upgrade_transfer
|
||||||
|
```
|
||||||
|
`max_to_deprov <Integer>` - No deprovisions are processed if the number of devices in `<CrOSEntity>` exceeds `<Integer>`;
|
||||||
|
the default value is one; set `<Integer>` to 0 for no limit.
|
||||||
|
|
||||||
|
7.43.04
|
||||||
|
|
||||||
|
Added option `include_suspended_zeros [<Boolean>]` to `gam print vaultcounts` that causes
|
||||||
|
GAM to generate zero count lines for suspended users with zero items as well as non-suspended users.
|
||||||
|
|
||||||
|
7.43.03
|
||||||
|
|
||||||
|
Added option `parentpathonly [<Boolean>]` to the following commands that causes GAM
|
||||||
|
to display only the parent folder names when displaying the path to a file.
|
||||||
|
```
|
||||||
|
gam <UserTypeEntity> info drivefile ... filepath|fullpath
|
||||||
|
gam <UserTypeEntity> show fileinfo ... filepath|fullpath
|
||||||
|
gam <UserTypeEntity> print|show filepath
|
||||||
|
gam <UserTypeEntity> print filelist ... filepath|fullpath
|
||||||
|
```
|
||||||
|
|
||||||
7.43.02
|
7.43.02
|
||||||
|
|
||||||
Added option `maxactivities <Number>` to `gam <UserTypeEntity> print driveactivity` to limit
|
Added option `maxactivities <Integer>` to `gam <UserTypeEntity> print driveactivity` to limit
|
||||||
the number of activities displayed; the default is 0, no limit.
|
the number of activities displayed; the default is 0, no limit.
|
||||||
|
|
||||||
7.43.01
|
7.43.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.43.02'
|
__version__ = '7.43.07'
|
||||||
__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
|
||||||
@@ -6071,6 +6071,26 @@ def getQueries(myarg):
|
|||||||
return [getString(Cmd.OB_QUERY)]
|
return [getString(Cmd.OB_QUERY)]
|
||||||
return shlexSplitList(getString(Cmd.OB_QUERY_LIST))
|
return shlexSplitList(getString(Cmd.OB_QUERY_LIST))
|
||||||
|
|
||||||
|
def _validateDeviceQuery(entityType, query):
|
||||||
|
if ':' in query:
|
||||||
|
qfield, qvalue = query.split(':', 1)
|
||||||
|
qfield = qfield.strip()
|
||||||
|
else:
|
||||||
|
qfield = ''
|
||||||
|
qvalue = query
|
||||||
|
if (not qfield) or (not qvalue) or ('?' in query):
|
||||||
|
Cmd.Backup()
|
||||||
|
usageErrorExit(Msg.INVALID_DEVICE_QUERY.format(Ent.Singular(entityType), query))
|
||||||
|
|
||||||
|
def getDeviceQueries(myarg, entityType):
|
||||||
|
if myarg in {'query', 'filter'}:
|
||||||
|
queries = [getString(Cmd.OB_QUERY)]
|
||||||
|
else:
|
||||||
|
queries = shlexSplitList(getString(Cmd.OB_QUERY_LIST))
|
||||||
|
for query in queries:
|
||||||
|
_validateDeviceQuery(entityType, query)
|
||||||
|
return queries
|
||||||
|
|
||||||
def convertEntityToList(entity, shlexSplit=False, nonListEntityType=False):
|
def convertEntityToList(entity, shlexSplit=False, nonListEntityType=False):
|
||||||
if not entity:
|
if not entity:
|
||||||
return []
|
return []
|
||||||
@@ -6756,6 +6776,7 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|||||||
if entityType == Cmd.ENTITY_CROS_SN:
|
if entityType == Cmd.ENTITY_CROS_SN:
|
||||||
queries = [f'id:{query}' for query in queries]
|
queries = [f'id:{query}' for query in queries]
|
||||||
for query in queries:
|
for query in queries:
|
||||||
|
_validateDeviceQuery(Ent.CROS_DEVICE, query)
|
||||||
printGettingAllAccountEntities(Ent.CROS_DEVICE, query)
|
printGettingAllAccountEntities(Ent.CROS_DEVICE, query)
|
||||||
try:
|
try:
|
||||||
result = callGAPIpages(cd.chromeosdevices(), 'list', 'chromeosdevices',
|
result = callGAPIpages(cd.chromeosdevices(), 'list', 'chromeosdevices',
|
||||||
@@ -6782,9 +6803,9 @@ def getItemsToModify(entityType, entity, memberRoles=None, isSuspended=None, isA
|
|||||||
includeChildOrgunits = entityType in Cmd.CROS_OU_CHILDREN_ENTITY_TYPES
|
includeChildOrgunits = entityType in Cmd.CROS_OU_CHILDREN_ENTITY_TYPES
|
||||||
allQualifier = Msg.DIRECTLY_IN_THE.format(Ent.Choose(Ent.ORGANIZATIONAL_UNIT, numOus)) if not includeChildOrgunits else Msg.IN_THE.format(Ent.Choose(Ent.ORGANIZATIONAL_UNIT, numOus))
|
allQualifier = Msg.DIRECTLY_IN_THE.format(Ent.Choose(Ent.ORGANIZATIONAL_UNIT, numOus)) if not includeChildOrgunits else Msg.IN_THE.format(Ent.Choose(Ent.ORGANIZATIONAL_UNIT, numOus))
|
||||||
if entityType in Cmd.CROS_OU_QUERY_ENTITY_TYPES:
|
if entityType in Cmd.CROS_OU_QUERY_ENTITY_TYPES:
|
||||||
queries = getQueries('query')
|
queries = getDeviceQueries('query', Ent.CROS_DEVICE)
|
||||||
elif entityType in Cmd.CROS_OU_QUERIES_ENTITY_TYPES:
|
elif entityType in Cmd.CROS_OU_QUERIES_ENTITY_TYPES:
|
||||||
queries = getQueries('queries')
|
queries = getDeviceQueries('queries', Ent.CROS_DEVICE)
|
||||||
else:
|
else:
|
||||||
queries = [None]
|
queries = [None]
|
||||||
for ou in ous:
|
for ou in ous:
|
||||||
@@ -24210,7 +24231,7 @@ CROS_ACTION_NAME_MAP = {
|
|||||||
|
|
||||||
# gam <CrOSTypeEntity> update <CrOSAttribute>+ [quickcrosmove [<Boolean>]] [nobatchupdate]
|
# gam <CrOSTypeEntity> update <CrOSAttribute>+ [quickcrosmove [<Boolean>]] [nobatchupdate]
|
||||||
# gam <CrOSTypeEntity> update action <CrOSAction> [acknowledge_device_touch_requirement]
|
# gam <CrOSTypeEntity> update action <CrOSAction> [acknowledge_device_touch_requirement]
|
||||||
# [actionbatchsize <Integer>]
|
# [actionbatchsize <Integer>] [maxtodeprov <Integer>]
|
||||||
def updateCrOSDevices(entityList):
|
def updateCrOSDevices(entityList):
|
||||||
cd = buildGAPIObject(API.DIRECTORY)
|
cd = buildGAPIObject(API.DIRECTORY)
|
||||||
noBatchUpdate = False
|
noBatchUpdate = False
|
||||||
@@ -24220,6 +24241,7 @@ def updateCrOSDevices(entityList):
|
|||||||
ackWipe = False
|
ackWipe = False
|
||||||
quickCrOSMove = GC.Values[GC.QUICK_CROS_MOVE]
|
quickCrOSMove = GC.Values[GC.QUICK_CROS_MOVE]
|
||||||
actionBatchSize = 10
|
actionBatchSize = 10
|
||||||
|
maxToDeprovision = None
|
||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
myarg = getArgument()
|
myarg = getArgument()
|
||||||
if myarg in UPDATE_CROS_ARGUMENT_TO_PROPERTY_MAP:
|
if myarg in UPDATE_CROS_ARGUMENT_TO_PROPERTY_MAP:
|
||||||
@@ -24245,6 +24267,8 @@ def updateCrOSDevices(entityList):
|
|||||||
noBatchUpdate = getBoolean()
|
noBatchUpdate = getBoolean()
|
||||||
elif myarg == 'actionbatchsize':
|
elif myarg == 'actionbatchsize':
|
||||||
actionBatchSize = getInteger(minVal=10, maxVal=250)
|
actionBatchSize = getInteger(minVal=10, maxVal=250)
|
||||||
|
elif myarg == 'maxtodeprov':
|
||||||
|
maxToDeprovision = getInteger(minVal=0)
|
||||||
else:
|
else:
|
||||||
unknownArgumentExit()
|
unknownArgumentExit()
|
||||||
if action_body and update_body:
|
if action_body and update_body:
|
||||||
@@ -24258,9 +24282,15 @@ def updateCrOSDevices(entityList):
|
|||||||
i, count, entityList = getEntityArgument(entityList)
|
i, count, entityList = getEntityArgument(entityList)
|
||||||
# Action
|
# Action
|
||||||
if action_body:
|
if action_body:
|
||||||
if action_body['changeChromeOsDeviceStatusAction'] == 'CHANGE_CHROME_OS_DEVICE_STATUS_ACTION_DEPROVISION' and not ackWipe:
|
if action_body['changeChromeOsDeviceStatusAction'] == 'CHANGE_CHROME_OS_DEVICE_STATUS_ACTION_DEPROVISION':
|
||||||
stderrWarningMsg(Msg.REFUSING_TO_DEPROVISION_DEVICES.format(count))
|
if not ackWipe:
|
||||||
systemErrorExit(ACTION_NOT_PERFORMED_RC, None)
|
stderrWarningMsg(Msg.REFUSING_TO_DEPROVISION_DEVICES.format(count))
|
||||||
|
systemErrorExit(ACTION_NOT_PERFORMED_RC, None)
|
||||||
|
if maxToDeprovision is None:
|
||||||
|
maxToDeprovision = 1
|
||||||
|
if count > maxToDeprovision > 0:
|
||||||
|
stderrWarningMsg(Msg.REFUSING_TO_DEPROVISION_N_DEVICES.format(count, maxToDeprovision))
|
||||||
|
systemErrorExit(ACTION_NOT_PERFORMED_RC, None)
|
||||||
while i < count:
|
while i < count:
|
||||||
bcount = min(count-i, actionBatchSize)
|
bcount = min(count-i, actionBatchSize)
|
||||||
action_body['deviceIds'] = entityList[i:i+bcount]
|
action_body['deviceIds'] = entityList[i:i+bcount]
|
||||||
@@ -25352,7 +25382,7 @@ def doPrintCrOSDevices(entityList=None):
|
|||||||
selectionAllowed = False
|
selectionAllowed = False
|
||||||
includeChildOrgunits = myarg in {Cmd.ENTITY_CROS_OU_AND_CHILDREN, Cmd.ENTITY_CROS_OUS_AND_CHILDREN}
|
includeChildOrgunits = myarg in {Cmd.ENTITY_CROS_OU_AND_CHILDREN, Cmd.ENTITY_CROS_OUS_AND_CHILDREN}
|
||||||
elif (selectionAllowed or queries == [None]) and myarg in {'query', 'queries'}:
|
elif (selectionAllowed or queries == [None]) and myarg in {'query', 'queries'}:
|
||||||
queries = getQueries(myarg)
|
queries = getDeviceQueries(myarg, Ent.CROS_DEVICE)
|
||||||
elif myarg.startswith('querytime'):
|
elif myarg.startswith('querytime'):
|
||||||
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
||||||
elif selectionAllowed and myarg == 'select':
|
elif selectionAllowed and myarg == 'select':
|
||||||
@@ -25631,7 +25661,7 @@ def doPrintCrOSActivity(entityList=None):
|
|||||||
selectionAllowed = False
|
selectionAllowed = False
|
||||||
directlyInOU = myarg in {Cmd.ENTITY_CROS_OU, Cmd.ENTITY_CROS_OUS}
|
directlyInOU = myarg in {Cmd.ENTITY_CROS_OU, Cmd.ENTITY_CROS_OUS}
|
||||||
elif (selectionAllowed or queries == [None]) and myarg in {'query', 'queries'}:
|
elif (selectionAllowed or queries == [None]) and myarg in {'query', 'queries'}:
|
||||||
queries = getQueries(myarg)
|
queries = getDeviceQueries(myarg, Ent.CROS_DEVICE)
|
||||||
elif myarg.startswith('querytime'):
|
elif myarg.startswith('querytime'):
|
||||||
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
||||||
elif selectionAllowed and myarg == 'select':
|
elif selectionAllowed and myarg == 'select':
|
||||||
@@ -26156,7 +26186,7 @@ def doMoveBrowsers():
|
|||||||
elif myarg in {'csv', 'csvfile'}:
|
elif myarg in {'csv', 'csvfile'}:
|
||||||
deviceIds.extend(getEntitiesFromCSVFile(False))
|
deviceIds.extend(getEntitiesFromCSVFile(False))
|
||||||
elif myarg in {'query', 'queries'}:
|
elif myarg in {'query', 'queries'}:
|
||||||
queries = getQueries(myarg)
|
queries = getDeviceQueries(myarg, Ent.CHROME_BROWSER)
|
||||||
elif myarg.startswith('querytime'):
|
elif myarg.startswith('querytime'):
|
||||||
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
||||||
elif myarg == 'browserou':
|
elif myarg == 'browserou':
|
||||||
@@ -26708,7 +26738,7 @@ def doPrintShowBrowsers():
|
|||||||
if csvPF and myarg == 'todrive':
|
if csvPF and myarg == 'todrive':
|
||||||
csvPF.GetTodriveParameters()
|
csvPF.GetTodriveParameters()
|
||||||
elif myarg in {'query', 'queries'}:
|
elif myarg in {'query', 'queries'}:
|
||||||
queries = getQueries(myarg)
|
queries = getDeviceQueries(myarg, Ent.CHROME_BROWSER)
|
||||||
elif myarg.startswith('querytime'):
|
elif myarg.startswith('querytime'):
|
||||||
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
||||||
elif myarg in {'ou', 'org', 'orgunit', 'browserou'}:
|
elif myarg in {'ou', 'org', 'orgunit', 'browserou'}:
|
||||||
@@ -26915,7 +26945,7 @@ def doPrintShowBrowserTokens():
|
|||||||
if csvPF and myarg == 'todrive':
|
if csvPF and myarg == 'todrive':
|
||||||
csvPF.GetTodriveParameters()
|
csvPF.GetTodriveParameters()
|
||||||
elif myarg in {'query', 'queries'}:
|
elif myarg in {'query', 'queries'}:
|
||||||
queries = getQueries(myarg)
|
queries = getDeviceQueries(myarg, Ent.CHROME_BROWSER)
|
||||||
elif myarg.startswith('querytime'):
|
elif myarg.startswith('querytime'):
|
||||||
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
||||||
elif myarg in {'ou', 'org', 'orgunit', 'browserou'}:
|
elif myarg in {'ou', 'org', 'orgunit', 'browserou'}:
|
||||||
@@ -31021,6 +31051,7 @@ def getCIDeviceEntity():
|
|||||||
if not name.startswith('devices/'):
|
if not name.startswith('devices/'):
|
||||||
name = f'devices/{name}'
|
name = f'devices/{name}'
|
||||||
return ([{'name': name}], ci, customer, True)
|
return ([{'name': name}], ci, customer, True)
|
||||||
|
_validateDeviceQuery(Ent.DEVICE, query)
|
||||||
printGettingAllAccountEntities(Ent.DEVICE, query)
|
printGettingAllAccountEntities(Ent.DEVICE, query)
|
||||||
pageMessage = getPageMessage()
|
pageMessage = getPageMessage()
|
||||||
try:
|
try:
|
||||||
@@ -31057,6 +31088,7 @@ def getCIDeviceUserEntity():
|
|||||||
return ([{'name': name}], ci, customer, True)
|
return ([{'name': name}], ci, customer, True)
|
||||||
Cmd.Backup()
|
Cmd.Backup()
|
||||||
invalidArgumentExit(DEVICE_USERNAME_FORMAT_REQUIRED)
|
invalidArgumentExit(DEVICE_USERNAME_FORMAT_REQUIRED)
|
||||||
|
_validateDeviceQuery(Ent.DEVICE_USER, query)
|
||||||
printGettingAllAccountEntities(Ent.DEVICE_USER, query)
|
printGettingAllAccountEntities(Ent.DEVICE_USER, query)
|
||||||
pageMessage = getPageMessage()
|
pageMessage = getPageMessage()
|
||||||
try:
|
try:
|
||||||
@@ -31205,7 +31237,7 @@ def doSyncCIDevices():
|
|||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
myarg = getArgument()
|
myarg = getArgument()
|
||||||
if myarg in ['filter', 'filters', 'query', 'queries']:
|
if myarg in ['filter', 'filters', 'query', 'queries']:
|
||||||
queries = getQueries(myarg)
|
queries = getDeviceQueries(myarg, Ent.COMPANY_DEVICE)
|
||||||
elif myarg.startswith('querytime'):
|
elif myarg.startswith('querytime'):
|
||||||
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
||||||
elif myarg in {'csv', 'csvfile'}:
|
elif myarg in {'csv', 'csvfile'}:
|
||||||
@@ -31511,7 +31543,7 @@ def doPrintCIDevices():
|
|||||||
if csvPF and myarg == 'todrive':
|
if csvPF and myarg == 'todrive':
|
||||||
csvPF.GetTodriveParameters()
|
csvPF.GetTodriveParameters()
|
||||||
elif myarg in ['filter', 'filters', 'query', 'queries']:
|
elif myarg in ['filter', 'filters', 'query', 'queries']:
|
||||||
queries = getQueries(myarg)
|
queries = getDeviceQueries(myarg, entityType)
|
||||||
elif myarg.startswith('querytime'):
|
elif myarg.startswith('querytime'):
|
||||||
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
||||||
elif myarg == 'orderby':
|
elif myarg == 'orderby':
|
||||||
@@ -31749,7 +31781,7 @@ def doPrintCIDeviceUsers():
|
|||||||
if not parent.startswith('devices/'):
|
if not parent.startswith('devices/'):
|
||||||
parent = f'devices/{parent}'
|
parent = f'devices/{parent}'
|
||||||
elif myarg in ['filter', 'filters', 'query', 'queries']:
|
elif myarg in ['filter', 'filters', 'query', 'queries']:
|
||||||
queries = getQueries(myarg)
|
queries = getDeviceQueries(myarg, Ent.DEVICE_USER)
|
||||||
elif myarg.startswith('querytime'):
|
elif myarg.startswith('querytime'):
|
||||||
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
||||||
elif myarg == 'orderby':
|
elif myarg == 'orderby':
|
||||||
@@ -33397,6 +33429,7 @@ def getMobileDeviceEntity():
|
|||||||
query = None
|
query = None
|
||||||
if not query:
|
if not query:
|
||||||
return ([{'resourceId': device, 'email': []} for device in getEntityList(Cmd.OB_MOBILE_ENTITY)], cd, True)
|
return ([{'resourceId': device, 'email': []} for device in getEntityList(Cmd.OB_MOBILE_ENTITY)], cd, True)
|
||||||
|
_validateDeviceQuery(Ent.MOBILE_DEVICE, query)
|
||||||
try:
|
try:
|
||||||
printGettingAllAccountEntities(Ent.MOBILE_DEVICE, query)
|
printGettingAllAccountEntities(Ent.MOBILE_DEVICE, query)
|
||||||
devices = callGAPIpages(cd.mobiledevices(), 'list', 'mobiledevices',
|
devices = callGAPIpages(cd.mobiledevices(), 'list', 'mobiledevices',
|
||||||
@@ -33707,7 +33740,7 @@ def doPrintMobileDevices():
|
|||||||
if myarg == 'todrive':
|
if myarg == 'todrive':
|
||||||
csvPF.GetTodriveParameters()
|
csvPF.GetTodriveParameters()
|
||||||
elif myarg in {'query', 'queries'}:
|
elif myarg in {'query', 'queries'}:
|
||||||
queries = getQueries(myarg)
|
queries = getDeviceQueries(myarg, Ent.MOBILE_DEVICE)
|
||||||
elif myarg.startswith('querytime'):
|
elif myarg.startswith('querytime'):
|
||||||
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
queryTimes[myarg] = getTimeOrDeltaFromNow()[0:19]
|
||||||
elif myarg == 'orderby':
|
elif myarg == 'orderby':
|
||||||
@@ -41121,6 +41154,8 @@ LIST_EVENTS_SELECT_PROPERTIES = {
|
|||||||
|
|
||||||
LIST_EVENTS_MATCH_FIELDS = {
|
LIST_EVENTS_MATCH_FIELDS = {
|
||||||
'attendees': ['attendees', 'email'],
|
'attendees': ['attendees', 'email'],
|
||||||
|
'attendeesorganizer': ['attendees', 'organizer'],
|
||||||
|
'attendeesorganiser': ['attendees', 'organizer'],
|
||||||
'attendeesonlydomainlist': ['attendees', 'onlydomainlist'],
|
'attendeesonlydomainlist': ['attendees', 'onlydomainlist'],
|
||||||
'attendeesdomainlist': ['attendees', 'domainlist'],
|
'attendeesdomainlist': ['attendees', 'domainlist'],
|
||||||
'attendeesnotdomainlist': ['attendees', 'notdomainlist'],
|
'attendeesnotdomainlist': ['attendees', 'notdomainlist'],
|
||||||
@@ -41200,6 +41235,8 @@ def getCalendarEventEntity():
|
|||||||
calendarEventEntity['matches'].append((matchField, set(getString(Cmd.OB_DOMAIN_NAME_LIST).replace(',', ' ').split())))
|
calendarEventEntity['matches'].append((matchField, set(getString(Cmd.OB_DOMAIN_NAME_LIST).replace(',', ' ').split())))
|
||||||
elif matchField[1] == 'email':
|
elif matchField[1] == 'email':
|
||||||
calendarEventEntity['matches'].append((matchField, getNormalizedEmailAddressEntity()))
|
calendarEventEntity['matches'].append((matchField, getNormalizedEmailAddressEntity()))
|
||||||
|
elif matchField[1] == 'organizer':
|
||||||
|
calendarEventEntity['matches'].append((matchField, getBoolean(defaultValue=None), getNormalizedEmailAddressEntity()))
|
||||||
else: #status
|
else: #status
|
||||||
calendarEventEntity['matches'].append((matchField,
|
calendarEventEntity['matches'].append((matchField,
|
||||||
getChoice(CALENDAR_ATTENDEE_OPTIONAL_CHOICE_MAP, defaultChoice=False, mapChoice=True),
|
getChoice(CALENDAR_ATTENDEE_OPTIONAL_CHOICE_MAP, defaultChoice=False, mapChoice=True),
|
||||||
@@ -41531,7 +41568,17 @@ def _eventMatches(event, match):
|
|||||||
if domain not in match[1]:
|
if domain not in match[1]:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
# status
|
if match[0][1] == 'organizer':
|
||||||
|
for matchEmail in match[2]:
|
||||||
|
for attendee in event['attendees']:
|
||||||
|
if 'email' in attendee and matchEmail == attendee['email']:
|
||||||
|
if attendee.get('organizer', False) != match[1]:
|
||||||
|
return False
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
# if match[0][1] == 'status':
|
||||||
for matchEmail in match[3]:
|
for matchEmail in match[3]:
|
||||||
for attendee in event['attendees']:
|
for attendee in event['attendees']:
|
||||||
if 'email' in attendee and matchEmail == attendee['email']:
|
if 'email' in attendee and matchEmail == attendee['email']:
|
||||||
@@ -45391,11 +45438,13 @@ PRINT_VAULT_COUNTS_TITLES = ['account', 'count', 'error']
|
|||||||
# [excludedrafts <Boolean>]
|
# [excludedrafts <Boolean>]
|
||||||
# [<JSONData>]
|
# [<JSONData>]
|
||||||
# [wait <Integer>]
|
# [wait <Integer>]
|
||||||
|
# [include_suspended_zeros [<Boolean>]]
|
||||||
# gam print vaultcounts [todrive <ToDriveAttributes>*]
|
# gam print vaultcounts [todrive <ToDriveAttributes>*]
|
||||||
# matter <MatterItem> operation <String> [wait <Integer>]
|
# matter <MatterItem> operation <String> [wait <Integer>]
|
||||||
def doPrintVaultCounts():
|
def doPrintVaultCounts():
|
||||||
v = buildGAPIObject(API.VAULT)
|
v = buildGAPIObject(API.VAULT)
|
||||||
csvPF = CSVPrintFile(PRINT_VAULT_COUNTS_TITLES, 'sortall')
|
csvPF = CSVPrintFile(PRINT_VAULT_COUNTS_TITLES, 'sortall')
|
||||||
|
includeSuspendedZeros = False
|
||||||
matterId = name = None
|
matterId = name = None
|
||||||
operationWait = 15
|
operationWait = 15
|
||||||
body = {'view': 'ALL', 'query': {}}
|
body = {'view': 'ALL', 'query': {}}
|
||||||
@@ -45413,6 +45462,8 @@ def doPrintVaultCounts():
|
|||||||
_buildVaultQuery(myarg, body['query'], VAULT_COUNTS_CORPUS_ARGUMENT_MAP)
|
_buildVaultQuery(myarg, body['query'], VAULT_COUNTS_CORPUS_ARGUMENT_MAP)
|
||||||
elif myarg == 'wait':
|
elif myarg == 'wait':
|
||||||
operationWait = getInteger(minVal=1)
|
operationWait = getInteger(minVal=1)
|
||||||
|
elif myarg == "includesuspendedzeros":
|
||||||
|
includeSuspendedZeros = getBoolean()
|
||||||
else:
|
else:
|
||||||
unknownArgumentExit()
|
unknownArgumentExit()
|
||||||
if not matterId:
|
if not matterId:
|
||||||
@@ -45451,9 +45502,13 @@ def doPrintVaultCounts():
|
|||||||
if search_method == 'ACCOUNT':
|
if search_method == 'ACCOUNT':
|
||||||
query_accounts = query.get('accountInfo', {}).get('emails', [])
|
query_accounts = query.get('accountInfo', {}).get('emails', [])
|
||||||
elif search_method == 'ENTIRE_ORG':
|
elif search_method == 'ENTIRE_ORG':
|
||||||
query_accounts = getItemsToModify(Cmd.ENTITY_ALL_USERS, '')
|
query_accounts = getItemsToModify(Cmd.ENTITY_ALL_USERS if not includeSuspendedZeros else Cmd.ENTITY_ALL_USERS_NS_SUSP,
|
||||||
|
'')
|
||||||
elif search_method == 'ORG_UNIT':
|
elif search_method == 'ORG_UNIT':
|
||||||
query_accounts = getItemsToModify(Cmd.ENTITY_OU, query['orgUnitInfo']['orgUnitId'])
|
query_accounts = getItemsToModify(Cmd.ENTITY_OU if not includeSuspendedZeros else Cmd.ENTITY_OU_NS_SUSP,
|
||||||
|
query['orgUnitInfo']['orgUnitId'])
|
||||||
|
else:
|
||||||
|
query_accounts = []
|
||||||
mailcounts = response.get('mailCountResult', {})
|
mailcounts = response.get('mailCountResult', {})
|
||||||
groupcounts = response.get('groupsCountResult', {})
|
groupcounts = response.get('groupsCountResult', {})
|
||||||
for a_count in [mailcounts, groupcounts]:
|
for a_count in [mailcounts, groupcounts]:
|
||||||
@@ -57541,7 +57596,7 @@ def initFilePathInfo(delimiter):
|
|||||||
return {'ids': {}, 'allPaths': {}, 'localPaths': None, 'delimiter': delimiter}
|
return {'ids': {}, 'allPaths': {}, 'localPaths': None, 'delimiter': delimiter}
|
||||||
|
|
||||||
def getFilePaths(drive, fileTree, initialResult, filePathInfo, addParentsToTree=False,
|
def getFilePaths(drive, fileTree, initialResult, filePathInfo, addParentsToTree=False,
|
||||||
fullpath=False, showDepth=False, folderPathOnly=False):
|
fullpath=False, showDepth=False, folderPathOnly=False, parentPathOnly=False):
|
||||||
def _getParentName(result):
|
def _getParentName(result):
|
||||||
if (result['mimeType'] == MIMETYPE_GA_FOLDER) and result.get('driveId') and (result['name'] == TEAM_DRIVE):
|
if (result['mimeType'] == MIMETYPE_GA_FOLDER) and result.get('driveId') and (result['name'] == TEAM_DRIVE):
|
||||||
parentName = _getSharedDriveNameFromId(drive, result['driveId'])
|
parentName = _getSharedDriveNameFromId(drive, result['driveId'])
|
||||||
@@ -57595,8 +57650,9 @@ def getFilePaths(drive, fileTree, initialResult, filePathInfo, addParentsToTree=
|
|||||||
if depth > maxDepth:
|
if depth > maxDepth:
|
||||||
maxDepth = depth-1
|
maxDepth = depth-1
|
||||||
fp.reverse()
|
fp.reverse()
|
||||||
if initialMimeType == MIMETYPE_GA_FOLDER or not folderPathOnly:
|
if not parentPathOnly:
|
||||||
fp.append(name)
|
if initialMimeType == MIMETYPE_GA_FOLDER or not folderPathOnly:
|
||||||
|
fp.append(name)
|
||||||
filePaths.append(filePathInfo['delimiter'].join(fp))
|
filePaths.append(filePathInfo['delimiter'].join(fp))
|
||||||
else:
|
else:
|
||||||
maxDepth = _makeFilePaths(v, fplist, filePaths, name, maxDepth)
|
maxDepth = _makeFilePaths(v, fplist, filePaths, name, maxDepth)
|
||||||
@@ -58112,7 +58168,7 @@ def _formatFileDriveLabels(showLabels, labels, result, printMode, delimiter):
|
|||||||
|
|
||||||
# gam <UserTypeEntity> info drivefile <DriveFileEntity>
|
# gam <UserTypeEntity> info drivefile <DriveFileEntity>
|
||||||
# [returnidonly]
|
# [returnidonly]
|
||||||
# [filepath|fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
# [filepath|fullpath] [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||||
# [allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)] [formatjson]
|
# [allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)] [formatjson]
|
||||||
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
# [showdrivename] [showshareddrivepermissions]
|
# [showdrivename] [showshareddrivepermissions]
|
||||||
@@ -58122,7 +58178,7 @@ def _formatFileDriveLabels(showLabels, labels, result, printMode, delimiter):
|
|||||||
# [stripcrsfromname] [formatjson]
|
# [stripcrsfromname] [formatjson]
|
||||||
# gam <UserTypeEntity> show fileinfo <DriveFileEntity>
|
# gam <UserTypeEntity> show fileinfo <DriveFileEntity>
|
||||||
# [returnidonly]
|
# [returnidonly]
|
||||||
# [filepath|fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
# [filepath|fullpath] [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||||
# [allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)] [formatjson]
|
# [allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)] [formatjson]
|
||||||
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
# [showdrivename] [showshareddrivepermissions]
|
# [showdrivename] [showshareddrivepermissions]
|
||||||
@@ -58140,7 +58196,7 @@ def showFileInfo(users):
|
|||||||
if followShortcuts:
|
if followShortcuts:
|
||||||
_setSkipObjects(skipObjects, ['mimeType', 'shortcutDetails'], DFF.fieldsList)
|
_setSkipObjects(skipObjects, ['mimeType', 'shortcutDetails'], DFF.fieldsList)
|
||||||
|
|
||||||
getPermissionsForSharedDrives = filepath = fullpath = folderPathOnly = followShortcuts = \
|
getPermissionsForSharedDrives = filepath = fullpath = folderPathOnly = parentPathOnly = followShortcuts = \
|
||||||
returnIdOnly = showParentsIdsAsList = showNoParents = stripCRsFromName = False
|
returnIdOnly = showParentsIdsAsList = showNoParents = stripCRsFromName = False
|
||||||
pathDelimiter = '/'
|
pathDelimiter = '/'
|
||||||
showLabels = None
|
showLabels = None
|
||||||
@@ -58158,6 +58214,8 @@ def showFileInfo(users):
|
|||||||
filepath = fullpath = True
|
filepath = fullpath = True
|
||||||
elif myarg == 'folderpathonly':
|
elif myarg == 'folderpathonly':
|
||||||
folderPathOnly = getBoolean()
|
folderPathOnly = getBoolean()
|
||||||
|
elif myarg == 'parentpathonly':
|
||||||
|
parentPathOnly = getBoolean()
|
||||||
elif myarg == 'pathdelimiter':
|
elif myarg == 'pathdelimiter':
|
||||||
pathDelimiter = getCharacter()
|
pathDelimiter = getCharacter()
|
||||||
elif myarg == 'showparentsidsaslist':
|
elif myarg == 'showparentsidsaslist':
|
||||||
@@ -58274,7 +58332,7 @@ def showFileInfo(users):
|
|||||||
extendFileTreeParents(drive, fileTree, pathFields)
|
extendFileTreeParents(drive, fileTree, pathFields)
|
||||||
if not FJQC.formatJSON:
|
if not FJQC.formatJSON:
|
||||||
_, paths, _ = getFilePaths(drive, fileTree, result, filePathInfo, addParentsToTree=True,
|
_, paths, _ = getFilePaths(drive, fileTree, result, filePathInfo, addParentsToTree=True,
|
||||||
fullpath=fullpath, folderPathOnly=folderPathOnly)
|
fullpath=fullpath, folderPathOnly=folderPathOnly, parentPathOnly=parentPathOnly)
|
||||||
kcount = len(paths)
|
kcount = len(paths)
|
||||||
printKeyValueList(['paths', kcount])
|
printKeyValueList(['paths', kcount])
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
@@ -58283,7 +58341,7 @@ def showFileInfo(users):
|
|||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
else:
|
else:
|
||||||
addFilePathsToInfo(drive, fileTree, result, filePathInfo,
|
addFilePathsToInfo(drive, fileTree, result, filePathInfo,
|
||||||
addParentsToTree=True, folderPathOnly=folderPathOnly)
|
addParentsToTree=True, folderPathOnly=folderPathOnly, parentPathOnly=parentPathOnly)
|
||||||
if fullpath:
|
if fullpath:
|
||||||
# Save simple parents list as mappings turn it into a list of dicts
|
# Save simple parents list as mappings turn it into a list of dicts
|
||||||
fpparents = result['parents'][:]
|
fpparents = result['parents'][:]
|
||||||
@@ -58960,9 +59018,9 @@ def buildFileTree(feed, drive):
|
|||||||
return fileTree
|
return fileTree
|
||||||
|
|
||||||
def addFilePathsToRow(drive, fileTree, fileEntryInfo, filePathInfo, csvPF, row,
|
def addFilePathsToRow(drive, fileTree, fileEntryInfo, filePathInfo, csvPF, row,
|
||||||
fullpath=False, showDepth=False, folderPathOnly=False):
|
fullpath=False, showDepth=False, folderPathOnly=False, parentPathOnly=False):
|
||||||
_, paths, maxDepth = getFilePaths(drive, fileTree, fileEntryInfo, filePathInfo,
|
_, paths, maxDepth = getFilePaths(drive, fileTree, fileEntryInfo, filePathInfo,
|
||||||
fullpath=fullpath, showDepth=showDepth, folderPathOnly=folderPathOnly)
|
fullpath=fullpath, showDepth=showDepth, folderPathOnly=folderPathOnly, parentPathOnly=parentPathOnly)
|
||||||
kcount = len(paths)
|
kcount = len(paths)
|
||||||
if showDepth:
|
if showDepth:
|
||||||
row['depth'] = maxDepth
|
row['depth'] = maxDepth
|
||||||
@@ -58977,9 +59035,9 @@ def addFilePathsToRow(drive, fileTree, fileEntryInfo, filePathInfo, csvPF, row,
|
|||||||
row[key] = path
|
row[key] = path
|
||||||
k += 1
|
k += 1
|
||||||
|
|
||||||
def addFilePathsToInfo(drive, fileTree, fileEntryInfo, filePathInfo, addParentsToTree=False, folderPathOnly=False):
|
def addFilePathsToInfo(drive, fileTree, fileEntryInfo, filePathInfo, addParentsToTree=False, folderPathOnly=False, parentPathOnly=False):
|
||||||
_, paths, _ = getFilePaths(drive, fileTree, fileEntryInfo, filePathInfo, addParentsToTree=addParentsToTree,
|
_, paths, _ = getFilePaths(drive, fileTree, fileEntryInfo, filePathInfo, addParentsToTree=addParentsToTree,
|
||||||
showDepth=False, folderPathOnly=folderPathOnly)
|
showDepth=False, folderPathOnly=folderPathOnly, parentPathOnly=parentPathOnly)
|
||||||
fileEntryInfo['paths'] = []
|
fileEntryInfo['paths'] = []
|
||||||
for path in sorted(paths):
|
for path in sorted(paths):
|
||||||
if GC.Values[GC.CSV_OUTPUT_CONVERT_CR_NL] and (path.find('\n') >= 0 or path.find('\r') >= 0):
|
if GC.Values[GC.CSV_OUTPUT_CONVERT_CR_NL] and (path.find('\n') >= 0 or path.find('\r') >= 0):
|
||||||
@@ -59572,7 +59630,7 @@ SIZE_FIELD_CHOICE_MAP = {
|
|||||||
# [countsonly [summary none|only|plus] [summaryuser <String>]
|
# [countsonly [summary none|only|plus] [summaryuser <String>]
|
||||||
# [showsource] [showsize] [showsizeunits] [showmimetypesize]]
|
# [showsource] [showsize] [showsizeunits] [showmimetypesize]]
|
||||||
# [countsrowfilter]
|
# [countsrowfilter]
|
||||||
# [filepath|fullpath [folderpathonly [<Boolean>]] [pathdelimiter <Character>] [addpathstojson] [showdepth]] [buildtree]
|
# [filepath|fullpath [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>] [addpathstojson] [showdepth]] [buildtree]
|
||||||
# [allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
# [allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
||||||
# [showdrivename] [showshareddrivepermissions]
|
# [showdrivename] [showshareddrivepermissions]
|
||||||
# (showlabels details|ids)|(includelabels <DriveLabelIDList>)]
|
# (showlabels details|ids)|(includelabels <DriveLabelIDList>)]
|
||||||
@@ -59676,9 +59734,9 @@ def printFileList(users):
|
|||||||
if filepath:
|
if filepath:
|
||||||
if not FJQC.formatJSON or not addPathsToJSON:
|
if not FJQC.formatJSON or not addPathsToJSON:
|
||||||
addFilePathsToRow(drive, fileTree, fileInfo, filePathInfo, csvPF, row,
|
addFilePathsToRow(drive, fileTree, fileInfo, filePathInfo, csvPF, row,
|
||||||
fullpath=fullpath, showDepth=showDepth, folderPathOnly=folderPathOnly)
|
fullpath=fullpath, showDepth=showDepth, folderPathOnly=folderPathOnly, parentPathOnly=parentPathOnly)
|
||||||
else:
|
else:
|
||||||
addFilePathsToInfo(drive, fileTree, fileInfo, filePathInfo, folderPathOnly=folderPathOnly)
|
addFilePathsToInfo(drive, fileTree, fileInfo, filePathInfo, folderPathOnly=folderPathOnly, parentPathOnly=parentPathOnly)
|
||||||
_mapDriveInfo(fileInfo, DFF.parentsSubFields, showParentsIdsAsList)
|
_mapDriveInfo(fileInfo, DFF.parentsSubFields, showParentsIdsAsList)
|
||||||
if showParentsIdsAsList and 'parentsIds' in fileInfo:
|
if showParentsIdsAsList and 'parentsIds' in fileInfo:
|
||||||
fileInfo['parents'] = len(fileInfo['parentsIds'])
|
fileInfo['parents'] = len(fileInfo['parentsIds'])
|
||||||
@@ -59812,7 +59870,7 @@ def printFileList(users):
|
|||||||
csvPF = CSVPrintFile('Owner', indexedTitles=DRIVE_INDEXED_TITLES)
|
csvPF = CSVPrintFile('Owner', indexedTitles=DRIVE_INDEXED_TITLES)
|
||||||
csvPFco = None
|
csvPFco = None
|
||||||
FJQC = FormatJSONQuoteChar(csvPF)
|
FJQC = FormatJSONQuoteChar(csvPF)
|
||||||
addPathsToJSON = continueOnInvalidQuery = countsRowFilter = buildTree = countsOnly = filepath = fullpath = folderPathOnly = \
|
addPathsToJSON = continueOnInvalidQuery = countsRowFilter = buildTree = countsOnly = filepath = fullpath = folderPathOnly = parentPathOnly = \
|
||||||
getPermissionDetailsForMyDrive = getPermissionsForSharedDrives = mimeTypeInQuery = noRecursion = oneItemPerRow = stripCRsFromName = \
|
getPermissionDetailsForMyDrive = getPermissionsForSharedDrives = mimeTypeInQuery = noRecursion = oneItemPerRow = stripCRsFromName = \
|
||||||
showParentsIdsAsList = showDepth = showParent = showSize = showSizeUnits = showMimeTypeSize = showSource = False
|
showParentsIdsAsList = showDepth = showParent = showSize = showSizeUnits = showMimeTypeSize = showSource = False
|
||||||
sizeField = 'quotaBytesUsed'
|
sizeField = 'quotaBytesUsed'
|
||||||
@@ -59870,6 +59928,8 @@ def printFileList(users):
|
|||||||
fullpath = myarg == 'fullpath'
|
fullpath = myarg == 'fullpath'
|
||||||
elif myarg == 'folderpathonly':
|
elif myarg == 'folderpathonly':
|
||||||
folderPathOnly = getBoolean()
|
folderPathOnly = getBoolean()
|
||||||
|
elif myarg == 'parentpathonly':
|
||||||
|
parentPathOnly = getBoolean()
|
||||||
elif myarg == 'pathdelimiter':
|
elif myarg == 'pathdelimiter':
|
||||||
pathDelimiter = getCharacter()
|
pathDelimiter = getCharacter()
|
||||||
elif myarg == 'addpathstojson':
|
elif myarg == 'addpathstojson':
|
||||||
@@ -60168,7 +60228,7 @@ def printFileList(users):
|
|||||||
break
|
break
|
||||||
if fullpath:
|
if fullpath:
|
||||||
getFilePaths(drive, fileTree, fileEntryInfo, filePathInfo, addParentsToTree=True,
|
getFilePaths(drive, fileTree, fileEntryInfo, filePathInfo, addParentsToTree=True,
|
||||||
fullpath=fullpath, showDepth=showDepth, folderPathOnly=folderPathOnly)
|
fullpath=fullpath, showDepth=showDepth, folderPathOnly=folderPathOnly, parentPathOnly=parentPathOnly)
|
||||||
if ((showParent and (fileEntryInfo['id'] not in {ORPHANS, SHARED_WITHME, SHARED_DRIVES})) or
|
if ((showParent and (fileEntryInfo['id'] not in {ORPHANS, SHARED_WITHME, SHARED_DRIVES})) or
|
||||||
fileEntryInfo['mimeType'] != MIMETYPE_GA_FOLDER or noRecursion):
|
fileEntryInfo['mimeType'] != MIMETYPE_GA_FOLDER or noRecursion):
|
||||||
if fileId not in filesPrinted:
|
if fileId not in filesPrinted:
|
||||||
@@ -60463,18 +60523,18 @@ def printShowFileComments(users):
|
|||||||
# gam <UserTypeEntity> print filepaths <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
# gam <UserTypeEntity> print filepaths <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
||||||
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
# [stripcrsfromname] [oneitemperrow]
|
# [stripcrsfromname] [oneitemperrow]
|
||||||
# [fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
# [fullpath] [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||||
# [followshortcuts [<Boolean>]]
|
# [followshortcuts [<Boolean>]]
|
||||||
# gam <UserTypeEntity> show filepaths <DriveFileEntity>
|
# gam <UserTypeEntity> show filepaths <DriveFileEntity>
|
||||||
# [returnpathonly]
|
# [returnpathonly]
|
||||||
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
# (orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
# [stripcrsfromname]
|
# [stripcrsfromname]
|
||||||
# [fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
# [fullpath] [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||||
# [followshortcuts [<Boolean>]]
|
# [followshortcuts [<Boolean>]]
|
||||||
def printShowFilePaths(users):
|
def printShowFilePaths(users):
|
||||||
csvPF = CSVPrintFile(['Owner', 'id', 'name', 'paths'], 'sortall', ['paths']) if Act.csvFormat() else None
|
csvPF = CSVPrintFile(['Owner', 'id', 'name', 'paths'], 'sortall', ['paths']) if Act.csvFormat() else None
|
||||||
fileIdEntity = getDriveFileEntity()
|
fileIdEntity = getDriveFileEntity()
|
||||||
fullpath = folderPathOnly = followShortcuts = oneItemPerRow = returnPathOnly = stripCRsFromName = False
|
fullpath = folderPathOnly = parentPathOnly = followShortcuts = oneItemPerRow = returnPathOnly = stripCRsFromName = False
|
||||||
pathDelimiter = '/'
|
pathDelimiter = '/'
|
||||||
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
|
OBY = OrderBy(DRIVEFILE_ORDERBY_CHOICE_MAP)
|
||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
@@ -60485,6 +60545,8 @@ def printShowFilePaths(users):
|
|||||||
fullpath = True
|
fullpath = True
|
||||||
elif myarg == 'folderpathonly':
|
elif myarg == 'folderpathonly':
|
||||||
folderPathOnly = getBoolean()
|
folderPathOnly = getBoolean()
|
||||||
|
elif myarg == 'parentpathonly':
|
||||||
|
parentPathOnly = getBoolean()
|
||||||
elif myarg == 'pathdelimiter':
|
elif myarg == 'pathdelimiter':
|
||||||
pathDelimiter = getCharacter()
|
pathDelimiter = getCharacter()
|
||||||
elif myarg == 'stripcrsfromname':
|
elif myarg == 'stripcrsfromname':
|
||||||
@@ -60556,7 +60618,7 @@ def printShowFilePaths(users):
|
|||||||
extendFileTree(fileTree, [result], None, False)
|
extendFileTree(fileTree, [result], None, False)
|
||||||
extendFileTreeParents(drive, fileTree, pathFields)
|
extendFileTreeParents(drive, fileTree, pathFields)
|
||||||
entityType, paths, _ = getFilePaths(drive, fileTree, result, filePathInfo, addParentsToTree=True,
|
entityType, paths, _ = getFilePaths(drive, fileTree, result, filePathInfo, addParentsToTree=True,
|
||||||
fullpath=fullpath, folderPathOnly=folderPathOnly)
|
fullpath=fullpath, folderPathOnly=folderPathOnly, parentPathOnly=parentPathOnly)
|
||||||
if returnPathOnly:
|
if returnPathOnly:
|
||||||
for path in paths:
|
for path in paths:
|
||||||
writeStdout(f'{path}\n')
|
writeStdout(f'{path}\n')
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class GamCLArgs():
|
|||||||
ENTITY_DOMAINS_ARCH = 'domains_arch'
|
ENTITY_DOMAINS_ARCH = 'domains_arch'
|
||||||
ENTITY_DOMAINS_NS = 'domains_ns'
|
ENTITY_DOMAINS_NS = 'domains_ns'
|
||||||
ENTITY_DOMAINS_SUSP = 'domains_susp'
|
ENTITY_DOMAINS_SUSP = 'domains_susp'
|
||||||
|
ENTITY_DOMAINS_NS_SUSP = 'domains_ns_susp'
|
||||||
ENTITY_DOMAINS_NA_NS = 'domains_na_ns'
|
ENTITY_DOMAINS_NA_NS = 'domains_na_ns'
|
||||||
ENTITY_GROUP = 'group'
|
ENTITY_GROUP = 'group'
|
||||||
ENTITY_GROUP_INDE = 'group_inde'
|
ENTITY_GROUP_INDE = 'group_inde'
|
||||||
@@ -60,6 +61,7 @@ class GamCLArgs():
|
|||||||
ENTITY_GROUP_ARCH = 'group_arch'
|
ENTITY_GROUP_ARCH = 'group_arch'
|
||||||
ENTITY_GROUP_NS = 'group_ns'
|
ENTITY_GROUP_NS = 'group_ns'
|
||||||
ENTITY_GROUP_SUSP = 'group_susp'
|
ENTITY_GROUP_SUSP = 'group_susp'
|
||||||
|
ENTITY_GROUP_NS_SUSP = 'group_ns_susp'
|
||||||
ENTITY_GROUP_NA_NS = 'group_na_ns'
|
ENTITY_GROUP_NA_NS = 'group_na_ns'
|
||||||
ENTITY_GROUPS = 'groups'
|
ENTITY_GROUPS = 'groups'
|
||||||
ENTITY_GROUPS_INDE = 'groups_inde'
|
ENTITY_GROUPS_INDE = 'groups_inde'
|
||||||
@@ -67,12 +69,14 @@ class GamCLArgs():
|
|||||||
ENTITY_GROUPS_ARCH = 'groups_arch'
|
ENTITY_GROUPS_ARCH = 'groups_arch'
|
||||||
ENTITY_GROUPS_NS = 'groups_ns'
|
ENTITY_GROUPS_NS = 'groups_ns'
|
||||||
ENTITY_GROUPS_SUSP = 'groups_susp'
|
ENTITY_GROUPS_SUSP = 'groups_susp'
|
||||||
|
ENTITY_GROUPS_NS_SUSP = 'groups_ns_susp'
|
||||||
ENTITY_GROUPS_NA_NS = 'groups_na_ns'
|
ENTITY_GROUPS_NA_NS = 'groups_na_ns'
|
||||||
ENTITY_GROUP_USERS = 'group_users'
|
ENTITY_GROUP_USERS = 'group_users'
|
||||||
ENTITY_GROUP_USERS_NA = 'group_users_na'
|
ENTITY_GROUP_USERS_NA = 'group_users_na'
|
||||||
ENTITY_GROUP_USERS_ARCH = 'group_users_arch'
|
ENTITY_GROUP_USERS_ARCH = 'group_users_arch'
|
||||||
ENTITY_GROUP_USERS_NS = 'group_users_ns'
|
ENTITY_GROUP_USERS_NS = 'group_users_ns'
|
||||||
ENTITY_GROUP_USERS_SUSP = 'group_users_susp'
|
ENTITY_GROUP_USERS_SUSP = 'group_users_susp'
|
||||||
|
ENTITY_GROUP_USERS_NS_SUSP = 'group_users_ns_susp'
|
||||||
ENTITY_GROUP_USERS_NA_NS = 'group_users_na_ns'
|
ENTITY_GROUP_USERS_NA_NS = 'group_users_na_ns'
|
||||||
ENTITY_GROUP_USERS_SELECT = 'group_users_select'
|
ENTITY_GROUP_USERS_SELECT = 'group_users_select'
|
||||||
ENTITY_LICENSES = 'licenses'
|
ENTITY_LICENSES = 'licenses'
|
||||||
@@ -82,24 +86,28 @@ class GamCLArgs():
|
|||||||
ENTITY_OU_ARCH = 'ou_arch'
|
ENTITY_OU_ARCH = 'ou_arch'
|
||||||
ENTITY_OU_NS = 'ou_ns'
|
ENTITY_OU_NS = 'ou_ns'
|
||||||
ENTITY_OU_SUSP = 'ou_susp'
|
ENTITY_OU_SUSP = 'ou_susp'
|
||||||
|
ENTITY_OU_NS_SUSP = 'ou_ns_susp'
|
||||||
ENTITY_OU_NA_NS = 'ou_na_ns'
|
ENTITY_OU_NA_NS = 'ou_na_ns'
|
||||||
ENTITY_OU_AND_CHILDREN = 'ou_and_children'
|
ENTITY_OU_AND_CHILDREN = 'ou_and_children'
|
||||||
ENTITY_OU_AND_CHILDREN_NA = 'ou_and_children_na'
|
ENTITY_OU_AND_CHILDREN_NA = 'ou_and_children_na'
|
||||||
ENTITY_OU_AND_CHILDREN_ARCH = 'ou_and_children_arch'
|
ENTITY_OU_AND_CHILDREN_ARCH = 'ou_and_children_arch'
|
||||||
ENTITY_OU_AND_CHILDREN_NS = 'ou_and_children_ns'
|
ENTITY_OU_AND_CHILDREN_NS = 'ou_and_children_ns'
|
||||||
ENTITY_OU_AND_CHILDREN_SUSP = 'ou_and_children_susp'
|
ENTITY_OU_AND_CHILDREN_SUSP = 'ou_and_children_susp'
|
||||||
|
ENTITY_OU_AND_CHILDREN_NS_SUSP = 'ou_and_children_ns_susp'
|
||||||
ENTITY_OU_AND_CHILDREN_NA_NS = 'ou_and_children_na_ns'
|
ENTITY_OU_AND_CHILDREN_NA_NS = 'ou_and_children_na_ns'
|
||||||
ENTITY_OUS = 'ous'
|
ENTITY_OUS = 'ous'
|
||||||
ENTITY_OUS_NA = 'ous_na'
|
ENTITY_OUS_NA = 'ous_na'
|
||||||
ENTITY_OUS_ARCH = 'ous_arch'
|
ENTITY_OUS_ARCH = 'ous_arch'
|
||||||
ENTITY_OUS_NS = 'ous_ns'
|
ENTITY_OUS_NS = 'ous_ns'
|
||||||
ENTITY_OUS_SUSP = 'ous_susp'
|
ENTITY_OUS_SUSP = 'ous_susp'
|
||||||
|
ENTITY_OUS_NS_SUSP = 'ous_ns_susp'
|
||||||
ENTITY_OUS_NA_NS = 'ous_na_ns'
|
ENTITY_OUS_NA_NS = 'ous_na_ns'
|
||||||
ENTITY_OUS_AND_CHILDREN = 'ous_and_children'
|
ENTITY_OUS_AND_CHILDREN = 'ous_and_children'
|
||||||
ENTITY_OUS_AND_CHILDREN_NA = 'ous_and_children_na'
|
ENTITY_OUS_AND_CHILDREN_NA = 'ous_and_children_na'
|
||||||
ENTITY_OUS_AND_CHILDREN_ARCH = 'ous_and_children_arch'
|
ENTITY_OUS_AND_CHILDREN_ARCH = 'ous_and_children_arch'
|
||||||
ENTITY_OUS_AND_CHILDREN_NS = 'ous_and_children_ns'
|
ENTITY_OUS_AND_CHILDREN_NS = 'ous_and_children_ns'
|
||||||
ENTITY_OUS_AND_CHILDREN_SUSP = 'ous_and_children_susp'
|
ENTITY_OUS_AND_CHILDREN_SUSP = 'ous_and_children_susp'
|
||||||
|
ENTITY_OUS_AND_CHILDREN_NS_SUSP = 'ous_and_children_ns_susp'
|
||||||
ENTITY_OUS_AND_CHILDREN_NA_NS = 'ous_and_children_na_ns'
|
ENTITY_OUS_AND_CHILDREN_NA_NS = 'ous_and_children_na_ns'
|
||||||
ENTITY_QUERIES = 'queries'
|
ENTITY_QUERIES = 'queries'
|
||||||
ENTITY_QUERY = 'query'
|
ENTITY_QUERY = 'query'
|
||||||
@@ -111,9 +119,9 @@ class GamCLArgs():
|
|||||||
ENTITY_USERS_ARCH = 'users_arch'
|
ENTITY_USERS_ARCH = 'users_arch'
|
||||||
ENTITY_USERS_NS = 'users_ns'
|
ENTITY_USERS_NS = 'users_ns'
|
||||||
ENTITY_USERS_SUSP = 'users_susp'
|
ENTITY_USERS_SUSP = 'users_susp'
|
||||||
|
ENTITY_USERS_NS_SUSP = 'users_ns_susp'
|
||||||
ENTITY_USERS_NA_NS = 'users_na_ns'
|
ENTITY_USERS_NA_NS = 'users_na_ns'
|
||||||
ENTITY_USERS_ARCH_OR_SUSP = 'users_arch_or_susp'
|
ENTITY_USERS_ARCH_OR_SUSP = 'users_arch_or_susp'
|
||||||
ENTITY_USERS_NS_SUSP = 'users_ns_susp'
|
|
||||||
ENTITY_USERS_AND_GUESTS = 'users_and_guests'
|
ENTITY_USERS_AND_GUESTS = 'users_and_guests'
|
||||||
ENTITY_USERS_AND_GUESTS_NS = 'users_and_guests_ns'
|
ENTITY_USERS_AND_GUESTS_NS = 'users_and_guests_ns'
|
||||||
ENTITY_USERS_AND_GUESTS_SUSP = 'users_and_guests_susp'
|
ENTITY_USERS_AND_GUESTS_SUSP = 'users_and_guests_susp'
|
||||||
@@ -158,6 +166,7 @@ class GamCLArgs():
|
|||||||
ENTITY_DOMAINS_ARCH,
|
ENTITY_DOMAINS_ARCH,
|
||||||
ENTITY_DOMAINS_NS,
|
ENTITY_DOMAINS_NS,
|
||||||
ENTITY_DOMAINS_SUSP,
|
ENTITY_DOMAINS_SUSP,
|
||||||
|
ENTITY_DOMAINS_NS_SUSP,
|
||||||
ENTITY_DOMAINS_NA_NS,
|
ENTITY_DOMAINS_NA_NS,
|
||||||
ENTITY_GROUP,
|
ENTITY_GROUP,
|
||||||
ENTITY_GROUP_INDE,
|
ENTITY_GROUP_INDE,
|
||||||
@@ -165,6 +174,7 @@ class GamCLArgs():
|
|||||||
ENTITY_GROUP_ARCH,
|
ENTITY_GROUP_ARCH,
|
||||||
ENTITY_GROUP_NS,
|
ENTITY_GROUP_NS,
|
||||||
ENTITY_GROUP_SUSP,
|
ENTITY_GROUP_SUSP,
|
||||||
|
ENTITY_GROUP_NS_SUSP,
|
||||||
ENTITY_GROUP_NA_NS,
|
ENTITY_GROUP_NA_NS,
|
||||||
ENTITY_GROUPS,
|
ENTITY_GROUPS,
|
||||||
ENTITY_GROUPS_INDE,
|
ENTITY_GROUPS_INDE,
|
||||||
@@ -172,12 +182,14 @@ class GamCLArgs():
|
|||||||
ENTITY_GROUPS_ARCH,
|
ENTITY_GROUPS_ARCH,
|
||||||
ENTITY_GROUPS_NS,
|
ENTITY_GROUPS_NS,
|
||||||
ENTITY_GROUPS_SUSP,
|
ENTITY_GROUPS_SUSP,
|
||||||
|
ENTITY_GROUPS_NS_SUSP,
|
||||||
ENTITY_GROUPS_NA_NS,
|
ENTITY_GROUPS_NA_NS,
|
||||||
ENTITY_GROUP_USERS,
|
ENTITY_GROUP_USERS,
|
||||||
ENTITY_GROUP_USERS_NA,
|
ENTITY_GROUP_USERS_NA,
|
||||||
ENTITY_GROUP_USERS_ARCH,
|
ENTITY_GROUP_USERS_ARCH,
|
||||||
ENTITY_GROUP_USERS_NS,
|
ENTITY_GROUP_USERS_NS,
|
||||||
ENTITY_GROUP_USERS_SUSP,
|
ENTITY_GROUP_USERS_SUSP,
|
||||||
|
ENTITY_GROUP_USERS_NS_SUSP,
|
||||||
ENTITY_GROUP_USERS_NA_NS,
|
ENTITY_GROUP_USERS_NA_NS,
|
||||||
ENTITY_GROUP_USERS_SELECT,
|
ENTITY_GROUP_USERS_SELECT,
|
||||||
ENTITY_LICENSES,
|
ENTITY_LICENSES,
|
||||||
@@ -187,24 +199,28 @@ class GamCLArgs():
|
|||||||
ENTITY_OU_ARCH,
|
ENTITY_OU_ARCH,
|
||||||
ENTITY_OU_NS,
|
ENTITY_OU_NS,
|
||||||
ENTITY_OU_SUSP,
|
ENTITY_OU_SUSP,
|
||||||
|
ENTITY_OU_NS_SUSP,
|
||||||
ENTITY_OU_NA_NS,
|
ENTITY_OU_NA_NS,
|
||||||
ENTITY_OU_AND_CHILDREN,
|
ENTITY_OU_AND_CHILDREN,
|
||||||
ENTITY_OU_AND_CHILDREN_NA,
|
ENTITY_OU_AND_CHILDREN_NA,
|
||||||
ENTITY_OU_AND_CHILDREN_ARCH,
|
ENTITY_OU_AND_CHILDREN_ARCH,
|
||||||
ENTITY_OU_AND_CHILDREN_NS,
|
ENTITY_OU_AND_CHILDREN_NS,
|
||||||
ENTITY_OU_AND_CHILDREN_SUSP,
|
ENTITY_OU_AND_CHILDREN_SUSP,
|
||||||
|
ENTITY_OU_AND_CHILDREN_NS_SUSP,
|
||||||
ENTITY_OU_AND_CHILDREN_NA_NS,
|
ENTITY_OU_AND_CHILDREN_NA_NS,
|
||||||
ENTITY_OUS,
|
ENTITY_OUS,
|
||||||
ENTITY_OUS_NA,
|
ENTITY_OUS_NA,
|
||||||
ENTITY_OUS_ARCH,
|
ENTITY_OUS_ARCH,
|
||||||
ENTITY_OUS_NS,
|
ENTITY_OUS_NS,
|
||||||
ENTITY_OUS_SUSP,
|
ENTITY_OUS_SUSP,
|
||||||
|
ENTITY_OUS_NS_SUSP,
|
||||||
ENTITY_OUS_NA_NS,
|
ENTITY_OUS_NA_NS,
|
||||||
ENTITY_OUS_AND_CHILDREN,
|
ENTITY_OUS_AND_CHILDREN,
|
||||||
ENTITY_OUS_AND_CHILDREN_NA,
|
ENTITY_OUS_AND_CHILDREN_NA,
|
||||||
ENTITY_OUS_AND_CHILDREN_ARCH,
|
ENTITY_OUS_AND_CHILDREN_ARCH,
|
||||||
ENTITY_OUS_AND_CHILDREN_NS,
|
ENTITY_OUS_AND_CHILDREN_NS,
|
||||||
ENTITY_OUS_AND_CHILDREN_SUSP,
|
ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||||
|
ENTITY_OUS_AND_CHILDREN_NS_SUSP,
|
||||||
ENTITY_OUS_AND_CHILDREN_NA_NS,
|
ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||||
ENTITY_QUERIES,
|
ENTITY_QUERIES,
|
||||||
ENTITY_QUERY,
|
ENTITY_QUERY,
|
||||||
@@ -286,48 +302,56 @@ class GamCLArgs():
|
|||||||
'org_arch': ENTITY_OU_ARCH,
|
'org_arch': ENTITY_OU_ARCH,
|
||||||
'org_ns': ENTITY_OU_NS,
|
'org_ns': ENTITY_OU_NS,
|
||||||
'org_susp': ENTITY_OU_SUSP,
|
'org_susp': ENTITY_OU_SUSP,
|
||||||
|
'org_ns_susp': ENTITY_OU_NS_SUSP,
|
||||||
'org_na_ns': ENTITY_OU_NA_NS,
|
'org_na_ns': ENTITY_OU_NA_NS,
|
||||||
'org_and_child': ENTITY_OU_AND_CHILDREN,
|
'org_and_child': ENTITY_OU_AND_CHILDREN,
|
||||||
'org_and_child_na': ENTITY_OU_AND_CHILDREN_NA,
|
'org_and_child_na': ENTITY_OU_AND_CHILDREN_NA,
|
||||||
'org_and_child_arch': ENTITY_OU_AND_CHILDREN_ARCH,
|
'org_and_child_arch': ENTITY_OU_AND_CHILDREN_ARCH,
|
||||||
'org_and_child_ns': ENTITY_OU_AND_CHILDREN_NS,
|
'org_and_child_ns': ENTITY_OU_AND_CHILDREN_NS,
|
||||||
'org_and_child_susp': ENTITY_OU_AND_CHILDREN_SUSP,
|
'org_and_child_susp': ENTITY_OU_AND_CHILDREN_SUSP,
|
||||||
|
'org_and_child_ns_susp': ENTITY_OU_AND_CHILDREN_NS_SUSP,
|
||||||
'org_and_child_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
|
'org_and_child_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
|
||||||
'org_and_children': ENTITY_OU_AND_CHILDREN,
|
'org_and_children': ENTITY_OU_AND_CHILDREN,
|
||||||
'org_and_children_na': ENTITY_OU_AND_CHILDREN_NA,
|
'org_and_children_na': ENTITY_OU_AND_CHILDREN_NA,
|
||||||
'org_and_children_arch': ENTITY_OU_AND_CHILDREN_ARCH,
|
'org_and_children_arch': ENTITY_OU_AND_CHILDREN_ARCH,
|
||||||
'org_and_children_ns': ENTITY_OU_AND_CHILDREN_NS,
|
'org_and_children_ns': ENTITY_OU_AND_CHILDREN_NS,
|
||||||
'org_and_children_susp': ENTITY_OU_AND_CHILDREN_SUSP,
|
'org_and_children_susp': ENTITY_OU_AND_CHILDREN_SUSP,
|
||||||
|
'org_and_children_ns_susp': ENTITY_OU_AND_CHILDREN_NS_SUSP,
|
||||||
'org_and_children_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
|
'org_and_children_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
|
||||||
'orgs': ENTITY_OUS,
|
'orgs': ENTITY_OUS,
|
||||||
'orgs_na': ENTITY_OUS_NA,
|
'orgs_na': ENTITY_OUS_NA,
|
||||||
'orgs_arch': ENTITY_OUS_ARCH,
|
'orgs_arch': ENTITY_OUS_ARCH,
|
||||||
'orgs_ns': ENTITY_OUS_NS,
|
'orgs_ns': ENTITY_OUS_NS,
|
||||||
'orgs_susp': ENTITY_OUS_SUSP,
|
'orgs_susp': ENTITY_OUS_SUSP,
|
||||||
|
'orgs_ns_susp': ENTITY_OUS_NS_SUSP,
|
||||||
'orgs_na_ns': ENTITY_OUS_NA_NS,
|
'orgs_na_ns': ENTITY_OUS_NA_NS,
|
||||||
'orgs_and_child': ENTITY_OUS_AND_CHILDREN,
|
'orgs_and_child': ENTITY_OUS_AND_CHILDREN,
|
||||||
'orgs_and_child_na': ENTITY_OUS_AND_CHILDREN_NA,
|
'orgs_and_child_na': ENTITY_OUS_AND_CHILDREN_NA,
|
||||||
'orgs_and_child_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
|
'orgs_and_child_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
|
||||||
'orgs_and_child_ns': ENTITY_OUS_AND_CHILDREN_NS,
|
'orgs_and_child_ns': ENTITY_OUS_AND_CHILDREN_NS,
|
||||||
'orgs_and_child_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
|
'orgs_and_child_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||||
|
'orgs_and_child_ns_susp': ENTITY_OUS_AND_CHILDREN_NS_SUSP,
|
||||||
'orgs_and_child_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
|
'orgs_and_child_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||||
'orgs_and_children': ENTITY_OUS_AND_CHILDREN,
|
'orgs_and_children': ENTITY_OUS_AND_CHILDREN,
|
||||||
'orgs_and_children_na': ENTITY_OUS_AND_CHILDREN_NA,
|
'orgs_and_children_na': ENTITY_OUS_AND_CHILDREN_NA,
|
||||||
'orgs_and_children_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
|
'orgs_and_children_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
|
||||||
'orgs_and_children_ns': ENTITY_OUS_AND_CHILDREN_NS,
|
'orgs_and_children_ns': ENTITY_OUS_AND_CHILDREN_NS,
|
||||||
'orgs_and_children_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
|
'orgs_and_children_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||||
|
'orgs_and_children_ns_susp': ENTITY_OUS_AND_CHILDREN_NS_SUSP,
|
||||||
'orgs_and_children_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
|
'orgs_and_children_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||||
'ou_and_child': ENTITY_OU_AND_CHILDREN,
|
'ou_and_child': ENTITY_OU_AND_CHILDREN,
|
||||||
'ou_and_child_na': ENTITY_OU_AND_CHILDREN_NA,
|
'ou_and_child_na': ENTITY_OU_AND_CHILDREN_NA,
|
||||||
'ou_and_child_arch': ENTITY_OU_AND_CHILDREN_ARCH,
|
'ou_and_child_arch': ENTITY_OU_AND_CHILDREN_ARCH,
|
||||||
'ou_and_child_ns': ENTITY_OU_AND_CHILDREN_NS,
|
'ou_and_child_ns': ENTITY_OU_AND_CHILDREN_NS,
|
||||||
'ou_and_child_susp': ENTITY_OU_AND_CHILDREN_SUSP,
|
'ou_and_child_susp': ENTITY_OU_AND_CHILDREN_SUSP,
|
||||||
|
'ou_and_child_ns_susp': ENTITY_OU_AND_CHILDREN_NS_SUSP,
|
||||||
'ou_and_child_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
|
'ou_and_child_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
|
||||||
'ous_and_child': ENTITY_OUS_AND_CHILDREN,
|
'ous_and_child': ENTITY_OUS_AND_CHILDREN,
|
||||||
'ous_and_child_na': ENTITY_OUS_AND_CHILDREN_NA,
|
'ous_and_child_na': ENTITY_OUS_AND_CHILDREN_NA,
|
||||||
'ous_and_child_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
|
'ous_and_child_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
|
||||||
'ous_and_child_ns': ENTITY_OUS_AND_CHILDREN_NS,
|
'ous_and_child_ns': ENTITY_OUS_AND_CHILDREN_NS,
|
||||||
'ous_and_child_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
|
'ous_and_child_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||||
|
'ous_and_child_ns_susp': ENTITY_OUS_AND_CHILDREN_NS_SUSP,
|
||||||
'ous_and_child_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
|
'ous_and_child_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||||
}
|
}
|
||||||
# CL entity source selectors
|
# CL entity source selectors
|
||||||
@@ -403,9 +427,9 @@ class GamCLArgs():
|
|||||||
ENTITY_USERS_ARCH,
|
ENTITY_USERS_ARCH,
|
||||||
ENTITY_USERS_NS,
|
ENTITY_USERS_NS,
|
||||||
ENTITY_USERS_SUSP,
|
ENTITY_USERS_SUSP,
|
||||||
|
ENTITY_USERS_NS_SUSP,
|
||||||
ENTITY_USERS_ARCH_OR_SUSP,
|
ENTITY_USERS_ARCH_OR_SUSP,
|
||||||
ENTITY_USERS_NA_NS,
|
ENTITY_USERS_NA_NS,
|
||||||
ENTITY_USERS_NS_SUSP,
|
|
||||||
ENTITY_USERS_AND_GUESTS,
|
ENTITY_USERS_AND_GUESTS,
|
||||||
ENTITY_USERS_AND_GUESTS_NS,
|
ENTITY_USERS_AND_GUESTS_NS,
|
||||||
ENTITY_USERS_AND_GUESTS_SUSP,
|
ENTITY_USERS_AND_GUESTS_SUSP,
|
||||||
@@ -422,9 +446,9 @@ class GamCLArgs():
|
|||||||
ENTITY_ALL_USERS_ARCH = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_ARCH
|
ENTITY_ALL_USERS_ARCH = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_ARCH
|
||||||
ENTITY_ALL_USERS_NS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NS
|
ENTITY_ALL_USERS_NS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NS
|
||||||
ENTITY_ALL_USERS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_SUSP
|
ENTITY_ALL_USERS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_SUSP
|
||||||
|
ENTITY_ALL_USERS_NS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NS_SUSP
|
||||||
ENTITY_ALL_USERS_NA_NS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NA_NS
|
ENTITY_ALL_USERS_NA_NS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NA_NS
|
||||||
ENTITY_ALL_USERS_ARCH_OR_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_ARCH_OR_SUSP
|
ENTITY_ALL_USERS_ARCH_OR_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_ARCH_OR_SUSP
|
||||||
ENTITY_ALL_USERS_NS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NS_SUSP
|
|
||||||
ENTITY_ALL_USERS_AND_GUESTS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_AND_GUESTS
|
ENTITY_ALL_USERS_AND_GUESTS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_AND_GUESTS
|
||||||
ENTITY_ALL_USERS_AND_GUESTS_NS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_AND_GUESTS_NS
|
ENTITY_ALL_USERS_AND_GUESTS_NS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_AND_GUESTS_NS
|
||||||
ENTITY_ALL_USERS_AND_GUESTS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_AND_GUESTS_SUSP
|
ENTITY_ALL_USERS_AND_GUESTS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_AND_GUESTS_SUSP
|
||||||
@@ -440,8 +464,8 @@ class GamCLArgs():
|
|||||||
ENTITY_ALL_USERS_ARCH,
|
ENTITY_ALL_USERS_ARCH,
|
||||||
ENTITY_ALL_USERS_NS,
|
ENTITY_ALL_USERS_NS,
|
||||||
ENTITY_ALL_USERS_SUSP,
|
ENTITY_ALL_USERS_SUSP,
|
||||||
ENTITY_ALL_USERS_NA_NS,
|
|
||||||
ENTITY_ALL_USERS_NS_SUSP,
|
ENTITY_ALL_USERS_NS_SUSP,
|
||||||
|
ENTITY_ALL_USERS_NA_NS,
|
||||||
ENTITY_ALL_USERS_AND_GUESTS,
|
ENTITY_ALL_USERS_AND_GUESTS,
|
||||||
ENTITY_ALL_USERS_AND_GUESTS_NS,
|
ENTITY_ALL_USERS_AND_GUESTS_NS,
|
||||||
ENTITY_ALL_USERS_AND_GUESTS_SUSP,
|
ENTITY_ALL_USERS_AND_GUESTS_SUSP,
|
||||||
@@ -457,6 +481,7 @@ class GamCLArgs():
|
|||||||
ENTITY_DOMAINS_ARCH,
|
ENTITY_DOMAINS_ARCH,
|
||||||
ENTITY_DOMAINS_NS,
|
ENTITY_DOMAINS_NS,
|
||||||
ENTITY_DOMAINS_SUSP,
|
ENTITY_DOMAINS_SUSP,
|
||||||
|
ENTITY_DOMAINS_NS_SUSP,
|
||||||
ENTITY_DOMAINS_NA_NS,
|
ENTITY_DOMAINS_NA_NS,
|
||||||
}
|
}
|
||||||
GROUP_ENTITY_TYPES = {
|
GROUP_ENTITY_TYPES = {
|
||||||
@@ -465,6 +490,7 @@ class GamCLArgs():
|
|||||||
ENTITY_GROUP_ARCH,
|
ENTITY_GROUP_ARCH,
|
||||||
ENTITY_GROUP_NS,
|
ENTITY_GROUP_NS,
|
||||||
ENTITY_GROUP_SUSP,
|
ENTITY_GROUP_SUSP,
|
||||||
|
ENTITY_GROUP_NS_SUSP,
|
||||||
ENTITY_GROUP_NA_NS,
|
ENTITY_GROUP_NA_NS,
|
||||||
ENTITY_GROUP_INDE,
|
ENTITY_GROUP_INDE,
|
||||||
}
|
}
|
||||||
@@ -474,6 +500,7 @@ class GamCLArgs():
|
|||||||
ENTITY_GROUPS_ARCH,
|
ENTITY_GROUPS_ARCH,
|
||||||
ENTITY_GROUPS_NS,
|
ENTITY_GROUPS_NS,
|
||||||
ENTITY_GROUPS_SUSP,
|
ENTITY_GROUPS_SUSP,
|
||||||
|
ENTITY_GROUPS_NS_SUSP,
|
||||||
ENTITY_GROUPS_NA_NS,
|
ENTITY_GROUPS_NA_NS,
|
||||||
ENTITY_GROUPS_INDE,
|
ENTITY_GROUPS_INDE,
|
||||||
}
|
}
|
||||||
@@ -483,6 +510,7 @@ class GamCLArgs():
|
|||||||
ENTITY_GROUP_USERS_ARCH,
|
ENTITY_GROUP_USERS_ARCH,
|
||||||
ENTITY_GROUP_USERS_NS,
|
ENTITY_GROUP_USERS_NS,
|
||||||
ENTITY_GROUP_USERS_SUSP,
|
ENTITY_GROUP_USERS_SUSP,
|
||||||
|
ENTITY_GROUP_USERS_NS_SUSP,
|
||||||
ENTITY_GROUP_USERS_NA_NS,
|
ENTITY_GROUP_USERS_NA_NS,
|
||||||
ENTITY_GROUP_USERS_SELECT,
|
ENTITY_GROUP_USERS_SELECT,
|
||||||
}
|
}
|
||||||
@@ -497,6 +525,8 @@ class GamCLArgs():
|
|||||||
ENTITY_OU_AND_CHILDREN_NS,
|
ENTITY_OU_AND_CHILDREN_NS,
|
||||||
ENTITY_OU_SUSP,
|
ENTITY_OU_SUSP,
|
||||||
ENTITY_OU_AND_CHILDREN_SUSP,
|
ENTITY_OU_AND_CHILDREN_SUSP,
|
||||||
|
ENTITY_OU_NS_SUSP,
|
||||||
|
ENTITY_OU_AND_CHILDREN_NS_SUSP,
|
||||||
ENTITY_OU_NA_NS,
|
ENTITY_OU_NA_NS,
|
||||||
ENTITY_OU_AND_CHILDREN_NA_NS,
|
ENTITY_OU_AND_CHILDREN_NA_NS,
|
||||||
}
|
}
|
||||||
@@ -511,6 +541,8 @@ class GamCLArgs():
|
|||||||
ENTITY_OUS_AND_CHILDREN_NS,
|
ENTITY_OUS_AND_CHILDREN_NS,
|
||||||
ENTITY_OUS_SUSP,
|
ENTITY_OUS_SUSP,
|
||||||
ENTITY_OUS_AND_CHILDREN_SUSP,
|
ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||||
|
ENTITY_OUS_NS_SUSP,
|
||||||
|
ENTITY_OUS_AND_CHILDREN_NS_SUSP,
|
||||||
ENTITY_OUS_NA_NS,
|
ENTITY_OUS_NA_NS,
|
||||||
ENTITY_OUS_AND_CHILDREN_NA_NS,
|
ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||||
}
|
}
|
||||||
@@ -525,6 +557,8 @@ class GamCLArgs():
|
|||||||
ENTITY_OUS_NS,
|
ENTITY_OUS_NS,
|
||||||
ENTITY_OU_SUSP,
|
ENTITY_OU_SUSP,
|
||||||
ENTITY_OUS_SUSP,
|
ENTITY_OUS_SUSP,
|
||||||
|
ENTITY_OU_NS_SUSP,
|
||||||
|
ENTITY_OUS_NS_SUSP,
|
||||||
ENTITY_OU_NA_NS,
|
ENTITY_OU_NA_NS,
|
||||||
ENTITY_OUS_NA_NS,
|
ENTITY_OUS_NA_NS,
|
||||||
}
|
}
|
||||||
@@ -588,6 +622,7 @@ class GamCLArgs():
|
|||||||
ENTITY_DOMAINS_ARCH: 'isArchived=True',
|
ENTITY_DOMAINS_ARCH: 'isArchived=True',
|
||||||
ENTITY_DOMAINS_NS: 'isSuspended=False',
|
ENTITY_DOMAINS_NS: 'isSuspended=False',
|
||||||
ENTITY_DOMAINS_SUSP: 'isSuspended=True',
|
ENTITY_DOMAINS_SUSP: 'isSuspended=True',
|
||||||
|
ENTITY_DOMAINS_NS_SUSP: None,
|
||||||
ENTITY_DOMAINS_NA_NS: 'isArchived=False isSuspended=False',
|
ENTITY_DOMAINS_NA_NS: 'isArchived=False isSuspended=False',
|
||||||
}
|
}
|
||||||
GROUPS_QUERY_MAP = { #(isArchived, isSuspended)
|
GROUPS_QUERY_MAP = { #(isArchived, isSuspended)
|
||||||
@@ -599,6 +634,8 @@ class GamCLArgs():
|
|||||||
ENTITY_GROUPS_NS: (None, False),
|
ENTITY_GROUPS_NS: (None, False),
|
||||||
ENTITY_GROUP_SUSP: (None, True),
|
ENTITY_GROUP_SUSP: (None, True),
|
||||||
ENTITY_GROUPS_SUSP: (None, True),
|
ENTITY_GROUPS_SUSP: (None, True),
|
||||||
|
ENTITY_GROUP_NS_SUSP: (None, None),
|
||||||
|
ENTITY_GROUPS_NS_SUSP: (None, None),
|
||||||
ENTITY_GROUP_NA_NS: (False, False),
|
ENTITY_GROUP_NA_NS: (False, False),
|
||||||
ENTITY_GROUPS_NA_NS: (False, False),
|
ENTITY_GROUPS_NA_NS: (False, False),
|
||||||
}
|
}
|
||||||
@@ -607,6 +644,7 @@ class GamCLArgs():
|
|||||||
ENTITY_GROUP_USERS_ARCH: (True, None),
|
ENTITY_GROUP_USERS_ARCH: (True, None),
|
||||||
ENTITY_GROUP_USERS_NS: (None, False),
|
ENTITY_GROUP_USERS_NS: (None, False),
|
||||||
ENTITY_GROUP_USERS_SUSP: (None, True),
|
ENTITY_GROUP_USERS_SUSP: (None, True),
|
||||||
|
ENTITY_GROUP_USERS_NS_SUSP: (None, None),
|
||||||
ENTITY_GROUP_USERS_NA_NS: (False, False),
|
ENTITY_GROUP_USERS_NA_NS: (False, False),
|
||||||
}
|
}
|
||||||
OU_QUERY_MAP = { #(isArchived, isSuspended)
|
OU_QUERY_MAP = { #(isArchived, isSuspended)
|
||||||
@@ -626,6 +664,10 @@ class GamCLArgs():
|
|||||||
ENTITY_OUS_SUSP: (None, True),
|
ENTITY_OUS_SUSP: (None, True),
|
||||||
ENTITY_OU_AND_CHILDREN_SUSP: (None, True),
|
ENTITY_OU_AND_CHILDREN_SUSP: (None, True),
|
||||||
ENTITY_OUS_AND_CHILDREN_SUSP: (None, True),
|
ENTITY_OUS_AND_CHILDREN_SUSP: (None, True),
|
||||||
|
ENTITY_OU_NS_SUSP: (None, None),
|
||||||
|
ENTITY_OUS_NS_SUSP: (None, None),
|
||||||
|
ENTITY_OU_AND_CHILDREN_NS_SUSP: (None, None),
|
||||||
|
ENTITY_OUS_AND_CHILDREN_NS_SUSP: (None, None),
|
||||||
ENTITY_OU_NA_NS: (False, False),
|
ENTITY_OU_NA_NS: (False, False),
|
||||||
ENTITY_OUS_NA_NS: (False, False),
|
ENTITY_OUS_NA_NS: (False, False),
|
||||||
ENTITY_OU_AND_CHILDREN_NA_NS: (False, False),
|
ENTITY_OU_AND_CHILDREN_NA_NS: (False, False),
|
||||||
@@ -667,6 +709,7 @@ class GamCLArgs():
|
|||||||
ENTITY_DOMAINS_ARCH,
|
ENTITY_DOMAINS_ARCH,
|
||||||
ENTITY_DOMAINS_NS,
|
ENTITY_DOMAINS_NS,
|
||||||
ENTITY_DOMAINS_SUSP,
|
ENTITY_DOMAINS_SUSP,
|
||||||
|
ENTITY_DOMAINS_NS_SUSP,
|
||||||
ENTITY_DOMAINS_NA_NS,
|
ENTITY_DOMAINS_NA_NS,
|
||||||
ENTITY_GROUPS,
|
ENTITY_GROUPS,
|
||||||
ENTITY_GROUPS_INDE,
|
ENTITY_GROUPS_INDE,
|
||||||
@@ -674,12 +717,14 @@ class GamCLArgs():
|
|||||||
ENTITY_GROUPS_ARCH,
|
ENTITY_GROUPS_ARCH,
|
||||||
ENTITY_GROUPS_NS,
|
ENTITY_GROUPS_NS,
|
||||||
ENTITY_GROUPS_SUSP,
|
ENTITY_GROUPS_SUSP,
|
||||||
|
ENTITY_GROUPS_NS_SUSP,
|
||||||
ENTITY_GROUPS_NA_NS,
|
ENTITY_GROUPS_NA_NS,
|
||||||
ENTITY_GROUP_USERS,
|
ENTITY_GROUP_USERS,
|
||||||
ENTITY_GROUP_USERS_NA,
|
ENTITY_GROUP_USERS_NA,
|
||||||
ENTITY_GROUP_USERS_ARCH,
|
ENTITY_GROUP_USERS_ARCH,
|
||||||
ENTITY_GROUP_USERS_NS,
|
ENTITY_GROUP_USERS_NS,
|
||||||
ENTITY_GROUP_USERS_SUSP,
|
ENTITY_GROUP_USERS_SUSP,
|
||||||
|
ENTITY_GROUP_USERS_NS_SUSP,
|
||||||
ENTITY_GROUP_USERS_NA_NS,
|
ENTITY_GROUP_USERS_NA_NS,
|
||||||
ENTITY_GROUP_USERS_SELECT,
|
ENTITY_GROUP_USERS_SELECT,
|
||||||
ENTITY_OUS,
|
ENTITY_OUS,
|
||||||
@@ -687,12 +732,14 @@ class GamCLArgs():
|
|||||||
ENTITY_OUS_ARCH,
|
ENTITY_OUS_ARCH,
|
||||||
ENTITY_OUS_NS,
|
ENTITY_OUS_NS,
|
||||||
ENTITY_OUS_SUSP,
|
ENTITY_OUS_SUSP,
|
||||||
|
ENTITY_OUS_NS_SUSP,
|
||||||
ENTITY_OUS_NA_NS,
|
ENTITY_OUS_NA_NS,
|
||||||
ENTITY_OUS_AND_CHILDREN,
|
ENTITY_OUS_AND_CHILDREN,
|
||||||
ENTITY_OUS_AND_CHILDREN_NA,
|
ENTITY_OUS_AND_CHILDREN_NA,
|
||||||
ENTITY_OUS_AND_CHILDREN_ARCH,
|
ENTITY_OUS_AND_CHILDREN_ARCH,
|
||||||
ENTITY_OUS_AND_CHILDREN_NS,
|
ENTITY_OUS_AND_CHILDREN_NS,
|
||||||
ENTITY_OUS_AND_CHILDREN_SUSP,
|
ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||||
|
ENTITY_OUS_AND_CHILDREN_NS_SUSP,
|
||||||
ENTITY_OUS_AND_CHILDREN_NA_NS,
|
ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||||
ENTITY_COURSEPARTICIPANTS,
|
ENTITY_COURSEPARTICIPANTS,
|
||||||
ENTITY_STUDENTS,
|
ENTITY_STUDENTS,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright (C) 2025 Ross Scroggs All Rights Reserved.
|
# Copyright (C) 2026 Ross Scroggs All Rights Reserved.
|
||||||
#
|
#
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
@@ -312,6 +312,7 @@ INVALID_ALIAS = 'Invalid Alias'
|
|||||||
INVALID_ATTENDEE_CHANGE = 'Invalid attendee change "{0}"'
|
INVALID_ATTENDEE_CHANGE = 'Invalid attendee change "{0}"'
|
||||||
INVALID_CHARSET = 'Invalid charset "{0}"'
|
INVALID_CHARSET = 'Invalid charset "{0}"'
|
||||||
INVALID_DATE_TIME_RANGE = '{0} {1} must be greater than/equal to {2} {3}'
|
INVALID_DATE_TIME_RANGE = '{0} {1} must be greater than/equal to {2} {3}'
|
||||||
|
INVALID_DEVICE_QUERY = 'Invalid {0} query "{1}"; it must be if the form "field:value" and must not contain a "?"'
|
||||||
INVALID_EMOJI_NAME = '{0} does not match pattern :[0-9a-z_-]:'
|
INVALID_EMOJI_NAME = '{0} does not match pattern :[0-9a-z_-]:'
|
||||||
INVALID_ENTITY = 'Invalid {0}, {1}'
|
INVALID_ENTITY = 'Invalid {0}, {1}'
|
||||||
INVALID_EVENT_TIMERANGE = '{0} {1} must be less than {2}'
|
INVALID_EVENT_TIMERANGE = '{0} {1} must be less than {2}'
|
||||||
@@ -474,6 +475,7 @@ REASON_ONLY_VALID_WITH_CONTENTRESTRICTIONS_READONLY_TRUE = 'reason only valid wi
|
|||||||
REAUTHENTICATION_IS_NEEDED = 'Reauthentication is needed, please run\n\ngam oauth create'
|
REAUTHENTICATION_IS_NEEDED = 'Reauthentication is needed, please run\n\ngam oauth create'
|
||||||
RECOMMEND_RUNNING_GAM_ROTATE_SAKEY = 'Recommend running "gam rotate sakey" to get a new key\n'
|
RECOMMEND_RUNNING_GAM_ROTATE_SAKEY = 'Recommend running "gam rotate sakey" to get a new key\n'
|
||||||
REFUSING_TO_DEPROVISION_DEVICES = 'Refusing to deprovision {0} devices because acknowledge_device_touch_requirement not specified.\nDeprovisioning a device means the device will have to be physically wiped and re-enrolled to be managed by your domain again.\nThis requires physical access to the device and is very time consuming to perform for each device.\nPlease add "acknowledge_device_touch_requirement" to the GAM command if you understand this and wish to proceed with the deprovision.\nPlease also be aware that deprovisioning can have an effect on your device license count.\nSee https://support.google.com/chrome/a/answer/3523633 for full details.'
|
REFUSING_TO_DEPROVISION_DEVICES = 'Refusing to deprovision {0} devices because acknowledge_device_touch_requirement not specified.\nDeprovisioning a device means the device will have to be physically wiped and re-enrolled to be managed by your domain again.\nThis requires physical access to the device and is very time consuming to perform for each device.\nPlease add "acknowledge_device_touch_requirement" to the GAM command if you understand this and wish to proceed with the deprovision.\nPlease also be aware that deprovisioning can have an effect on your device license count.\nSee https://support.google.com/chrome/a/answer/3523633 for full details.'
|
||||||
|
REFUSING_TO_DEPROVISION_N_DEVICES = 'Refusing to deprovision {0} devices due to maxtodepov {1}.\nSpecify "maxtodeprov 0" to deprovision all {0} devices'
|
||||||
REPLY_TO_CUSTOM_REQUIRES_EMAIL_ADDRESS = 'replyto REPLY_TO_CUSTOM requires customReplyTo <EmailAddress>'
|
REPLY_TO_CUSTOM_REQUIRES_EMAIL_ADDRESS = 'replyto REPLY_TO_CUSTOM requires customReplyTo <EmailAddress>'
|
||||||
REQUEST_COMPLETED_NO_FILES = 'Request completed but no results/files were returned, try requesting again'
|
REQUEST_COMPLETED_NO_FILES = 'Request completed but no results/files were returned, try requesting again'
|
||||||
REQUEST_NOT_COMPLETE = 'Request needs to be completed before downloading, current status is: {0}'
|
REQUEST_NOT_COMPLETE = 'Request needs to be completed before downloading, current status is: {0}'
|
||||||
|
|||||||
@@ -315,6 +315,9 @@ You can optionally specify the type of service account key with `algorithm|local
|
|||||||
Use `nokey` if you do not want a service account key created for the project.
|
Use `nokey` if you do not want a service account key created for the project.
|
||||||
|
|
||||||
## Use an existing project for GAM authorization
|
## Use an existing project for GAM authorization
|
||||||
|
|
||||||
|
To use the same GAM project on multiple computers, see: [GAM Configuration](Multiple-Computers)
|
||||||
|
|
||||||
Use an existing project to create and download two files: `client_secrets.json` for the Client and `oauth2service.json` for the Service Account.
|
Use an existing project to create and download two files: `client_secrets.json` for the Client and `oauth2service.json` for the Service Account.
|
||||||
|
|
||||||
### Default values
|
### Default values
|
||||||
|
|||||||
@@ -456,9 +456,9 @@
|
|||||||
See: https://cloud.google.com/access-context-manager/docs/custom-access-level-spec
|
See: https://cloud.google.com/access-context-manager/docs/custom-access-level-spec
|
||||||
<QueryContact> ::= <String>
|
<QueryContact> ::= <String>
|
||||||
See: https://developers.google.com/google-apps/contacts/v3/reference#contacts-query-parameters-reference
|
See: https://developers.google.com/google-apps/contacts/v3/reference#contacts-query-parameters-reference
|
||||||
<QueryCrOS> ::= <String>
|
<QueryCrOS> ::= <String>:<String>
|
||||||
See: https://support.google.com/chrome/a/answer/1698333
|
See: https://support.google.com/chrome/a/answer/1698333
|
||||||
<QueryDevice> ::= <String>
|
<QueryDevice> ::= <String>:<String>
|
||||||
See: https://support.google.com/a/answer/7549103
|
See: https://support.google.com/a/answer/7549103
|
||||||
<QueryDriveFile> ::= <String>
|
<QueryDriveFile> ::= <String>
|
||||||
See: https://developers.google.com/drive/api/v3/search-files
|
See: https://developers.google.com/drive/api/v3/search-files
|
||||||
@@ -471,7 +471,7 @@
|
|||||||
<QueryItem> ::= <UniqueID>|<String>
|
<QueryItem> ::= <UniqueID>|<String>
|
||||||
<QueryMemberRestrictions> ::= <String>
|
<QueryMemberRestrictions> ::= <String>
|
||||||
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
|
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
|
||||||
<QueryMobile> ::= <String>
|
<QueryMobile> ::= <String>:<String>
|
||||||
See: https://support.google.com/a/answer/7549103
|
See: https://support.google.com/a/answer/7549103
|
||||||
<QueryTeamDrive> ::= <String>
|
<QueryTeamDrive> ::= <String>
|
||||||
See: https://developers.google.com/drive/api/v3/search-parameters
|
See: https://developers.google.com/drive/api/v3/search-parameters
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ gam oauth create
|
|||||||
|
|
||||||
```
|
```
|
||||||
<OrgUnitPath> ::= /|(/<String)+
|
<OrgUnitPath> ::= /|(/<String)+
|
||||||
<QueryCrOS> ::= <String> See: https://support.google.com/chrome/a/answer/1698333
|
<QueryCrOS> ::= <String>:<String>
|
||||||
|
See: https://support.google.com/chrome/a/answer/1698333
|
||||||
<CommandID> ::= <String>
|
<CommandID> ::= <String>
|
||||||
<CrOSID> ::= <String>
|
<CrOSID> ::= <String>
|
||||||
<CrOSIDList> ::= "<CrOSID>(,<CrOSID>)*"
|
<CrOSIDList> ::= "<CrOSID>(,<CrOSID>)*"
|
||||||
@@ -409,11 +410,13 @@ gam update ou csvkmd cros.csv keyfield OU datafield deviceId add croscsvdata dev
|
|||||||
reenable
|
reenable
|
||||||
|
|
||||||
gam <CrOSTypeEntity> update action <CrOSAction> [acknowledge_device_touch_requirement]
|
gam <CrOSTypeEntity> update action <CrOSAction> [acknowledge_device_touch_requirement]
|
||||||
[actionbatchsize <Integer>]
|
[actionbatchsize <Integer>] [maxtodeprov <Integer>]
|
||||||
```
|
```
|
||||||
ChromeOS devices are now processed in batches.
|
ChromeOS devices are now processed in batches.
|
||||||
The batch size defaults to 10, the `actionbatchsize <Integer>` option can be used to set a batch size between 10 and 250.
|
The batch size defaults to 10, the `actionbatchsize <Integer>` option can be used to set a batch size between 10 and 250.
|
||||||
|
|
||||||
|
### Deprovisioning
|
||||||
|
|
||||||
As deprovisioning ChromeOS devices is not reversible, you must enter `acknowledge_device_touch_requirement`
|
As deprovisioning ChromeOS devices is not reversible, you must enter `acknowledge_device_touch_requirement`
|
||||||
when `<CrOSAction>` is `deprovision_same_model_replace`, `deprovision_different_model_replace`,
|
when `<CrOSAction>` is `deprovision_same_model_replace`, `deprovision_different_model_replace`,
|
||||||
`deprovision_retiring_device` or `deprovision_upgrade_transfer`.
|
`deprovision_retiring_device` or `deprovision_upgrade_transfer`.
|
||||||
@@ -424,6 +427,20 @@ each device. Please also be aware that deprovisioning can have an effect on your
|
|||||||
|
|
||||||
See https://support.google.com/chrome/a/answer/3523633 for full details.
|
See https://support.google.com/chrome/a/answer/3523633 for full details.
|
||||||
|
|
||||||
|
Prior to version 7.43.05, all devices in `<CrOSEntity>` would be deprovisioned. When `<CrOSEntity>`
|
||||||
|
was derived from an OU, this was desirable. However, if `<CrOSEntity>` was derived from a query,
|
||||||
|
more devices than desired may have been deprovisioned. In version 7.43.05 and higher,
|
||||||
|
GAM defaults to not deprovisioning devices if the number of devices exceeds one.
|
||||||
|
|
||||||
|
The option `max_to_deprov <Integer>` can be used to verify the number of devices to be deprovisioned;
|
||||||
|
no deprovisions are processed if the number of devices in `<CrOSEntity>` exceeds `<Integer>`;
|
||||||
|
the default value is one; set `<Number>` to 0 for no limit.
|
||||||
|
|
||||||
|
When `<CrOSEntity>` is derived from an OU, set `max_to_deprov 0` and all devices will be deprovisioned.
|
||||||
|
|
||||||
|
When `<CrOSEntity>` is derived from a query, e.g., `cros_sn <SerialNumber>`, the default `max_to_deprov 1`
|
||||||
|
protects you from accidentally deprovisioning more devices than desired.
|
||||||
|
|
||||||
## Send remote commands to ChromeOS devices
|
## Send remote commands to ChromeOS devices
|
||||||
Thanks to Jay for most of the following.
|
Thanks to Jay for most of the following.
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ Use this table to filter/query for specific device types:
|
|||||||
```
|
```
|
||||||
<AssetTag> ::= <String>
|
<AssetTag> ::= <String>
|
||||||
<AssetTagList> ::= "<AssetTag>(,<AssetTag>)*"
|
<AssetTagList> ::= "<AssetTag>(,<AssetTag>)*"
|
||||||
<QueryDevice> ::= <String>
|
<QueryDevice> ::= <String>:<String>
|
||||||
See: https://support.google.com/a/answer/7549103
|
See: https://support.google.com/a/answer/7549103
|
||||||
<QueryDeviceList> ::= "<QueryDevice>(,<QueryDevice>)*"
|
<QueryDeviceList> ::= "<QueryDevice>(,<QueryDevice>)*"
|
||||||
<DeviceID> ::= devices/<String>
|
<DeviceID> ::= devices/<String>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ gam info domain [<DomainName>]
|
|||||||
gam show domains
|
gam show domains
|
||||||
[formatjson]
|
[formatjson]
|
||||||
```
|
```
|
||||||
For `info`, if `<DomainName>` is omitted, information about the primary domain will be displayed.
|
For `info`, if `<DomainName>` is omitted, customer information about the primary domain will be displayed.
|
||||||
|
|
||||||
By default, Gam displays the information as an indented list of keys and values.
|
By default, Gam displays the information as an indented list of keys and values.
|
||||||
* `formatjson` - Display the fields in JSON format.
|
* `formatjson` - Display the fields in JSON format.
|
||||||
|
|||||||
@@ -10,6 +10,56 @@ 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.43.07
|
||||||
|
|
||||||
|
Improved validation of `<QueryCrOS>`, `<QueryDevice>` and `<QueryMobile>`.
|
||||||
|
|
||||||
|
### 7.43.06
|
||||||
|
|
||||||
|
Updated commands that use `<QueryCrOS>`, `<QueryDevice>` or `<QueryMobile>` to validate
|
||||||
|
that it is of the form `field:value` and that `value` does not contain a '?'.
|
||||||
|
Without validation, Google can return many more devices than are expected.
|
||||||
|
|
||||||
|
### 7.43.05
|
||||||
|
|
||||||
|
Added option `matchfield attendeesorganizer <Boolean> <EmailAddressEntity>` to `<EventMatchProperty>`
|
||||||
|
that is used in commands that process events. The match is true if all of the addresses in `<EmailAddressEntity>`
|
||||||
|
are present as attendees in the event and are an organizer or not based on `<Boolean>`.
|
||||||
|
|
||||||
|
Added option `max_to_deprov <Integer>` to `gam update cros <CrOSEntity> action <CrOSAction>`
|
||||||
|
that is used when `<CrOSAction>` is any of the following:
|
||||||
|
```
|
||||||
|
deprovision_different_model_replace|
|
||||||
|
deprovision_different_model_replacement|
|
||||||
|
deprovision_retiring_device|
|
||||||
|
deprovision_same_model_replace|
|
||||||
|
deprovision_same_model_replacement|
|
||||||
|
deprovision_upgrade_transfer
|
||||||
|
```
|
||||||
|
`max_to_deprov <Integer>` - No deprovisions are processed if the number of devices in `<CrOSEntity>` exceeds `<Integer>`;
|
||||||
|
the default value is one; set `<Integer>` to 0 for no limit.
|
||||||
|
|
||||||
|
### 7.43.04
|
||||||
|
|
||||||
|
Added option `include_suspended_zeros [<Boolean>]` to `gam print vaultcounts` that causes
|
||||||
|
GAM to generate zero count lines for suspended users with zero items as well as non-suspended users.
|
||||||
|
|
||||||
|
### 7.43.03
|
||||||
|
|
||||||
|
Added option `parentpathonly [<Boolean>]` to the following commands that causes GAM
|
||||||
|
to display only the parent folder names when displaying the path to a file.
|
||||||
|
```
|
||||||
|
gam <UserTypeEntity> info drivefile ... filepath|fullpath
|
||||||
|
gam <UserTypeEntity> show fileinfo ... filepath|fullpath
|
||||||
|
gam <UserTypeEntity> print|show filepath
|
||||||
|
gam <UserTypeEntity> print filelist ... filepath|fullpath
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.43.02
|
||||||
|
|
||||||
|
Added option `maxactivities <Integer>` to `gam <UserTypeEntity> print driveactivity` to limit
|
||||||
|
the number of activities displayed; the default is 0, no limit.
|
||||||
|
|
||||||
### 7.43.01
|
### 7.43.01
|
||||||
|
|
||||||
Updated `gam info user` and `gam print users` to display guest user attributes: `isGuestUser, guestAccountInfo`
|
Updated `gam info user` and `gam print users` to display guest user attributes: `isGuestUser, guestAccountInfo`
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ writes the credentials into the file oauth2.txt.
|
|||||||
```
|
```
|
||||||
gamteam@server:/Users/gamteam$ rm -f /Users/gamteam/GAMConfig/oauth2.txt
|
gamteam@server:/Users/gamteam$ rm -f /Users/gamteam/GAMConfig/oauth2.txt
|
||||||
gamteam@server:/Users/gamteam$ gam version
|
gamteam@server:/Users/gamteam$ gam version
|
||||||
GAM 7.43.01 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.43.07 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.4 64-bit final
|
Python 3.14.4 64-bit final
|
||||||
macOS Tahoe 26.4.1 arm64
|
macOS Tahoe 26.4.1 arm64
|
||||||
@@ -1034,7 +1034,7 @@ writes the credentials into the file oauth2.txt.
|
|||||||
```
|
```
|
||||||
C:\>del C:\GAMConfig\oauth2.txt
|
C:\>del C:\GAMConfig\oauth2.txt
|
||||||
C:\>gam version
|
C:\>gam version
|
||||||
GAM 7.43.01 - https://github.com/GAM-team/GAM - pythonsource
|
GAM 7.43.07 - https://github.com/GAM-team/GAM - pythonsource
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.4 64-bit final
|
Python 3.14.4 64-bit final
|
||||||
Windows 11 10.0.26200 AMD64
|
Windows 11 10.0.26200 AMD64
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
## Definitions
|
## Definitions
|
||||||
```
|
```
|
||||||
<QueryMobile> ::= <String>
|
<QueryMobile> ::= <String>:<String>
|
||||||
See: https://support.google.com/a/answer/7549103
|
See: https://support.google.com/a/answer/7549103
|
||||||
<QueryMobileList> ::= "<QueryMobile>(,<QueryMobile>)*"
|
<QueryMobileList> ::= "<QueryMobile>(,<QueryMobile>)*"
|
||||||
<ResourceID> ::= <String>
|
<ResourceID> ::= <String>
|
||||||
|
|||||||
@@ -277,6 +277,7 @@
|
|||||||
|
|
||||||
<EventMatchProperty> ::=
|
<EventMatchProperty> ::=
|
||||||
(matchfield attendees <EmailAddressEntity>)|
|
(matchfield attendees <EmailAddressEntity>)|
|
||||||
|
(matchfield attendeesorganizer <Boolean> <EmailAddressEntity>)|
|
||||||
(matchfield attendeesonlydomainlist <DomainNameList>)|
|
(matchfield attendeesonlydomainlist <DomainNameList>)|
|
||||||
(matchfield attendeesdomainlist <DomainNameList>)|
|
(matchfield attendeesdomainlist <DomainNameList>)|
|
||||||
(matchfield attendeesnotdomainlist <DomainNameList>)|
|
(matchfield attendeesnotdomainlist <DomainNameList>)|
|
||||||
@@ -460,8 +461,11 @@ The Google Calendar API processes `<EventSelectProperty>*`; you may specify none
|
|||||||
* `singleevents` - Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves
|
* `singleevents` - Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves
|
||||||
* `updatedmin <Time>` - Lower bound for an event's last modification time (as a RFC3339 timestamp) to filter by. When specified, entries deleted since this time will always be included regardless of showdeletedevents
|
* `updatedmin <Time>` - Lower bound for an event's last modification time (as a RFC3339 timestamp) to filter by. When specified, entries deleted since this time will always be included regardless of showdeletedevents
|
||||||
|
|
||||||
GAM processes `<EventMatchProperty>*`; you may specify none or multiple properties.
|
GAM processes `<EventMatchProperty>*`
|
||||||
* `matchfield attendees <EmailAddressEntity>` - All of the attendees in `<EmailAddressEntity>` must be present
|
; you may specify none or multiple properties.
|
||||||
|
* `matchfield attendees <EmailAddressEntity>` - All of the addresses in `<EmailAddressEntity>` must be present as attendees
|
||||||
|
* `matchfield attendeesorganizer <Boolean> <EmailAddressEntity>` - All of the addressed in `<EmailAddressEntity>` must be present
|
||||||
|
as attendees and are an organizer or not based on `<Boolean>`
|
||||||
* `matchfield attendeesonlydomainlist <DomainNameList>` - All attendee's email addresses must be in a domain in `<DomainNameList>`
|
* `matchfield attendeesonlydomainlist <DomainNameList>` - All attendee's email addresses must be in a domain in `<DomainNameList>`
|
||||||
* For example, this lets you look for events with all attendees in your internal domains. You should include `resource.calendar.google.com`
|
* For example, this lets you look for events with all attendees in your internal domains. You should include `resource.calendar.google.com`
|
||||||
in `<DomainNameList>` if the events use resources.
|
in `<DomainNameList>` if the events use resources.
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ gam <UserTypeEntity> print driveactivity [todrive <ToDriveAttributes>*]
|
|||||||
(query <QueryDriveFile>)]
|
(query <QueryDriveFile>)]
|
||||||
[([start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>])|(range <Date>|<Time> <Date)|<Time>|
|
[([start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>])|(range <Date>|<Time> <Date)|<Time>|
|
||||||
yesterday|today|thismonth|(previousmonths <Integer>)]
|
yesterday|today|thismonth|(previousmonths <Integer>)]
|
||||||
[action|actions [not] <DriveActivityActionList>]
|
[action|actions [not] <DriveActivityActionList>] [maxactivities <Number>]
|
||||||
[consolidationstrategy legacy|none]
|
[consolidationstrategy legacy|none]
|
||||||
[idmapfile <FileName>|(gsheet <UserGoogleSheet>) [charset <String>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]]
|
[idmapfile <FileName>|(gsheet <UserGoogleSheet>) [charset <String>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]]
|
||||||
[stripcrsfromname] [formatjson [quotechar <Character>]]
|
[stripcrsfromname] [formatjson [quotechar <Character>]]
|
||||||
@@ -99,6 +99,8 @@ Google does the filtering.
|
|||||||
* `action|actions <DriveActivityActionList>` - Only display activities with the specified actions; by default, all actions are displayed
|
* `action|actions <DriveActivityActionList>` - Only display activities with the specified actions; by default, all actions are displayed
|
||||||
* `action|actions not <DriveActivityActionList>` - Only display activities without the specified actions; by default, all actions are displayed
|
* `action|actions not <DriveActivityActionList>` - Only display activities without the specified actions; by default, all actions are displayed
|
||||||
|
|
||||||
|
You can limit the number of activities displayed with the `maxactivities <Number>; the default is 0, no limit.
|
||||||
|
|
||||||
The API only returns a permissionId and user name for each event but no user email address. To get an email address perform the
|
The API only returns a permissionId and user name for each event but no user email address. To get an email address perform the
|
||||||
following command to generate a file that contains the email address and permissionId for all users. You can substitute for `all users` if desired.
|
following command to generate a file that contains the email address and permissionId for all users. You can substitute for `all users` if desired.
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -528,7 +528,7 @@ There are two methods for moving a folder from a My Drive to a Shared Drive:
|
|||||||
* GAM
|
* GAM
|
||||||
* The Drive API doesn't allow moving a folder from a My Drive to a Shared Drive; GAM has to recreate the folders on the Shared Drive, thus changing their IDs
|
* The Drive API doesn't allow moving a folder from a My Drive to a Shared Drive; GAM has to recreate the folders on the Shared Drive, thus changing their IDs
|
||||||
* Files are simply moved from their existing My Drive folder to the recreated Shared Drive folder; their IDs do not change
|
* Files are simply moved from their existing My Drive folder to the recreated Shared Drive folder; their IDs do not change
|
||||||
* Files owmed by users outside of your domain can't be moved
|
* Files owned by users outside of your domain can't be moved
|
||||||
|
|
||||||
## Simple moves by changing parents
|
## Simple moves by changing parents
|
||||||
Use this command in the following cases:
|
Use this command in the following cases:
|
||||||
|
|||||||
@@ -425,7 +425,7 @@ Display file details in indented keyword: value format. The two forms are equiva
|
|||||||
```
|
```
|
||||||
gam <UserTypeEntity> show fileinfo <DriveFileEntity>
|
gam <UserTypeEntity> show fileinfo <DriveFileEntity>
|
||||||
[returnidonly]
|
[returnidonly]
|
||||||
[filepath|fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
[filepath|fullpath] [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||||
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
||||||
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
[showdrivename] [showshareddrivepermissions]
|
[showdrivename] [showshareddrivepermissions]
|
||||||
@@ -436,7 +436,7 @@ gam <UserTypeEntity> show fileinfo <DriveFileEntity>
|
|||||||
[formatjson]
|
[formatjson]
|
||||||
gam <UserTypeEntity> info drivefile <DriveFileEntity>
|
gam <UserTypeEntity> info drivefile <DriveFileEntity>
|
||||||
[returnidonly]
|
[returnidonly]
|
||||||
[filepath|fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
[filepath|fullpath] [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||||
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
||||||
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
[showdrivename] [showshareddrivepermissions]
|
[showdrivename] [showshareddrivepermissions]
|
||||||
@@ -455,6 +455,7 @@ Use `fullpath` to add additional path information indicating that a file is an O
|
|||||||
By default, the path to a file includes the file name as the last element of the path.
|
By default, the path to a file includes the file name as the last element of the path.
|
||||||
Use `folderpathonly` to display only the folder names when displaying the path to a file. This folder only path
|
Use `folderpathonly` to display only the folder names when displaying the path to a file. This folder only path
|
||||||
an be used in `gam <UserTypeEntity> create drivefolderpath` to recreate the folder hierarchy.
|
an be used in `gam <UserTypeEntity> create drivefolderpath` to recreate the folder hierarchy.
|
||||||
|
Use `parentpathonly` to display only the parent folder names when displaying the path to a file.
|
||||||
|
|
||||||
By default, file path components are separated by `/`; use `pathdelimiter <Character>` to use `<Character>` as the separator.
|
By default, file path components are separated by `/`; use `pathdelimiter <Character>` to use `<Character>` as the separator.
|
||||||
|
|
||||||
@@ -517,12 +518,12 @@ gam <UserTypeEntity> show filepath <DriveFileEntity>
|
|||||||
[returnpathonly]
|
[returnpathonly]
|
||||||
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
[stripcrsfromname]
|
[stripcrsfromname]
|
||||||
[folderpathonly [<Boolean>]] [fullpath] [pathdelimiter <Character>]
|
[folderpathonly|parentpathonly [<Boolean>]] [fullpath] [pathdelimiter <Character>]
|
||||||
[followshortcuts [<Boolean>]]
|
[followshortcuts [<Boolean>]]
|
||||||
gam <UserTypeEntity> print filepath <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print filepath <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
||||||
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
|
||||||
[stripcrsfromname] [oneitemperrow]
|
[stripcrsfromname] [oneitemperrow]
|
||||||
[fullpath] [folderpathonly [<Boolean>]] [pathdelimiter <Character>]
|
[fullpath] [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>]
|
||||||
[followshortcuts [<Boolean>]]
|
[followshortcuts [<Boolean>]]
|
||||||
```
|
```
|
||||||
Use `returnpathonly` to display just the file path of the files in `<DriveFileEntity>`.
|
Use `returnpathonly` to display just the file path of the files in `<DriveFileEntity>`.
|
||||||
@@ -532,6 +533,7 @@ Use `fullpath` to add additional path information indicating that a file is an O
|
|||||||
By default, the path to a file includes the file name as the last element of the path.
|
By default, the path to a file includes the file name as the last element of the path.
|
||||||
Use `folderpathonly` to display only the folder names when displaying the path to a file. This folder only path
|
Use `folderpathonly` to display only the folder names when displaying the path to a file. This folder only path
|
||||||
an be used in `gam <UserTypeEntity> create drivefolderpath` to recreate the folder hierarchy.
|
an be used in `gam <UserTypeEntity> create drivefolderpath` to recreate the folder hierarchy.
|
||||||
|
Use `parentpathonly` to display only the parent folder names when displaying the path to a file.
|
||||||
|
|
||||||
By default, file path components are separated by `/`; use `pathdelimiter <Character>` to use `<Character>` as the separator.
|
By default, file path components are separated by `/`; use `pathdelimiter <Character>` to use `<Character>` as the separator.
|
||||||
|
|
||||||
@@ -1106,7 +1108,7 @@ gam <UserTypeEntity> print|show filelist [todrive <ToDriveAttribute>*]
|
|||||||
[countsonly [summary none|only|plus] [summaryuser <String>]
|
[countsonly [summary none|only|plus] [summaryuser <String>]
|
||||||
[showsource] [showsize] [showsizeunits] [showmimetypesize]]
|
[showsource] [showsize] [showsizeunits] [showmimetypesize]]
|
||||||
[countsrowfilter]
|
[countsrowfilter]
|
||||||
[filepath|fullpath [folderpathonly [<Boolean>]] [pathdelimiter <Character>] [addpathstojson] [showdepth]] [buildtree]
|
[filepath|fullpath [folderpathonly|parentpathonly [<Boolean>]] [pathdelimiter <Character>] [addpathstojson] [showdepth]] [buildtree]
|
||||||
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
[allfields|<DriveFieldName>*|(fields <DriveFieldNameList>)]
|
||||||
[showdrivename] [showshareddrivepermissions]
|
[showdrivename] [showshareddrivepermissions]
|
||||||
[(showlabels details|ids)|(includelabels <ClassificationLabelIDList>)]
|
[(showlabels details|ids)|(includelabels <ClassificationLabelIDList>)]
|
||||||
@@ -1239,6 +1241,7 @@ JSON data rather than as additional columns
|
|||||||
By default, the path to a file includes the file name as the last element of the path.
|
By default, the path to a file includes the file name as the last element of the path.
|
||||||
Use `folderpathonly` to display only the folder names when displaying the path to a file. This folder only path
|
Use `folderpathonly` to display only the folder names when displaying the path to a file. This folder only path
|
||||||
an be used in `gam <UserTypeEntity> create drivefolderpath` to recreate the folder hierarchy.
|
an be used in `gam <UserTypeEntity> create drivefolderpath` to recreate the folder hierarchy.
|
||||||
|
Use `parentpathonly` to display only the parent folder names when displaying the path to a file.
|
||||||
|
|
||||||
By default, file path components are separated by `/`; use `pathdelimiter <Character>` to use `<Character>` as the separator.
|
By default, file path components are separated by `/`; use `pathdelimiter <Character>` to use `<Character>` as the separator.
|
||||||
|
|
||||||
|
|||||||
@@ -257,11 +257,17 @@ gam print vaultcounts [todrive <ToDriveAttributes>*]
|
|||||||
[excludedrafts <Boolean>]
|
[excludedrafts <Boolean>]
|
||||||
[<JSONData>]
|
[<JSONData>]
|
||||||
[wait <Integer>]
|
[wait <Integer>]
|
||||||
|
[include_suspended_zeros [<Boolean>]]
|
||||||
```
|
```
|
||||||
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|entireorg` - Search for all accounts in the organization
|
* `everyone|entireorg` - Search all accounts in the organization
|
||||||
|
|
||||||
|
By default, the Vault API doesn't return accounts with zero items; GAM
|
||||||
|
generates a zero count line for non-suspended accounts with zero items.
|
||||||
|
The `include_suspended_zeros` option causes GAM to generate a zero count line
|
||||||
|
for suspended accounts with zero items.
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Print the current version of Gam with details
|
Print the current version of Gam with details
|
||||||
```
|
```
|
||||||
gam version
|
gam version
|
||||||
GAM 7.43.01 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.43.07 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.4 64-bit final
|
Python 3.14.4 64-bit final
|
||||||
macOS Tahoe 26.4.1 arm64
|
macOS Tahoe 26.4.1 arm64
|
||||||
@@ -15,7 +15,7 @@ Time: 2026-02-15T07:51:00-08: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.43.01 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.43.07 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.4 64-bit final
|
Python 3.14.4 64-bit final
|
||||||
macOS Tahoe 26.4.1 arm64
|
macOS Tahoe 26.4.1 arm64
|
||||||
@@ -27,7 +27,7 @@ Your system time differs from www.googleapis.com by less than 1 second
|
|||||||
Print the current version of Gam with extended details and SSL information
|
Print the current version of Gam with extended details and SSL information
|
||||||
```
|
```
|
||||||
gam version extended
|
gam version extended
|
||||||
GAM 7.43.01 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.43.07 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.4 64-bit final
|
Python 3.14.4 64-bit final
|
||||||
macOS Tahoe 26.4.1 arm64
|
macOS Tahoe 26.4.1 arm64
|
||||||
@@ -68,7 +68,7 @@ MacOS High Sierra 10.13.6 x86_64
|
|||||||
Path: /Users/gamteam/bin/gam7
|
Path: /Users/gamteam/bin/gam7
|
||||||
Version Check:
|
Version Check:
|
||||||
Current: 5.35.08
|
Current: 5.35.08
|
||||||
Latest: 7.43.01
|
Latest: 7.43.07
|
||||||
echo $?
|
echo $?
|
||||||
1
|
1
|
||||||
```
|
```
|
||||||
@@ -76,7 +76,7 @@ echo $?
|
|||||||
Print the current version number without details
|
Print the current version number without details
|
||||||
```
|
```
|
||||||
gam version simple
|
gam version simple
|
||||||
7.43.01
|
7.43.07
|
||||||
```
|
```
|
||||||
In Linux/MacOS you can do:
|
In Linux/MacOS you can do:
|
||||||
```
|
```
|
||||||
@@ -86,7 +86,7 @@ echo $VER
|
|||||||
Print the current version of Gam and address of this Wiki
|
Print the current version of Gam and address of this Wiki
|
||||||
```
|
```
|
||||||
gam help
|
gam help
|
||||||
GAM 7.43.01 - https://github.com/GAM-team/GAM
|
GAM 7.43.07 - https://github.com/GAM-team/GAM
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.4 64-bit final
|
Python 3.14.4 64-bit final
|
||||||
macOS Tahoe 26.4.1 arm64
|
macOS Tahoe 26.4.1 arm64
|
||||||
|
|||||||
Reference in New Issue
Block a user