mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-28 09:51:36 +00:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac12adb1f2 | ||
|
|
e4af5e6126 | ||
|
|
6e296e0f2d | ||
|
|
4b2e14c2d5 | ||
|
|
eb59663f6a | ||
|
|
d12289c4f4 | ||
|
|
738ff3e7fb | ||
|
|
789e543b3f | ||
|
|
4e933f4485 | ||
|
|
a99f23ce40 | ||
|
|
5462c0359e | ||
|
|
0c143414a8 | ||
|
|
bebcfb7c44 | ||
|
|
18ce64886d | ||
|
|
db87aa54d8 | ||
|
|
1867af9366 | ||
|
|
e1f2bedd7c | ||
|
|
8735021c9b | ||
|
|
2860ae02a2 | ||
|
|
31b4b70f0f | ||
|
|
1c8bf44867 | ||
|
|
472905d6c0 | ||
|
|
bed9b5e1b6 | ||
|
|
c8521c6307 | ||
|
|
870a3149d8 | ||
|
|
8622ae6c0f | ||
|
|
c92468276a | ||
|
|
d80b93b86e | ||
|
|
2d26fa6004 | ||
|
|
a09a98e3ae | ||
|
|
7d7817664b | ||
|
|
9aea95e8db | ||
|
|
8b6781a49b | ||
|
|
ff59855a2c | ||
|
|
37d00ff0d8 | ||
|
|
669dffcd39 | ||
|
|
e3ad108c91 | ||
|
|
d7d98d41cd | ||
|
|
213b0f2ba2 |
24
.github/workflows/build.yml
vendored
24
.github/workflows/build.yml
vendored
@@ -145,7 +145,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
@@ -165,7 +165,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
cache.tar.xz
|
cache.tar.xz
|
||||||
key: gam-${{ matrix.jid }}-20260609
|
key: gam-${{ matrix.jid }}-20260611
|
||||||
|
|
||||||
- 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'
|
||||||
@@ -529,18 +529,6 @@ jobs:
|
|||||||
echo "gam=${gam}" >> $GITHUB_ENV
|
echo "gam=${gam}" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#- name: Upgrade pip, wheel, etc
|
|
||||||
# run: |
|
|
||||||
# curl $curl_retry -O https://bootstrap.pypa.io/get-pip.py
|
|
||||||
# "$PYTHON" get-pip.py
|
|
||||||
# "$PYTHON" -m pip install --upgrade pip
|
|
||||||
# "$PYTHON" -m pip install --upgrade wheel
|
|
||||||
# "$PYTHON" -m pip install --upgrade setuptools
|
|
||||||
# "$PYTHON" -m pip install --upgrade importlib-metadata
|
|
||||||
# "$PYTHON" -m pip install --upgrade setuptools-scm
|
|
||||||
# "$PYTHON" -m pip install --upgrade packaging
|
|
||||||
# "$PYTHON" -m pip list
|
|
||||||
|
|
||||||
- name: Install pip requirements
|
- name: Install pip requirements
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
@@ -550,8 +538,12 @@ jobs:
|
|||||||
# https://github.com/pyca/cryptography/issues/14293
|
# https://github.com/pyca/cryptography/issues/14293
|
||||||
gh release download --repo "jay0lee/cryptography-wheels" --pattern "*win_arm64.whl" --clobber
|
gh release download --repo "jay0lee/cryptography-wheels" --pattern "*win_arm64.whl" --clobber
|
||||||
"$PYTHON" -m pip install cryptography-*.whl
|
"$PYTHON" -m pip install cryptography-*.whl
|
||||||
|
elif [[ "$RUNNER_OS" == "macOS" && "$RUNNER_ARCH" == "x86_64" ]]; then
|
||||||
|
# custom cryptography wheel for macos x86_64 since it's no longer standard
|
||||||
|
gh release download --repo "jay0lee/cryptography-wheels" --pattern "*macosx_15_0_x86_64.whl" --clobber
|
||||||
|
"$PYTHON" -m pip install cryptography-*.whl
|
||||||
fi
|
fi
|
||||||
"$PYTHON" -m pip install -vvv --upgrade ..[yubikey]
|
"$PYTHON" -m pip install ..[yubikey]
|
||||||
|
|
||||||
- name: Install PyInstaller
|
- name: Install PyInstaller
|
||||||
if: matrix.goal == 'build'
|
if: matrix.goal == 'build'
|
||||||
@@ -1121,7 +1113,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|||||||
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -39,7 +39,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v5.0.0
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
|
|||||||
2
.github/workflows/get-cacerts.yml
vendored
2
.github/workflows/get-cacerts.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
check-certs:
|
check-certs:
|
||||||
runs-on: ubuntu-slim
|
runs-on: ubuntu-slim
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token
|
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token
|
||||||
fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
|
fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
|
||||||
|
|||||||
2
.github/workflows/pushwiki.yml
vendored
2
.github/workflows/pushwiki.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
git clone https://github.com/GAM-team/GAM
|
git clone https://github.com/GAM-team/GAM
|
||||||
|
|
||||||
- name: Checkout Wiki source
|
- name: Checkout Wiki source
|
||||||
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v5.0.0
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
with:
|
with:
|
||||||
path: GAM.wiki
|
path: GAM.wiki
|
||||||
repository: GAM-team/GAM.wiki
|
repository: GAM-team/GAM.wiki
|
||||||
|
|||||||
2
.github/workflows/pypi.yml
vendored
2
.github/workflows/pypi.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
id-token: write
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v5.0.0
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|||||||
126
.github/workflows/upgrade_deps.yml
vendored
126
.github/workflows/upgrade_deps.yml
vendored
@@ -15,20 +15,25 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
|
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
|
||||||
with:
|
with:
|
||||||
python-version: '3.14'
|
python-version: '3.14'
|
||||||
|
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v3
|
||||||
|
with:
|
||||||
|
version: "latest"
|
||||||
|
|
||||||
- name: Calculate and pin two-week old stable versions
|
- name: Calculate and pin two-week old stable versions
|
||||||
shell: python
|
shell: python
|
||||||
run: |
|
run: |
|
||||||
import json
|
import subprocess
|
||||||
import urllib.request
|
|
||||||
import re
|
import re
|
||||||
import tomllib
|
import tomllib
|
||||||
|
import os
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -42,14 +47,10 @@ jobs:
|
|||||||
|
|
||||||
target_deps = set()
|
target_deps = set()
|
||||||
|
|
||||||
# Standard [project.dependencies]
|
# Gather all dependencies
|
||||||
target_deps.update(parsed_toml.get("project", {}).get("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():
|
for deps in parsed_toml.get("project", {}).get("optional-dependencies", {}).values():
|
||||||
target_deps.update(deps)
|
target_deps.update(deps)
|
||||||
|
|
||||||
# Dev [dependency-groups] (uv / PEP 735 standard)
|
|
||||||
for deps in parsed_toml.get("dependency-groups", {}).values():
|
for deps in parsed_toml.get("dependency-groups", {}).values():
|
||||||
if isinstance(deps, list):
|
if isinstance(deps, list):
|
||||||
for d in deps:
|
for d in deps:
|
||||||
@@ -60,73 +61,80 @@ jobs:
|
|||||||
print("No dependencies found to process.")
|
print("No dependencies found to process.")
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
updates = {}
|
# 1. Create a "clean" requirements list (base names + markers only, no versions)
|
||||||
two_weeks_ago = datetime.now(timezone.utc) - timedelta(days=14)
|
clean_reqs = []
|
||||||
print(f"Evaluating dependencies against cutoff date: {two_weeks_ago.isoformat()}")
|
|
||||||
|
|
||||||
for dep in target_deps:
|
for dep in target_deps:
|
||||||
# Isolate base package name (e.g., "yubikey-manager>=5.6.1" -> "yubikey-manager")
|
pkg_base = re.split(r'[<>=!~;\s]', dep)[0].strip()
|
||||||
pkg_name = re.split(r'[<>=!~;\s]', dep)[0].strip()
|
if ";" in dep:
|
||||||
|
marker = dep.split(";", 1)[1].strip()
|
||||||
|
clean_reqs.append(f"{pkg_base} ; {marker}")
|
||||||
|
else:
|
||||||
|
clean_reqs.append(pkg_base)
|
||||||
|
|
||||||
|
temp_in = Path("temp_reqs.in")
|
||||||
|
temp_in.write_text("\n".join(clean_reqs), encoding="utf-8")
|
||||||
|
|
||||||
|
# 2. Calculate Cutoff Date
|
||||||
|
two_weeks_ago = datetime.now(timezone.utc) - timedelta(days=14)
|
||||||
|
cutoff_str = two_weeks_ago.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
print(f"Resolving dependencies against cutoff date: {cutoff_str}")
|
||||||
|
|
||||||
|
# 3. Use uv to resolve the CLEAN list, allowing free upgrades/downgrades
|
||||||
|
try:
|
||||||
|
subprocess.run([
|
||||||
|
"uv", "pip", "compile",
|
||||||
|
str(temp_in),
|
||||||
|
"--exclude-newer", cutoff_str,
|
||||||
|
"--quiet",
|
||||||
|
"-o", "resolved.txt"
|
||||||
|
], check=True)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
print("\nDependency resolution failed! Upstream constraints are impossible to satisfy.")
|
||||||
|
if temp_in.exists(): temp_in.unlink()
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# 4. Parse the resolved lockfile
|
||||||
|
resolved_versions = {}
|
||||||
|
with open("resolved.txt", "r", encoding="utf-8") as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.split("#")[0].strip()
|
||||||
|
if "==" in line:
|
||||||
|
pkg, ver = line.split("==", 1)
|
||||||
|
resolved_versions[pkg.strip().lower()] = ver.strip()
|
||||||
|
|
||||||
|
# Cleanup temp files so they don't get committed to the PR
|
||||||
|
if temp_in.exists():
|
||||||
|
temp_in.unlink()
|
||||||
|
if Path("resolved.txt").exists():
|
||||||
|
Path("resolved.txt").unlink()
|
||||||
|
|
||||||
|
# 5. Map the newly resolved versions back to your pyproject.toml updates
|
||||||
|
updates = {}
|
||||||
|
for dep in target_deps:
|
||||||
|
pkg_name_raw = re.split(r'[<>=!~;\s]', dep)[0].strip()
|
||||||
|
pkg_name_lower = pkg_name_raw.lower()
|
||||||
|
|
||||||
# Preserve environment markers if they exist
|
|
||||||
marker = ""
|
marker = ""
|
||||||
if ";" in dep:
|
if ";" in dep:
|
||||||
marker = " ; " + dep.split(";", 1)[1].strip()
|
marker = " ; " + dep.split(";", 1)[1].strip()
|
||||||
|
|
||||||
print(f"Fetching PyPI data for: {pkg_name}")
|
if pkg_name_lower in resolved_versions:
|
||||||
try:
|
target_version = resolved_versions[pkg_name_lower]
|
||||||
url = f"https://pypi.org/pypi/{pkg_name}/json"
|
pinned_dep = f"{pkg_name_raw}=={target_version}{marker}"
|
||||||
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:
|
if pinned_dep != dep:
|
||||||
updates[dep] = pinned_dep
|
updates[dep] = pinned_dep
|
||||||
print(f" -> Pinning: '{dep}' => '{pinned_dep}'")
|
print(f" -> Changing: '{dep}' => '{pinned_dep}'")
|
||||||
else:
|
else:
|
||||||
print(f" -> Already pinned correctly to {target_version}")
|
print(f" -> Up to date: {dep}")
|
||||||
else:
|
|
||||||
print(f" -> No valid historical versions found.")
|
|
||||||
|
|
||||||
except urllib.error.HTTPError as e:
|
# 6. Replace the strings safely in the original file content
|
||||||
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
|
new_content = content
|
||||||
for old_dep, new_dep in updates.items():
|
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)
|
escaped_old = re.escape(old_dep)
|
||||||
pattern = r'([\'"])' + escaped_old + r'\1'
|
pattern = r'([\'"])' + escaped_old + r'\1'
|
||||||
new_content = re.sub(pattern, lambda m: m.group(1) + new_dep + m.group(1), new_content)
|
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:
|
if content != new_content:
|
||||||
toml_path.write_text(new_content, encoding="utf-8")
|
toml_path.write_text(new_content, encoding="utf-8")
|
||||||
print("\npyproject.toml updated successfully.")
|
print("\npyproject.toml updated successfully.")
|
||||||
@@ -139,6 +147,6 @@ jobs:
|
|||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
commit-message: "chore: upgrade PyPi deps"
|
commit-message: "chore: upgrade PyPi deps"
|
||||||
title: "Upgrade PyPi deps"
|
title: "Upgrade PyPi deps"
|
||||||
body: "Automated scan checking PyPI for package versions at least 2 weeks old."
|
body: "Automated scan checking PyPI for mutually compatible package versions at least 2 weeks old. Handles both upgrades and conflict-driven downgrades."
|
||||||
branch: sys-deps-upgrade
|
branch: sys-deps-upgrade
|
||||||
force: false # Standard push, plays nice with rulesets
|
force: false # Standard push, plays nice with rulesets
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -10,13 +10,13 @@ authors = [
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow==1.4.0",
|
"arrow==1.4.0",
|
||||||
"chardet==7.4.3",
|
"chardet==7.4.3",
|
||||||
"cryptography==48.0.0",
|
"cryptography==48.0.1",
|
||||||
"distro==1.9.0 ; sys_platform=='linux'",
|
"distro==1.9.0 ; sys_platform=='linux'",
|
||||||
"filelock==3.29.0",
|
"filelock==3.29.4",
|
||||||
"google-api-python-client==2.196.0",
|
"google-api-python-client==2.197.0",
|
||||||
"google-auth-httplib2==0.4.0",
|
"google-auth-httplib2==0.4.0",
|
||||||
"google-auth-oauthlib==1.4.0",
|
"google-auth-oauthlib==1.4.0",
|
||||||
"google-auth==2.53.0",
|
"google-auth==2.54.0",
|
||||||
"httplib2==0.31.2",
|
"httplib2==0.31.2",
|
||||||
"lxml==6.1.1",
|
"lxml==6.1.1",
|
||||||
"passlib==1.7.4",
|
"passlib==1.7.4",
|
||||||
|
|||||||
@@ -1676,6 +1676,10 @@ gam <UserTypeEntity> show analyticdatastreams
|
|||||||
<CalendarACLScopeEntity>::=
|
<CalendarACLScopeEntity>::=
|
||||||
<CalendarACLScopeList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
|
<CalendarACLScopeList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
|
||||||
|
|
||||||
|
Transfer ownership of a selection of a users secondary calendars to another user
|
||||||
|
|
||||||
|
gam calendars <CalendarEntity> transfer <UserItem>
|
||||||
|
|
||||||
gam calendars <CalendarEntity> create|add acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
|
gam calendars <CalendarEntity> create|add acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
|
||||||
gam calendars <CalendarEntity> update acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
|
gam calendars <CalendarEntity> update acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
|
||||||
gam calendars <CalendarEntity> delete acls|calendaracls [<CalendarACLRole>] <CalendarACLScopeEntity>
|
gam calendars <CalendarEntity> delete acls|calendaracls [<CalendarACLRole>] <CalendarACLScopeEntity>
|
||||||
@@ -6298,13 +6302,6 @@ gam <UserTypeEntity> print calendaracls <UserCalendarEntity> [todrive <ToDriveAt
|
|||||||
[noselfowner] (addcsvdata <FieldName> <String>)*
|
[noselfowner] (addcsvdata <FieldName> <String>)*
|
||||||
[formatjson [quotechar <Character>]]
|
[formatjson [quotechar <Character>]]
|
||||||
|
|
||||||
Transfer ownership of a selection of a users secondary calendars to another user
|
|
||||||
|
|
||||||
gam <UserTypeEntity> transfer calendars|seccals <UserItem> [<UserCalendarEntity>]
|
|
||||||
[keepuser | (retainrole <CalendarACLRole>)] [sendnotifications <Boolean>] [noretentionmessages]
|
|
||||||
<CalendarSettings>* [append description|location|summary] [noupdatemessages]
|
|
||||||
[deletefromoldowner] [addtonewowner <CalendarAttribute>*] [nolistmessages]
|
|
||||||
|
|
||||||
<AttendeeAttendance> ::= optional|required
|
<AttendeeAttendance> ::= optional|required
|
||||||
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
|
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
7.46.03
|
||||||
|
|
||||||
|
Updated all Vault related commands to handle the following error: `ERROR: 403: permissionDenied`
|
||||||
|
|
||||||
|
7.46.02
|
||||||
|
|
||||||
|
Updated `gam calendars <CalendarEntity> show settings` to display `dataOwner` field;
|
||||||
|
it is labelled `Owner`.
|
||||||
|
|
||||||
|
7.46.01
|
||||||
|
|
||||||
|
Fixed bug in `gam <CrOSTypeEntity> issuecommand command <CrOSCommand> ... csv` where
|
||||||
|
command execution status lines were improperly indented.
|
||||||
|
|
||||||
|
Upgraded to Python 3.14.6.
|
||||||
|
|
||||||
7.46.00
|
7.46.00
|
||||||
|
|
||||||
Added commands to create, update and delete Cloud Identity policies for data loss prevention (DLP) rules and detectors.
|
Added commands to create, update and delete Cloud Identity policies for data loss prevention (DLP) rules and detectors.
|
||||||
|
|||||||
@@ -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.46.00'
|
__version__ = '7.46.03'
|
||||||
__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
|
||||||
@@ -683,7 +683,7 @@ def accessErrorMessage(cd, errMsg=None):
|
|||||||
[Ent.Singular(Ent.CUSTOMER_ID), GC.Values[GC.CUSTOMER_ID],
|
[Ent.Singular(Ent.CUSTOMER_ID), GC.Values[GC.CUSTOMER_ID],
|
||||||
Msg.DOES_NOT_EXIST],
|
Msg.DOES_NOT_EXIST],
|
||||||
'')
|
'')
|
||||||
except GAPI.forbidden:
|
except (GAPI.forbidden, GAPI.permissionDenied):
|
||||||
return formatKeyValueList('',
|
return formatKeyValueList('',
|
||||||
Ent.FormatEntityValueList([Ent.CUSTOMER_ID, GC.Values[GC.CUSTOMER_ID],
|
Ent.FormatEntityValueList([Ent.CUSTOMER_ID, GC.Values[GC.CUSTOMER_ID],
|
||||||
Ent.DOMAIN, GC.Values[GC.DOMAIN],
|
Ent.DOMAIN, GC.Values[GC.DOMAIN],
|
||||||
@@ -24392,7 +24392,7 @@ def displayCrOSCommandResult(cd, deviceId, commandId, checkResultRetries, i, cou
|
|||||||
if addCSVData:
|
if addCSVData:
|
||||||
result.update(addCSVData)
|
result.update(addCSVData)
|
||||||
csvPF.WriteRowTitles(flattenJSON(result, timeObjects=CROS_COMMAND_TIME_OBJECTS))
|
csvPF.WriteRowTitles(flattenJSON(result, timeObjects=CROS_COMMAND_TIME_OBJECTS))
|
||||||
return
|
break
|
||||||
showJSON(None, result, timeObjects=CROS_COMMAND_TIME_OBJECTS)
|
showJSON(None, result, timeObjects=CROS_COMMAND_TIME_OBJECTS)
|
||||||
state = result.get('state')
|
state = result.get('state')
|
||||||
if state in CROS_COMMAND_FINAL_STATES:
|
if state in CROS_COMMAND_FINAL_STATES:
|
||||||
@@ -24871,9 +24871,9 @@ def infoCrOSDevices(entityList):
|
|||||||
i += 1
|
i += 1
|
||||||
try:
|
try:
|
||||||
cros = callGAPI(cd.chromeosdevices(), 'get',
|
cros = callGAPI(cd.chromeosdevices(), 'get',
|
||||||
throwReasons=[GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN],
|
throwReasons=[GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
||||||
customerId=GC.Values[GC.CUSTOMER_ID], deviceId=deviceId, projection=projection, fields=fields)
|
customerId=GC.Values[GC.CUSTOMER_ID], deviceId=deviceId, projection=projection, fields=fields)
|
||||||
except (GAPI.badRequest, GAPI.resourceNotFound, GAPI.forbidden):
|
except (GAPI.badRequest, GAPI.resourceNotFound, GAPI.forbidden, GAPI.permissionDenied):
|
||||||
checkEntityAFDNEorAccessErrorExit(cd, Ent.CROS_DEVICE, deviceId, i, count)
|
checkEntityAFDNEorAccessErrorExit(cd, Ent.CROS_DEVICE, deviceId, i, count)
|
||||||
continue
|
continue
|
||||||
checkTPMVulnerability(cros)
|
checkTPMVulnerability(cros)
|
||||||
@@ -25498,7 +25498,7 @@ def doPrintCrOSDevices(entityList=None):
|
|||||||
try:
|
try:
|
||||||
feed = callGAPI(cd.chromeosdevices(), 'list',
|
feed = callGAPI(cd.chromeosdevices(), 'list',
|
||||||
throwReasons=[GAPI.INVALID_INPUT, GAPI.INVALID_ORGUNIT,
|
throwReasons=[GAPI.INVALID_INPUT, GAPI.INVALID_ORGUNIT,
|
||||||
GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN],
|
GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
pageToken=pageToken,
|
pageToken=pageToken,
|
||||||
customerId=GC.Values[GC.CUSTOMER_ID], query=query, projection=projection,
|
customerId=GC.Values[GC.CUSTOMER_ID], query=query, projection=projection,
|
||||||
@@ -25532,7 +25532,7 @@ def doPrintCrOSDevices(entityList=None):
|
|||||||
except GAPI.invalidOrgunit as e:
|
except GAPI.invalidOrgunit as e:
|
||||||
entityActionFailedWarning([Ent.CROS_DEVICE, None], str(e))
|
entityActionFailedWarning([Ent.CROS_DEVICE, None], str(e))
|
||||||
return
|
return
|
||||||
except (GAPI.badRequest, GAPI.resourceNotFound, GAPI.forbidden):
|
except (GAPI.badRequest, GAPI.resourceNotFound, GAPI.forbidden, GAPI.permissionDenied):
|
||||||
accessErrorExit(cd)
|
accessErrorExit(cd)
|
||||||
if showItemCountOnly:
|
if showItemCountOnly:
|
||||||
writeStdout(f'{totalItems}\n')
|
writeStdout(f'{totalItems}\n')
|
||||||
@@ -42956,14 +42956,16 @@ def doCalendarsModifySettings(calIds):
|
|||||||
def _showCalendarSettings(calendar, j, jcount):
|
def _showCalendarSettings(calendar, j, jcount):
|
||||||
printEntity([Ent.CALENDAR, calendar['id']], j, jcount)
|
printEntity([Ent.CALENDAR, calendar['id']], j, jcount)
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
|
if 'dataOwner' in calendar:
|
||||||
|
printKeyValueList(['Owner', calendar['dataOwner']])
|
||||||
if 'summaryOverride' in calendar or 'summary' in calendar:
|
if 'summaryOverride' in calendar or 'summary' in calendar:
|
||||||
printKeyValueList(['Summary', calendar.get('summaryOverride', calendar.get('summary', ''))])
|
printKeyValueList(['Summary', calendar.get('summaryOverride', calendar.get('summary', ''))])
|
||||||
if 'description' in calendar:
|
if 'description' in calendar:
|
||||||
printKeyValueWithCRsNLs('Description', calendar.get('description', ''))
|
printKeyValueWithCRsNLs('Description', calendar['description'])
|
||||||
if 'location' in calendar:
|
if 'location' in calendar:
|
||||||
printKeyValueList(['Location', calendar.get('location', '')])
|
printKeyValueList(['Location', calendar['location']])
|
||||||
if 'timeZone' in calendar:
|
if 'timeZone' in calendar:
|
||||||
printKeyValueList(['Timezone', calendar.get('timeZone', '')])
|
printKeyValueList(['Timezone', calendar['timeZone']])
|
||||||
if 'conferenceProperties' in calendar:
|
if 'conferenceProperties' in calendar:
|
||||||
printKeyValueList(['ConferenceProperties', None])
|
printKeyValueList(['ConferenceProperties', None])
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
@@ -43642,7 +43644,7 @@ def convertExportNameToID(v, nameOrId, matterId, matterNameId):
|
|||||||
if cg:
|
if cg:
|
||||||
try:
|
try:
|
||||||
export = callGAPI(v.matters().exports(), 'get',
|
export = callGAPI(v.matters().exports(), 'get',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN,
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED,
|
||||||
GAPI.INVALID_ARGUMENT, GAPI.FAILED_PRECONDITION],
|
GAPI.INVALID_ARGUMENT, GAPI.FAILED_PRECONDITION],
|
||||||
matterId=matterId, exportId=cg.group(1))
|
matterId=matterId, exportId=cg.group(1))
|
||||||
return (export['id'], export['name'], formatVaultNameId(export['id'], export['name']))
|
return (export['id'], export['name'], formatVaultNameId(export['id'], export['name']))
|
||||||
@@ -43650,14 +43652,14 @@ def convertExportNameToID(v, nameOrId, matterId, matterNameId):
|
|||||||
entityDoesNotHaveItemExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, nameOrId])
|
entityDoesNotHaveItemExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, nameOrId])
|
||||||
except (GAPI.failedPrecondition) as e:
|
except (GAPI.failedPrecondition) as e:
|
||||||
entityActionFailedExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, nameOrId], str(e))
|
entityActionFailedExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, nameOrId], str(e))
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
ClientAPIAccessDeniedExit(str(e))
|
ClientAPIAccessDeniedExit(str(e))
|
||||||
nameOrIdlower = nameOrId.lower()
|
nameOrIdlower = nameOrId.lower()
|
||||||
try:
|
try:
|
||||||
exports = callGAPIpages(v.matters().exports(), 'list', 'exports',
|
exports = callGAPIpages(v.matters().exports(), 'list', 'exports',
|
||||||
throwReasons=[GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, fields='exports(id,name),nextPageToken')
|
matterId=matterId, fields='exports(id,name),nextPageToken')
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
ClientAPIAccessDeniedExit(str(e))
|
ClientAPIAccessDeniedExit(str(e))
|
||||||
for export in exports:
|
for export in exports:
|
||||||
if export['name'].lower() == nameOrIdlower:
|
if export['name'].lower() == nameOrIdlower:
|
||||||
@@ -43669,19 +43671,19 @@ def convertHoldNameToID(v, nameOrId, matterId, matterNameId):
|
|||||||
if cg:
|
if cg:
|
||||||
try:
|
try:
|
||||||
hold = callGAPI(v.matters().holds(), 'get',
|
hold = callGAPI(v.matters().holds(), 'get',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, holdId=cg.group(1))
|
matterId=matterId, holdId=cg.group(1))
|
||||||
return (hold['holdId'], hold['name'], formatVaultNameId(hold['holdId'], hold['name']))
|
return (hold['holdId'], hold['name'], formatVaultNameId(hold['holdId'], hold['name']))
|
||||||
except (GAPI.notFound, GAPI.badRequest):
|
except (GAPI.notFound, GAPI.badRequest):
|
||||||
entityDoesNotHaveItemExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, nameOrId])
|
entityDoesNotHaveItemExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, nameOrId])
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
ClientAPIAccessDeniedExit(str(e))
|
ClientAPIAccessDeniedExit(str(e))
|
||||||
nameOrIdlower = nameOrId.lower()
|
nameOrIdlower = nameOrId.lower()
|
||||||
try:
|
try:
|
||||||
holds = callGAPIpages(v.matters().holds(), 'list', 'holds',
|
holds = callGAPIpages(v.matters().holds(), 'list', 'holds',
|
||||||
throwReasons=[GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, fields='holds(holdId,name),nextPageToken')
|
matterId=matterId, fields='holds(holdId,name),nextPageToken')
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
ClientAPIAccessDeniedExit(str(e))
|
ClientAPIAccessDeniedExit(str(e))
|
||||||
for hold in holds:
|
for hold in holds:
|
||||||
if hold['name'].lower() == nameOrIdlower:
|
if hold['name'].lower() == nameOrIdlower:
|
||||||
@@ -43693,16 +43695,18 @@ def convertMatterNameToID(v, nameOrId, state=None):
|
|||||||
if cg:
|
if cg:
|
||||||
try:
|
try:
|
||||||
matter = callGAPI(v.matters(), 'get',
|
matter = callGAPI(v.matters(), 'get',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=cg.group(1), view='BASIC', fields='matterId,name,state')
|
matterId=cg.group(1), view='BASIC', fields='matterId,name,state')
|
||||||
return (matter['matterId'], matter['name'], formatVaultNameId(matter['name'], matter['matterId']), matter['state'])
|
return (matter['matterId'], matter['name'], formatVaultNameId(matter['name'], matter['matterId']), matter['state'])
|
||||||
except (GAPI.notFound, GAPI.forbidden):
|
except GAPI.notFound:
|
||||||
entityDoesNotExistExit(Ent.VAULT_MATTER, nameOrId)
|
entityDoesNotExistExit(Ent.VAULT_MATTER, nameOrId)
|
||||||
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
|
ClientAPIAccessDeniedExit(str(e))
|
||||||
try:
|
try:
|
||||||
matters = callGAPIpages(v.matters(), 'list', 'matters',
|
matters = callGAPIpages(v.matters(), 'list', 'matters',
|
||||||
throwReasons=[GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
view='BASIC', state=state, fields='matters(matterId,name,state),nextPageToken')
|
view='BASIC', state=state, fields='matters(matterId,name,state),nextPageToken')
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
ClientAPIAccessDeniedExit(str(e))
|
ClientAPIAccessDeniedExit(str(e))
|
||||||
nameOrIdlower = nameOrId.lower()
|
nameOrIdlower = nameOrId.lower()
|
||||||
ids = []
|
ids = []
|
||||||
@@ -43724,19 +43728,19 @@ def convertQueryNameToID(v, nameOrId, matterId, matterNameId):
|
|||||||
if cg:
|
if cg:
|
||||||
try:
|
try:
|
||||||
query = callGAPI(v.matters().savedQueries(), 'get',
|
query = callGAPI(v.matters().savedQueries(), 'get',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, savedQueryId=cg.group(1))
|
matterId=matterId, savedQueryId=cg.group(1))
|
||||||
return (query['savedQueryId'], query['displayName'], formatVaultNameId(query['savedQueryId'], query['displayName']), query['query'])
|
return (query['savedQueryId'], query['displayName'], formatVaultNameId(query['savedQueryId'], query['displayName']), query['query'])
|
||||||
except (GAPI.notFound, GAPI.badRequest):
|
except (GAPI.notFound, GAPI.badRequest):
|
||||||
entityDoesNotHaveItemExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, nameOrId])
|
entityDoesNotHaveItemExit([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, nameOrId])
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
ClientAPIAccessDeniedExit(str(e))
|
ClientAPIAccessDeniedExit(str(e))
|
||||||
nameOrIdlower = nameOrId.lower()
|
nameOrIdlower = nameOrId.lower()
|
||||||
try:
|
try:
|
||||||
queries = callGAPIpages(v.matters().savedQueries(), 'list', 'savedQueries',
|
queries = callGAPIpages(v.matters().savedQueries(), 'list', 'savedQueries',
|
||||||
throwReasons=[GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, fields='savedQueries(savedQueryId,displayName,query),nextPageToken')
|
matterId=matterId, fields='savedQueries(savedQueryId,displayName,query),nextPageToken')
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
ClientAPIAccessDeniedExit(str(e))
|
ClientAPIAccessDeniedExit(str(e))
|
||||||
for query in queries:
|
for query in queries:
|
||||||
if query['displayName'].lower() == nameOrIdlower:
|
if query['displayName'].lower() == nameOrIdlower:
|
||||||
@@ -43751,9 +43755,9 @@ def warnMatterNotOpen(v, matter, matterNameId, j, jcount):
|
|||||||
if v is not None:
|
if v is not None:
|
||||||
try:
|
try:
|
||||||
matter['state'] = callGAPI(v.matters(), 'get',
|
matter['state'] = callGAPI(v.matters(), 'get',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matter['matterId'], view='BASIC', fields='state')['state']
|
matterId=matter['matterId'], view='BASIC', fields='state')['state']
|
||||||
except (GAPI.notFound, GAPI.forbidden, GAPI.invalidArgument):
|
except (GAPI.notFound, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument):
|
||||||
matter['state'] = 'Unknown'
|
matter['state'] = 'Unknown'
|
||||||
else:
|
else:
|
||||||
setSysExitRC(DATA_NOT_AVALIABLE_RC)
|
setSysExitRC(DATA_NOT_AVALIABLE_RC)
|
||||||
@@ -44124,10 +44128,10 @@ def doDeleteVaultExport():
|
|||||||
unknownArgumentExit()
|
unknownArgumentExit()
|
||||||
try:
|
try:
|
||||||
callGAPI(v.matters().exports(), 'delete',
|
callGAPI(v.matters().exports(), 'delete',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, exportId=exportId)
|
matterId=matterId, exportId=exportId)
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, exportNameId])
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, exportNameId])
|
||||||
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, exportNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, exportNameId], str(e))
|
||||||
|
|
||||||
VAULT_EXPORT_FIELDS_CHOICE_MAP = {
|
VAULT_EXPORT_FIELDS_CHOICE_MAP = {
|
||||||
@@ -44182,7 +44186,7 @@ def doInfoVaultExport():
|
|||||||
GAPI.INVALID_ARGUMENT, GAPI.FAILED_PRECONDITION],
|
GAPI.INVALID_ARGUMENT, GAPI.FAILED_PRECONDITION],
|
||||||
matterId=matterId, exportId=exportId, fields=fields)
|
matterId=matterId, exportId=exportId, fields=fields)
|
||||||
_showVaultExport(matterNameId, export, cd, FJQC)
|
_showVaultExport(matterNameId, export, cd, FJQC)
|
||||||
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument, GAPI.failedPrecondition) as e:
|
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument, GAPI.failedPrecondition) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, exportNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, exportNameId], str(e))
|
||||||
|
|
||||||
VAULT_EXPORT_STATUS_MAP = {'completed': 'COMPLETED', 'failed': 'FAILED', 'inprogress': 'IN_PROGRESS'}
|
VAULT_EXPORT_STATUS_MAP = {'completed': 'COMPLETED', 'failed': 'FAILED', 'inprogress': 'IN_PROGRESS'}
|
||||||
@@ -44245,9 +44249,9 @@ def doPrintShowVaultExports():
|
|||||||
try:
|
try:
|
||||||
results = callGAPIpages(v.matters(), 'list', 'matters',
|
results = callGAPIpages(v.matters(), 'list', 'matters',
|
||||||
pageMessage=getPageMessage(),
|
pageMessage=getPageMessage(),
|
||||||
throwReasons=[GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
view='BASIC', state='OPEN', fields='matters(matterId,name,state),nextPageToken')
|
view='BASIC', state='OPEN', fields='matters(matterId,name,state),nextPageToken')
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_EXPORT, None], str(e))
|
entityActionFailedWarning([Ent.VAULT_EXPORT, None], str(e))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
@@ -44275,12 +44279,12 @@ def doPrintShowVaultExports():
|
|||||||
try:
|
try:
|
||||||
exports = callGAPIpages(v.matters().exports(), 'list', 'exports',
|
exports = callGAPIpages(v.matters().exports(), 'list', 'exports',
|
||||||
pageMessage=pageMessage,
|
pageMessage=pageMessage,
|
||||||
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, fields=fields)
|
matterId=matterId, fields=fields)
|
||||||
except GAPI.failedPrecondition:
|
except GAPI.failedPrecondition:
|
||||||
warnMatterNotOpen(v, matter, matterNameId, j, jcount)
|
warnMatterNotOpen(v, matter, matterNameId, j, jcount)
|
||||||
continue
|
continue
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_EXPORT, None], str(e))
|
entityActionFailedWarning([Ent.VAULT_EXPORT, None], str(e))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
@@ -44358,7 +44362,7 @@ def doCopyVaultExport():
|
|||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN,
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN,
|
||||||
GAPI.INVALID_ARGUMENT, GAPI.FAILED_PRECONDITION],
|
GAPI.INVALID_ARGUMENT, GAPI.FAILED_PRECONDITION],
|
||||||
matterId=matterId, exportId=exportId)
|
matterId=matterId, exportId=exportId)
|
||||||
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument, GAPI.failedPrecondition) as e:
|
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument, GAPI.failedPrecondition) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, exportNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, exportNameId], str(e))
|
||||||
return
|
return
|
||||||
if export['status'] == 'COMPLETED':
|
if export['status'] == 'COMPLETED':
|
||||||
@@ -44459,7 +44463,7 @@ def doDownloadVaultExport():
|
|||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN,
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN,
|
||||||
GAPI.INVALID_ARGUMENT, GAPI.FAILED_PRECONDITION],
|
GAPI.INVALID_ARGUMENT, GAPI.FAILED_PRECONDITION],
|
||||||
matterId=matterId, exportId=exportId)
|
matterId=matterId, exportId=exportId)
|
||||||
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument, GAPI.failedPrecondition) as e:
|
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument, GAPI.failedPrecondition) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, exportNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_EXPORT, exportNameId], str(e))
|
||||||
return
|
return
|
||||||
if export['status'] == 'COMPLETED':
|
if export['status'] == 'COMPLETED':
|
||||||
@@ -44685,7 +44689,7 @@ def doCreateVaultHold():
|
|||||||
try:
|
try:
|
||||||
hold = callGAPI(v.matters().holds(), 'create',
|
hold = callGAPI(v.matters().holds(), 'create',
|
||||||
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.BAD_REQUEST, GAPI.BACKEND_ERROR, GAPI.FAILED_PRECONDITION,
|
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.BAD_REQUEST, GAPI.BACKEND_ERROR, GAPI.FAILED_PRECONDITION,
|
||||||
GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, body=body)
|
matterId=matterId, body=body)
|
||||||
if not returnIdOnly:
|
if not returnIdOnly:
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, formatVaultNameId(hold['name'], hold['holdId'])])
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, formatVaultNameId(hold['name'], hold['holdId'])])
|
||||||
@@ -44694,7 +44698,7 @@ def doCreateVaultHold():
|
|||||||
else:
|
else:
|
||||||
writeStdout(f'{hold["holdId"]}\n')
|
writeStdout(f'{hold["holdId"]}\n')
|
||||||
except (GAPI.alreadyExists, GAPI.badRequest, GAPI.backendError, GAPI.failedPrecondition,
|
except (GAPI.alreadyExists, GAPI.badRequest, GAPI.backendError, GAPI.failedPrecondition,
|
||||||
GAPI.forbidden, GAPI.invalidArgument) as e:
|
GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, body.get('name')], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, body.get('name')], str(e))
|
||||||
|
|
||||||
# gam update vaulthold|hold <HoldItem> matter <MatterItem>
|
# gam update vaulthold|hold <HoldItem> matter <MatterItem>
|
||||||
@@ -44739,9 +44743,9 @@ def doUpdateVaultHold():
|
|||||||
missingArgumentExit('matter')
|
missingArgumentExit('matter')
|
||||||
try:
|
try:
|
||||||
old_body = callGAPI(v.matters().holds(), 'get',
|
old_body = callGAPI(v.matters().holds(), 'get',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, holdId=holdId, fields='name,corpus,query,orgUnit')
|
matterId=matterId, holdId=holdId, fields='name,corpus,query,orgUnit')
|
||||||
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId], str(e))
|
||||||
return
|
return
|
||||||
accountType = 'group' if old_body['corpus'] == 'GROUPS' else 'user'
|
accountType = 'group' if old_body['corpus'] == 'GROUPS' else 'user'
|
||||||
@@ -44767,10 +44771,10 @@ def doUpdateVaultHold():
|
|||||||
if body:
|
if body:
|
||||||
try:
|
try:
|
||||||
hold = callGAPI(v.matters().holds(), 'update',
|
hold = callGAPI(v.matters().holds(), 'update',
|
||||||
throwReas=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReas=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, holdId=holdId, body=body)
|
matterId=matterId, holdId=holdId, body=body)
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId])
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId])
|
||||||
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId], str(e))
|
||||||
return
|
return
|
||||||
jcount = len(addAccountIds)
|
jcount = len(addAccountIds)
|
||||||
@@ -44783,12 +44787,12 @@ def doUpdateVaultHold():
|
|||||||
j += 1
|
j += 1
|
||||||
try:
|
try:
|
||||||
callGAPI(v.matters().holds().accounts(), 'create',
|
callGAPI(v.matters().holds().accounts(), 'create',
|
||||||
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.BACKEND_ERROR, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.BACKEND_ERROR, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, holdId=holdId, body={'accountId': account['id']})
|
matterId=matterId, holdId=holdId, body={'accountId': account['id']})
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId, Ent.ACCOUNT, account['email']], j, jcount)
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId, Ent.ACCOUNT, account['email']], j, jcount)
|
||||||
except (GAPI.alreadyExists, GAPI.backendError) as e:
|
except (GAPI.alreadyExists, GAPI.backendError) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId, Ent.ACCOUNT, account['email']], str(e), j, jcount)
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId, Ent.ACCOUNT, account['email']], str(e), j, jcount)
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, None], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, None], str(e))
|
||||||
return
|
return
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
@@ -44804,12 +44808,12 @@ def doUpdateVaultHold():
|
|||||||
j += 1
|
j += 1
|
||||||
try:
|
try:
|
||||||
callGAPI(v.matters().holds().accounts(), 'delete',
|
callGAPI(v.matters().holds().accounts(), 'delete',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BACKEND_ERROR, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BACKEND_ERROR, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, holdId=holdId, accountId=account['id'])
|
matterId=matterId, holdId=holdId, accountId=account['id'])
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId, Ent.ACCOUNT, account['email']], j, jcount)
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId, Ent.ACCOUNT, account['email']], j, jcount)
|
||||||
except (GAPI.alreadyExists, GAPI.backendError) as e:
|
except (GAPI.alreadyExists, GAPI.backendError) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId, Ent.ACCOUNT, account['email']], str(e), j, jcount)
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId, Ent.ACCOUNT, account['email']], str(e), j, jcount)
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, None], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, None], str(e))
|
||||||
return
|
return
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
@@ -44834,10 +44838,10 @@ def doDeleteVaultHold():
|
|||||||
unknownArgumentExit()
|
unknownArgumentExit()
|
||||||
try:
|
try:
|
||||||
callGAPI(v.matters().holds(), 'delete',
|
callGAPI(v.matters().holds(), 'delete',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, holdId=holdId)
|
matterId=matterId, holdId=holdId)
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId])
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId])
|
||||||
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId], str(e))
|
||||||
|
|
||||||
VAULT_HOLD_FIELDS_CHOICE_MAP = {
|
VAULT_HOLD_FIELDS_CHOICE_MAP = {
|
||||||
@@ -44887,10 +44891,10 @@ def doInfoVaultHold():
|
|||||||
fields = getFieldsFromFieldsList(fieldsList)
|
fields = getFieldsFromFieldsList(fieldsList)
|
||||||
try:
|
try:
|
||||||
hold = callGAPI(v.matters().holds(), 'get',
|
hold = callGAPI(v.matters().holds(), 'get',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, holdId=holdId, fields=fields)
|
matterId=matterId, holdId=holdId, fields=fields)
|
||||||
_showVaultHold(matterNameId, hold, cd, FJQC)
|
_showVaultHold(matterNameId, hold, cd, FJQC)
|
||||||
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_HOLD, holdNameId], str(e))
|
||||||
|
|
||||||
PRINT_VAULT_HOLDS_TITLES = ['matterId', 'matterName', 'holdId', 'name', 'updateTime']
|
PRINT_VAULT_HOLDS_TITLES = ['matterId', 'matterName', 'holdId', 'name', 'updateTime']
|
||||||
@@ -44941,9 +44945,9 @@ def doPrintShowVaultHolds():
|
|||||||
try:
|
try:
|
||||||
results = callGAPIpages(v.matters(), 'list', 'matters',
|
results = callGAPIpages(v.matters(), 'list', 'matters',
|
||||||
pageMessage=getPageMessage(),
|
pageMessage=getPageMessage(),
|
||||||
throwReasons=[GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
view='BASIC', state='OPEN', fields='matters(matterId,name,state),nextPageToken')
|
view='BASIC', state='OPEN', fields='matters(matterId,name,state),nextPageToken')
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_HOLD, None], str(e))
|
entityActionFailedWarning([Ent.VAULT_HOLD, None], str(e))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
@@ -44970,12 +44974,12 @@ def doPrintShowVaultHolds():
|
|||||||
try:
|
try:
|
||||||
holds = callGAPIpages(v.matters().holds(), 'list', 'holds',
|
holds = callGAPIpages(v.matters().holds(), 'list', 'holds',
|
||||||
pageMessage=pageMessage,
|
pageMessage=pageMessage,
|
||||||
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, fields=fields)
|
matterId=matterId, fields=fields)
|
||||||
except GAPI.failedPrecondition:
|
except GAPI.failedPrecondition:
|
||||||
warnMatterNotOpen(v, matter, matterNameId, j, jcount)
|
warnMatterNotOpen(v, matter, matterNameId, j, jcount)
|
||||||
continue
|
continue
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_HOLD, None], str(e))
|
entityActionFailedWarning([Ent.VAULT_HOLD, None], str(e))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
@@ -45021,9 +45025,9 @@ def printShowUserVaultHolds(entityList):
|
|||||||
try:
|
try:
|
||||||
matters = callGAPIpages(v.matters(), 'list', 'matters',
|
matters = callGAPIpages(v.matters(), 'list', 'matters',
|
||||||
pageMessage=getPageMessage(),
|
pageMessage=getPageMessage(),
|
||||||
throwReasons=[GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
view='BASIC', state='OPEN', fields='matters(matterId,name,state),nextPageToken')
|
view='BASIC', state='OPEN', fields='matters(matterId,name,state),nextPageToken')
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_HOLD, None], str(e))
|
entityActionFailedWarning([Ent.VAULT_HOLD, None], str(e))
|
||||||
return
|
return
|
||||||
jcount = len(matters)
|
jcount = len(matters)
|
||||||
@@ -45037,11 +45041,11 @@ def printShowUserVaultHolds(entityList):
|
|||||||
try:
|
try:
|
||||||
matter['holds'] = callGAPIpages(v.matters().holds(), 'list', 'holds',
|
matter['holds'] = callGAPIpages(v.matters().holds(), 'list', 'holds',
|
||||||
pageMessage=getPageMessageForWhom(),
|
pageMessage=getPageMessageForWhom(),
|
||||||
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, fields='holds(holdId,name,accounts(accountId,email),orgUnit(orgUnitId)),nextPageToken')
|
matterId=matterId, fields='holds(holdId,name,accounts(accountId,email),orgUnit(orgUnitId)),nextPageToken')
|
||||||
except GAPI.failedPrecondition:
|
except GAPI.failedPrecondition:
|
||||||
warnMatterNotOpen(v, matter, matterNameId, j, jcount)
|
warnMatterNotOpen(v, matter, matterNameId, j, jcount)
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_HOLD, None], str(e), j, jcount)
|
entityActionFailedWarning([Ent.VAULT_HOLD, None], str(e), j, jcount)
|
||||||
totalHolds = 0
|
totalHolds = 0
|
||||||
_, _, entityList = getEntityArgument(entityList)
|
_, _, entityList = getEntityArgument(entityList)
|
||||||
@@ -45155,7 +45159,7 @@ def doCreateCopyVaultQuery(copyCmd):
|
|||||||
resultNameId = matterNameId
|
resultNameId = matterNameId
|
||||||
try:
|
try:
|
||||||
result = callGAPI(v.matters().savedQueries(), 'create',
|
result = callGAPI(v.matters().savedQueries(), 'create',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT, GAPI.ALREADY_EXISTS],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT, GAPI.ALREADY_EXISTS],
|
||||||
matterId=resultId, body=body)
|
matterId=resultId, body=body)
|
||||||
if not returnIdOnly:
|
if not returnIdOnly:
|
||||||
if not FJQC.formatJSON:
|
if not FJQC.formatJSON:
|
||||||
@@ -45164,7 +45168,7 @@ def doCreateCopyVaultQuery(copyCmd):
|
|||||||
_showVaultQuery(resultNameId, result, cd, drive, FJQC)
|
_showVaultQuery(resultNameId, result, cd, drive, FJQC)
|
||||||
else:
|
else:
|
||||||
writeStdout(f'{result["savedQueryId"]}\n')
|
writeStdout(f'{result["savedQueryId"]}\n')
|
||||||
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument, GAPI.alreadyExists) as e:
|
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument, GAPI.alreadyExists) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, resultNameId, Ent.VAULT_QUERY, body['displayName']], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, resultNameId, Ent.VAULT_QUERY, body['displayName']], str(e))
|
||||||
|
|
||||||
# gam create vaultquery <MatterItem> [name <String>]
|
# gam create vaultquery <MatterItem> [name <String>]
|
||||||
@@ -45212,10 +45216,10 @@ def doDeleteVaultQuery():
|
|||||||
unknownArgumentExit()
|
unknownArgumentExit()
|
||||||
try:
|
try:
|
||||||
callGAPI(v.matters().savedQueries(), 'delete',
|
callGAPI(v.matters().savedQueries(), 'delete',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, savedQueryId=queryId)
|
matterId=matterId, savedQueryId=queryId)
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, queryNameId])
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, queryNameId])
|
||||||
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, queryNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, queryNameId], str(e))
|
||||||
|
|
||||||
VAULT_QUERY_FIELDS_CHOICE_MAP = {
|
VAULT_QUERY_FIELDS_CHOICE_MAP = {
|
||||||
@@ -45261,10 +45265,10 @@ def doInfoVaultQuery():
|
|||||||
fields = getFieldsFromFieldsList(fieldsList)
|
fields = getFieldsFromFieldsList(fieldsList)
|
||||||
try:
|
try:
|
||||||
query = callGAPI(v.matters().savedQueries(), 'get',
|
query = callGAPI(v.matters().savedQueries(), 'get',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.BAD_REQUEST, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, savedQueryId=queryId, fields=fields)
|
matterId=matterId, savedQueryId=queryId, fields=fields)
|
||||||
_showVaultQuery(matterNameId, query, cd, drive, FJQC)
|
_showVaultQuery(matterNameId, query, cd, drive, FJQC)
|
||||||
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.notFound, GAPI.badRequest, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, queryNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId, Ent.VAULT_QUERY, queryNameId], str(e))
|
||||||
|
|
||||||
PRINT_VAULT_QUERIES_TITLES = ['matterId', 'matterName', 'savedQueryId', 'displayName']
|
PRINT_VAULT_QUERIES_TITLES = ['matterId', 'matterName', 'savedQueryId', 'displayName']
|
||||||
@@ -45305,9 +45309,9 @@ def doPrintShowVaultQueries():
|
|||||||
try:
|
try:
|
||||||
results = callGAPIpages(v.matters(), 'list', 'matters',
|
results = callGAPIpages(v.matters(), 'list', 'matters',
|
||||||
pageMessage=getPageMessage(),
|
pageMessage=getPageMessage(),
|
||||||
throwReasons=[GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
view='BASIC', state='OPEN', fields='matters(matterId,name,state),nextPageToken')
|
view='BASIC', state='OPEN', fields='matters(matterId,name,state),nextPageToken')
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_QUERY, None], str(e))
|
entityActionFailedWarning([Ent.VAULT_QUERY, None], str(e))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
@@ -45334,12 +45338,12 @@ def doPrintShowVaultQueries():
|
|||||||
try:
|
try:
|
||||||
queries = callGAPIpages(v.matters().savedQueries(), 'list', 'savedQueries',
|
queries = callGAPIpages(v.matters().savedQueries(), 'list', 'savedQueries',
|
||||||
pageMessage=pageMessage,
|
pageMessage=pageMessage,
|
||||||
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, fields=fields)
|
matterId=matterId, fields=fields)
|
||||||
except GAPI.failedPrecondition:
|
except GAPI.failedPrecondition:
|
||||||
warnMatterNotOpen(v, matter, matterNameId, j, jcount)
|
warnMatterNotOpen(v, matter, matterNameId, j, jcount)
|
||||||
continue
|
continue
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_QUERY, None], str(e))
|
entityActionFailedWarning([Ent.VAULT_QUERY, None], str(e))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
@@ -45426,7 +45430,7 @@ def doCreateVaultMatter():
|
|||||||
body['name'] = f'GAM Matter - {ISOformatTimeStamp(todaysTime())}'
|
body['name'] = f'GAM Matter - {ISOformatTimeStamp(todaysTime())}'
|
||||||
try:
|
try:
|
||||||
matter = callGAPI(v.matters(), 'create',
|
matter = callGAPI(v.matters(), 'create',
|
||||||
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
body=body)
|
body=body)
|
||||||
matterId = matter['matterId']
|
matterId = matter['matterId']
|
||||||
matterNameId = formatVaultNameId(matter['name'], matterId)
|
matterNameId = formatVaultNameId(matter['name'], matterId)
|
||||||
@@ -45434,7 +45438,7 @@ def doCreateVaultMatter():
|
|||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId])
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId])
|
||||||
else:
|
else:
|
||||||
writeStdout(f'{matterId}\n')
|
writeStdout(f'{matterId}\n')
|
||||||
except (GAPI.alreadyExists, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.alreadyExists, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, body['name']], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, body['name']], str(e))
|
||||||
return
|
return
|
||||||
jcount = len(collaborators)
|
jcount = len(collaborators)
|
||||||
@@ -45449,11 +45453,11 @@ def doCreateVaultMatter():
|
|||||||
cbody['matterPermission']['accountId'] = collaborator['id']
|
cbody['matterPermission']['accountId'] = collaborator['id']
|
||||||
try:
|
try:
|
||||||
callGAPI(v.matters(), 'addPermissions',
|
callGAPI(v.matters(), 'addPermissions',
|
||||||
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, body=cbody)
|
matterId=matterId, body=cbody)
|
||||||
if not returnIdOnly:
|
if not returnIdOnly:
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.COLLABORATOR, collaborator['email']], j, jcount)
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.COLLABORATOR, collaborator['email']], j, jcount)
|
||||||
except (GAPI.failedPrecondition, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.failedPrecondition, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
||||||
break
|
break
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
@@ -45477,10 +45481,10 @@ def doActionVaultMatter(action, matterId=None, matterNameId=None, v=None):
|
|||||||
action_kwargs = {} if action == 'delete' else {'body': {}}
|
action_kwargs = {} if action == 'delete' else {'body': {}}
|
||||||
try:
|
try:
|
||||||
callGAPI(v.matters(), action,
|
callGAPI(v.matters(), action,
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, **action_kwargs)
|
matterId=matterId, **action_kwargs)
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId])
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId])
|
||||||
except (GAPI.notFound, GAPI.failedPrecondition, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.notFound, GAPI.failedPrecondition, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
||||||
|
|
||||||
# gam close vaultmatter|matter <MatterItem>
|
# gam close vaultmatter|matter <MatterItem>
|
||||||
@@ -45533,7 +45537,7 @@ def doUpdateVaultMatter():
|
|||||||
if 'name' not in body or 'description' not in body:
|
if 'name' not in body or 'description' not in body:
|
||||||
# bah, API requires name/description to be sent on update even when it's not changing
|
# bah, API requires name/description to be sent on update even when it's not changing
|
||||||
result = callGAPI(v.matters(), 'get',
|
result = callGAPI(v.matters(), 'get',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, view='BASIC')
|
matterId=matterId, view='BASIC')
|
||||||
body.setdefault('name', result['name'])
|
body.setdefault('name', result['name'])
|
||||||
body.setdefault('description', result.get('description'))
|
body.setdefault('description', result.get('description'))
|
||||||
@@ -45541,7 +45545,7 @@ def doUpdateVaultMatter():
|
|||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN],
|
||||||
matterId=matterId, body=body)
|
matterId=matterId, body=body)
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId])
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId])
|
||||||
except (GAPI.notFound, GAPI.failedPrecondition, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.notFound, GAPI.failedPrecondition, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
||||||
return
|
return
|
||||||
jcount = len(addCollaborators)
|
jcount = len(addCollaborators)
|
||||||
@@ -45554,10 +45558,10 @@ def doUpdateVaultMatter():
|
|||||||
j += 1
|
j += 1
|
||||||
try:
|
try:
|
||||||
callGAPI(v.matters(), 'addPermissions',
|
callGAPI(v.matters(), 'addPermissions',
|
||||||
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, body={'matterPermission': {'role': 'COLLABORATOR', 'accountId': collaborator['id']}})
|
matterId=matterId, body={'matterPermission': {'role': 'COLLABORATOR', 'accountId': collaborator['id']}})
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.COLLABORATOR, collaborator['email']], j, jcount)
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.COLLABORATOR, collaborator['email']], j, jcount)
|
||||||
except (GAPI.failedPrecondition, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.failedPrecondition, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
||||||
break
|
break
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
@@ -45571,10 +45575,10 @@ def doUpdateVaultMatter():
|
|||||||
j += 1
|
j += 1
|
||||||
try:
|
try:
|
||||||
callGAPI(v.matters(), 'removePermissions',
|
callGAPI(v.matters(), 'removePermissions',
|
||||||
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, body={'accountId': collaborator['id']})
|
matterId=matterId, body={'accountId': collaborator['id']})
|
||||||
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.COLLABORATOR, collaborator['email']], j, jcount)
|
entityActionPerformed([Ent.VAULT_MATTER, matterNameId, Ent.COLLABORATOR, collaborator['email']], j, jcount)
|
||||||
except (GAPI.failedPrecondition, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.failedPrecondition, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
||||||
break
|
break
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
@@ -45607,11 +45611,11 @@ def doInfoVaultMatter():
|
|||||||
fields = getFieldsFromFieldsList(fieldsList)
|
fields = getFieldsFromFieldsList(fieldsList)
|
||||||
try:
|
try:
|
||||||
matter = callGAPI(v.matters(), 'get',
|
matter = callGAPI(v.matters(), 'get',
|
||||||
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT],
|
||||||
matterId=matterId, view=view, fields=fields)
|
matterId=matterId, view=view, fields=fields)
|
||||||
cd = buildGAPIObject(API.DIRECTORY) if 'matterPermissions' in matter else None
|
cd = buildGAPIObject(API.DIRECTORY) if 'matterPermissions' in matter else None
|
||||||
_showVaultMatter(matter, cd, FJQC)
|
_showVaultMatter(matter, cd, FJQC)
|
||||||
except (GAPI.notFound, GAPI.forbidden, GAPI.invalidArgument) as e:
|
except (GAPI.notFound, GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, matterNameId], str(e))
|
||||||
|
|
||||||
VAULT_MATTER_STATE_MAP = {'open': 'OPEN', 'closed': 'CLOSED', 'deleted': 'DELETED'}
|
VAULT_MATTER_STATE_MAP = {'open': 'OPEN', 'closed': 'CLOSED', 'deleted': 'DELETED'}
|
||||||
@@ -45667,9 +45671,9 @@ def doPrintShowVaultMatters():
|
|||||||
try:
|
try:
|
||||||
matters = callGAPIpages(v.matters(), 'list', 'matters',
|
matters = callGAPIpages(v.matters(), 'list', 'matters',
|
||||||
pageMessage=getPageMessage(),
|
pageMessage=getPageMessage(),
|
||||||
throwReasons=[GAPI.FORBIDDEN, GAPI.INVALID_ARGUMENT, GAPI.INVALID_ARGUMENT],
|
throwReasons=[GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED, GAPI.INVALID_ARGUMENT, GAPI.INVALID_ARGUMENT],
|
||||||
view=view, state=stateParm, fields=fields)
|
view=view, state=stateParm, fields=fields)
|
||||||
except (GAPI.forbidden, GAPI.invalidArgument, GAPI.invalidArgument) as e:
|
except (GAPI.forbidden, GAPI.permissionDenied, GAPI.invalidArgument, GAPI.invalidArgument) as e:
|
||||||
entityActionFailedWarning([Ent.VAULT_MATTER, None], str(e))
|
entityActionFailedWarning([Ent.VAULT_MATTER, None], str(e))
|
||||||
return
|
return
|
||||||
jcount = len(matters)
|
jcount = len(matters)
|
||||||
@@ -55346,16 +55350,30 @@ def printShowCalendarACLs(users):
|
|||||||
if csvPF:
|
if csvPF:
|
||||||
csvPF.writeCSVfile('Calendar ACLs')
|
csvPF.writeCSVfile('Calendar ACLs')
|
||||||
|
|
||||||
# gam <UserTypeEntity> transfer calendars|seccals <UserItem> [<UserCalendarEntity>]
|
# gam <CalendarEntity> transfer ownership <UserItem>
|
||||||
# [keepuser | (retainrole <CalendarACLRole>)] [sendnotifications <Boolean>] [noretentionmessages]
|
def doCalendarsTransferOwnership(calIds):
|
||||||
# <CalendarSettings>* [append description|location|summary] [noupdatemessages]
|
Act.Set(Act.TRANSFER_OWNERSHIP)
|
||||||
# [deletefromoldowner] [addtonewowner <CalendarAttribute>*] [nolistmessages]
|
newDataOwner = getEmailAddress()
|
||||||
def transferCalendars(users):
|
checkForExtraneousArguments()
|
||||||
errMsg = ''' Due to the following Calendar API update, the `gam <UserTypeEntity> transfer calendars` command has been removed.
|
count = len(calIds)
|
||||||
* See: https://developers.google.com/workspace/calendar/release-notes#October_27_2025
|
i = 0
|
||||||
Data ownership can be transferred in the Google Calendar UI.
|
for calId in calIds:
|
||||||
'''
|
i += 1
|
||||||
systemErrorExit(ACTION_FAILED_RC, errMsg)
|
calId, cal = validateCalendar(calId, i, count)
|
||||||
|
if not cal:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
callGAPI(cal.calendars(), 'transferOwnership',
|
||||||
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID, GAPI.INVALID_PARAMETER,
|
||||||
|
GAPI.FORBIDDEN, GAPI.AUTH_ERROR, GAPI.CONDITION_NOT_MET],
|
||||||
|
calendarId=calId, newDataOwner=newDataOwner, useAdminAccess=True)
|
||||||
|
entityPerformActionModifierNewValue([Ent.CALENDAR, calId], Act.MODIFIER_TO, newDataOwner, i, count)
|
||||||
|
except (GAPI.notFound, GAPI.invalid, GAPI.invalidParameter,
|
||||||
|
GAPI.forbidden, GAPI.authError, GAPI.conditionNotMet) as e:
|
||||||
|
entityModifierNewValueActionFailedWarning([Ent.CALENDAR, calId], Act.MODIFIER_TO, newDataOwner, str(e), i, count)
|
||||||
|
except AttributeError as e:
|
||||||
|
entityModifierNewValueActionFailedWarning([Ent.CALENDAR, calId], Act.MODIFIER_TO, newDataOwner, str(e), i, count)
|
||||||
|
return
|
||||||
|
|
||||||
def _createImportCalendarEvent(users, function):
|
def _createImportCalendarEvent(users, function):
|
||||||
calendarEntity = getUserCalendarEntity()
|
calendarEntity = getUserCalendarEntity()
|
||||||
@@ -81568,6 +81586,11 @@ CALENDARS_SUBCOMMANDS_WITH_OBJECTS = {
|
|||||||
Cmd.ARG_SETTINGS: doCalendarsPrintShowSettings,
|
Cmd.ARG_SETTINGS: doCalendarsPrintShowSettings,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
'transfer':
|
||||||
|
(Act.TRANSFER,
|
||||||
|
{Cmd.ARG_OWNERSHIP: doCalendarsTransferOwnership,
|
||||||
|
}
|
||||||
|
),
|
||||||
'update':
|
'update':
|
||||||
(Act.UPDATE,
|
(Act.UPDATE,
|
||||||
{Cmd.ARG_CALENDARACL: doCalendarsUpdateACLs,
|
{Cmd.ARG_CALENDARACL: doCalendarsUpdateACLs,
|
||||||
@@ -82302,7 +82325,6 @@ USER_COMMANDS_WITH_OBJECTS = {
|
|||||||
'transfer':
|
'transfer':
|
||||||
(Act.TRANSFER,
|
(Act.TRANSFER,
|
||||||
{Cmd.ARG_DRIVE: transferDrive,
|
{Cmd.ARG_DRIVE: transferDrive,
|
||||||
Cmd.ARG_CALENDAR: transferCalendars,
|
|
||||||
Cmd.ARG_OWNERSHIP: transferOwnership,
|
Cmd.ARG_OWNERSHIP: transferOwnership,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
- [Manage calendar access](#manage-calendar-access)
|
- [Manage calendar access](#manage-calendar-access)
|
||||||
- [Display calendar access](#display-calendar-access)
|
- [Display calendar access](#display-calendar-access)
|
||||||
- [Old format commands](#old-format-commands)
|
- [Old format commands](#old-format-commands)
|
||||||
|
- [Transfer calendar ownership](#transfer-calendar-ownership)
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
These commands use Client access for all commands except those that reference user's primary calendars
|
These commands use Client access for all commands except those that reference user's primary calendars
|
||||||
@@ -42,6 +43,9 @@ Added `writerwithoutprivateaccess` to `<CalendarACLRole>` in 7.44.03; this will
|
|||||||
"<CalendarACLScope>(,<CalendarACLScope>)*"
|
"<CalendarACLScope>(,<CalendarACLScope>)*"
|
||||||
<CalendarACLScopeEntity>::=
|
<CalendarACLScopeEntity>::=
|
||||||
<CalendarACLScopeList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
|
<CalendarACLScopeList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
|
||||||
|
|
||||||
|
<UniqueID> ::= id:<String>
|
||||||
|
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
|
||||||
```
|
```
|
||||||
## Manage calendar access
|
## Manage calendar access
|
||||||
```
|
```
|
||||||
@@ -92,3 +96,13 @@ gam calendar <CalendarEntity> printacl [todrive <ToDriveAttribute>*]
|
|||||||
```
|
```
|
||||||
By default, when you add or update a calendar ACL, notification is sent to the members referenced in the `<CalendarACLScopeEntity>`.
|
By default, when you add or update a calendar ACL, notification is sent to the members referenced in the `<CalendarACLScopeEntity>`.
|
||||||
Use `sendnotifications false` to suppress sending the notification.
|
Use `sendnotifications false` to suppress sending the notification.
|
||||||
|
|
||||||
|
## Transfer calendar ownership
|
||||||
|
|
||||||
|
You can transfer ownership of secondary calendars from one user to another.
|
||||||
|
|
||||||
|
```
|
||||||
|
gam <CalendarEntity> transfer ownership <UserItem>
|
||||||
|
```
|
||||||
|
|
||||||
|
See: https://workspaceupdates.googleblog.com/2026/06/secondary-calendar-management-API.html
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
- [Definitions](#definitions)
|
- [Definitions](#definitions)
|
||||||
- [Policies](#policies)
|
- [Policies](#policies)
|
||||||
- [Display Cloud Identity Policies](#display-cloud-identity-policies)
|
- [Display Cloud Identity Policies](#display-cloud-identity-policies)
|
||||||
|
- [Create and Update Cloud Identity Policies](#create-and-update-cloud-identity-policies)
|
||||||
|
- [Delete Cloud Identity Policies](#delete-cloud-identity-policies)
|
||||||
|
|
||||||
## API documentation
|
## API documentation
|
||||||
* [Policy API](https://cloud.google.com/identity/docs/reference/rest/v1/policies)
|
* [Policy API](https://cloud.google.com/identity/docs/reference/rest/v1/policies)
|
||||||
@@ -35,6 +37,9 @@ You must enable access to policies in the GCP cloud console.
|
|||||||
* Click Organization Policy Administrator
|
* Click Organization Policy Administrator
|
||||||
* Click Save
|
* Click Save
|
||||||
|
|
||||||
|
The commands to create, update and delete Cloud Identity policies for data loss prevention (DLP) rules and detectors
|
||||||
|
were added in version `7.46.00`.
|
||||||
|
|
||||||
## Definitions
|
## Definitions
|
||||||
```
|
```
|
||||||
<CIPolicyName> ::= policies/<String>|settings/<String>|<String>
|
<CIPolicyName> ::= policies/<String>|settings/<String>|<String>
|
||||||
@@ -87,7 +92,7 @@ gam show policies
|
|||||||
[formatjson]
|
[formatjson]
|
||||||
```
|
```
|
||||||
By default, all policies are displayed.
|
By default, all policies are displayed.
|
||||||
* `filter <String>` - Display filtered policies, See https://cloud.google.com/identity/docs/reference/rest/v1beta1/policies/list
|
* `filter <String>` - Display filtered policies, See https://cloud.google.com/identity/docs/reference/rest/v1/policies/list
|
||||||
* `group <REMatchPattern>` - Only display policies whose group email address matches the `<REMatchPattern>`
|
* `group <REMatchPattern>` - Only display policies whose group email address matches the `<REMatchPattern>`
|
||||||
* `ou|org|orgunit <REMatchPattern>` - Only display policies whose OU path matches the `<REMatchPattern>`
|
* `ou|org|orgunit <REMatchPattern>` - Only display policies whose OU path matches the `<REMatchPattern>`
|
||||||
|
|
||||||
@@ -110,7 +115,7 @@ gam print policies [todrive <ToDriveAttribute>*]
|
|||||||
[formatjson [quotechar <Character>]]
|
[formatjson [quotechar <Character>]]
|
||||||
```
|
```
|
||||||
By default, all policies are displayed:
|
By default, all policies are displayed:
|
||||||
* `filter <String>` - Display filtered policies, See https://cloud.google.com/identity/docs/reference/rest/v1beta1/policies/list
|
* `filter <String>` - Display filtered policies, See https://cloud.google.com/identity/docs/reference/rest/v1/policies/list
|
||||||
* `group <REMatchPattern>` - Only display policies whose group email address matches the `<REMatchPattern>`
|
* `group <REMatchPattern>` - Only display policies whose group email address matches the `<REMatchPattern>`
|
||||||
* `ou|org|orgunit <REMatchPattern>` - Only display policies whose OU path matches the `<REMatchPattern>`
|
* `ou|org|orgunit <REMatchPattern>` - Only display policies whose OU path matches the `<REMatchPattern>`
|
||||||
|
|
||||||
@@ -152,3 +157,32 @@ Print all polices that apply to the OU "/Staff" and its sub-OUs.
|
|||||||
```
|
```
|
||||||
gam redirect csv ./StaffPolicies.csv print policies ou "^/Staff"
|
gam redirect csv ./StaffPolicies.csv print policies ou "^/Staff"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Create and Update Cloud Identity Policies
|
||||||
|
Policies can be complex objects, it is probably easiest to create template policies in the Admin console (under Rules),
|
||||||
|
output the JSON format data for those policies to be used in subsequent create and update commands.
|
||||||
|
|
||||||
|
```
|
||||||
|
gam create policy
|
||||||
|
json <JSONData>
|
||||||
|
[(ou|orgunit <OrgUnitItem>)|(group <GroupItem>)|(query <String>)]
|
||||||
|
gam update policy
|
||||||
|
json <JSONData>
|
||||||
|
[(ou|orgunit <OrgUnitItem>)|(group <GroupItem>)|(query <String>)]
|
||||||
|
```
|
||||||
|
```
|
||||||
|
gam redirect stdout ./policy.json info policies policies/akajj264aoclblvncu
|
||||||
|
Make changes to policy.json and update the policy.
|
||||||
|
gam update policy json file policy.json
|
||||||
|
|
||||||
|
Update the policy to reference a different group.
|
||||||
|
gam update policy json file policy.json group <EmailAddress>
|
||||||
|
|
||||||
|
Make changes to policy.json and create a new policy in a different OU.
|
||||||
|
gam create policy json file policy.json ou <OrgUnitPath>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Delete Cloud Identity Policies
|
||||||
|
```
|
||||||
|
gam delete policies <CIPolicyNameEntity>
|
||||||
|
```
|
||||||
|
|||||||
@@ -10,6 +10,29 @@ 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.46.03
|
||||||
|
|
||||||
|
Updated all Vault related commands to handle the following error: `ERROR: 403: permissionDenied`
|
||||||
|
|
||||||
|
### 7.46.02
|
||||||
|
|
||||||
|
Updated `gam calendars <CalendarEntity> show settings` to display `dataOwner` field;
|
||||||
|
it is labelled `Owner`.
|
||||||
|
|
||||||
|
### 7.46.01
|
||||||
|
|
||||||
|
Fixed bug in `gam <CrOSTypeEntity> issuecommand command <CrOSCommand> ... csv` where
|
||||||
|
command execution status lines were improperly indented.
|
||||||
|
|
||||||
|
Upgraded to Python 3.14.6.
|
||||||
|
|
||||||
|
### 7.46.00
|
||||||
|
|
||||||
|
Added commands to create, update and delete Cloud Identity policies for data loss prevention (DLP) rules and detectors.
|
||||||
|
|
||||||
|
* See: https://github.com/GAM-team/GAM/wiki/Cloud-Identity-Policies
|
||||||
|
* See: https://workspaceupdates.googleblog.com/2026/06/introducing-workspace-policy-api-mutate-endpoints-for-DLP.html
|
||||||
|
|
||||||
### 7.45.00
|
### 7.45.00
|
||||||
|
|
||||||
Added options `isdisabled [<Boolean>]`, `disabledafter <DateTime>` and `disabledbefore <DateTime>`
|
Added options `isdisabled [<Boolean>]`, `disabledafter <DateTime>` and `disabledbefore <DateTime>`
|
||||||
|
|||||||
@@ -251,9 +251,9 @@ 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.45.00 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.46.03 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.5 64-bit final
|
Python 3.14.6 64-bit final
|
||||||
macOS Tahoe 26.5.1 arm64
|
macOS Tahoe 26.5.1 arm64
|
||||||
Path: /Users/gamteam/bin/gam7
|
Path: /Users/gamteam/bin/gam7
|
||||||
Config File: /Users/gamteam/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
Config File: /Users/gamteam/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||||
@@ -1034,9 +1034,9 @@ 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.45.00 - https://github.com/GAM-team/GAM - pythonsource
|
GAM 7.46.03 - https://github.com/GAM-team/GAM - pythonsource
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.5 64-bit final
|
Python 3.14.6 64-bit final
|
||||||
Windows 11 10.0.26200 AMD64
|
Windows 11 10.0.26200 AMD64
|
||||||
Path: C:\GAM7
|
Path: C:\GAM7
|
||||||
Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
- [Calendar selection](#calendar-selection)
|
- [Calendar selection](#calendar-selection)
|
||||||
- [Manage calendar access](#manage-calendar-access)
|
- [Manage calendar access](#manage-calendar-access)
|
||||||
- [Display calendar access](#display-calendar-access)
|
- [Display calendar access](#display-calendar-access)
|
||||||
- [Transfer calendar ownership](#transfer-calendar-ownership)
|
- [Transfer calendar ownership](Calendars-Access)
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
Calendar ACL roles (as seen in Calendar GUI):
|
Calendar ACL roles (as seen in Calendar GUI):
|
||||||
@@ -144,13 +144,3 @@ the quote character itself, the column delimiter (comma by default) and new-line
|
|||||||
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
|
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
|
||||||
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
|
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
|
||||||
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
|
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
|
||||||
|
|
||||||
## Transfer calendar ownership
|
|
||||||
|
|
||||||
You can transfer ownership of calendars from one user to another; only non-primary calendars owned by the source user can be transferred.
|
|
||||||
|
|
||||||
This capability is no longer available, see: https://developers.google.com/workspace/calendar/release-notes#October_27_2025
|
|
||||||
|
|
||||||
Data ownership can be transferred in the Google Calendar UI.
|
|
||||||
|
|
||||||
See: https://workspaceupdates.googleblog.com/2026/03/an-update-on-secondary-calendar-lifecycle-changes-and-a-new-API.html
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ gam <UserTypeEntity> print driveactivity [todrive <ToDriveAttributes>*]
|
|||||||
By default, drive activity for all files in the top level of My Drive will be displayed.
|
By default, drive activity for all files in the top level of My Drive will be displayed.
|
||||||
* `fileid <DriveFileID>` - Display drive activity for file `<DriveFileID>`
|
* `fileid <DriveFileID>` - Display drive activity for file `<DriveFileID>`
|
||||||
* `folderid <DriveFolderID>` - Display drive activity for all files in folder `<DriveFolderID>`
|
* `folderid <DriveFolderID>` - Display drive activity for all files in folder `<DriveFolderID>`
|
||||||
* `drivefilename <DriveFileName>` - Display drive activity for the file with name `<DriveFolderID>`
|
* `drivefilename <DriveFileName>` - Display drive activity for the file with name `<DriveFileName>`
|
||||||
* `drivefoldername <DriveFolderName>` - Display drive activity for all files in the folder with name `<DriveFolderName>`
|
* `drivefoldername <DriveFolderName>` - Display drive activity for all files in the folder with name `<DriveFolderName>`
|
||||||
* `query` - Display drive activity for all files/folders selected by the query
|
* `query` - Display drive activity for all files/folders selected by the query
|
||||||
|
|
||||||
|
|||||||
@@ -535,6 +535,14 @@ User: user@domain.com, Delete maximum of 15 Other Contacts
|
|||||||
User: user@domain.com, Other Contact: otherContacts/c6318452176100245073, Deleted
|
User: user@domain.com, Other Contact: otherContacts/c6318452176100245073, Deleted
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Bulk delete Other Contacts
|
||||||
|
|
||||||
|
Let's suppose you have a CSV file (OtherContacts.csv) with at least these two headers: User,resourceName
|
||||||
|
The file can contain multiple users and their other contacts. This is the most API effecient way to delete the contacts.
|
||||||
|
```
|
||||||
|
gam redirect stdout ./DeleteOtherContacts.txt redirect stderr stdout csvkmd users OtherContacts.csv keyfield User datafield resourceName delete othercontacts csvdata resourceName
|
||||||
|
```
|
||||||
|
|
||||||
## Display User Other Contacts
|
## Display User Other Contacts
|
||||||
### Display as an indented list of keys and values.
|
### Display as an indented list of keys and values.
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ For `corpus calendar`, you can specify advanced search options:
|
|||||||
* `minuswords <StringList>`
|
* `minuswords <StringList>`
|
||||||
* Matches only those events that do not contain any of the words in the given set in title, description, location, or attendees.
|
* Matches only those events that do not contain any of the words in the given set in title, description, location, or attendees.
|
||||||
* Entries in the set are considered in "or".
|
* Entries in the set are considered in "or".
|
||||||
* `responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*
|
* `responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*`
|
||||||
* Matches only events for which the custodian gave one of these responses. If the set is empty, there will be no filtering on responses.
|
* Matches only events for which the custodian gave one of these responses. If the set is empty, there will be no filtering on responses.
|
||||||
* `calendarversiondate <Date>|<Time>`
|
* `calendarversiondate <Date>|<Time>`
|
||||||
* Search the current version of the Calendar event, but export the contents of the last version saved before 12:00 AM UTC on the specified date.
|
* Search the current version of the Calendar event, but export the contents of the last version saved before 12:00 AM UTC on the specified date.
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
Print the current version of Gam with details
|
Print the current version of Gam with details
|
||||||
```
|
```
|
||||||
gam version
|
gam version
|
||||||
GAM 7.45.00 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.46.03 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.5 64-bit final
|
Python 3.14.6 64-bit final
|
||||||
macOS Tahoe 26.5.1 arm64
|
macOS Tahoe 26.5.1 arm64
|
||||||
Path: /Users/gamteam/bin/gam7
|
Path: /Users/gamteam/bin/gam7
|
||||||
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||||
@@ -15,9 +15,9 @@ 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.45.00 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.46.03 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.5 64-bit final
|
Python 3.14.6 64-bit final
|
||||||
macOS Tahoe 26.5.1 arm64
|
macOS Tahoe 26.5.1 arm64
|
||||||
Path: /Users/gamteam/bin/gam7
|
Path: /Users/gamteam/bin/gam7
|
||||||
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||||
@@ -27,29 +27,29 @@ 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.45.00 - https://github.com/GAM-team/GAM - pyinstaller
|
GAM 7.46.03 - https://github.com/GAM-team/GAM - pyinstaller
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.5 64-bit final
|
Python 3.14.6 64-bit final
|
||||||
macOS Tahoe 26.5.1 arm64
|
macOS Tahoe 26.5.1 arm64
|
||||||
Path: /Users/gamteam/bin/gam7
|
Path: /Users/gamteam/bin/gam7
|
||||||
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||||
Time: 2026-02-15T07:51:00-08:00
|
Time: 2026-02-15T07:51:00-08:00
|
||||||
Your system time differs from admin.googleapis.com by less than 1 second
|
Your system time differs from admin.googleapis.com by less than 1 second
|
||||||
OpenSSL 4.0.0 14 Apr 2026
|
OpenSSL 4.0.1 9 Jun 2026
|
||||||
arrow 1.4.0
|
arrow 1.4.0
|
||||||
chardet 5.2.0
|
chardet 7.4.3
|
||||||
cryptography 46.0.5
|
cryptography 48.0.0
|
||||||
filelock 3.21.2
|
filelock 3.29.0
|
||||||
google-api-python-client 2.190.0
|
google-api-python-client 2.196.0
|
||||||
google-auth-httplib2 0.3.0
|
google-auth-httplib2 0.4.0
|
||||||
google-auth-oauthlib 1.2.4
|
google-auth-oauthlib 1.4.0
|
||||||
google-auth 2.48.0
|
google-auth 2.53.0
|
||||||
lxml 6.0.2
|
lxml 6.1.1
|
||||||
httplib2 0.31.2
|
httplib2 0.31.2
|
||||||
passlib 1.7.4
|
passlib 1.7.4
|
||||||
pathvalidate 3.3.1
|
pathvalidate 3.3.1
|
||||||
pyscard 2.3.1
|
pyscard 2.3.1
|
||||||
yubikey-manager 5.9.0
|
yubikey-manager 5.9.1
|
||||||
admin.googleapis.com connects using TLSv1.3 TLS_AES_256_GCM_SHA384
|
admin.googleapis.com connects using TLSv1.3 TLS_AES_256_GCM_SHA384
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -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.45.00
|
Latest: 7.46.03
|
||||||
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.45.00
|
7.46.03
|
||||||
```
|
```
|
||||||
In Linux/MacOS you can do:
|
In Linux/MacOS you can do:
|
||||||
```
|
```
|
||||||
@@ -86,9 +86,9 @@ 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.45.00 - https://github.com/GAM-team/GAM
|
GAM 7.46.03 - https://github.com/GAM-team/GAM
|
||||||
GAM Team <google-apps-manager@googlegroups.com>
|
GAM Team <google-apps-manager@googlegroups.com>
|
||||||
Python 3.14.5 64-bit final
|
Python 3.14.6 64-bit final
|
||||||
macOS Tahoe 26.5.1 arm64
|
macOS Tahoe 26.5.1 arm64
|
||||||
Path: /Users/gamteam/bin/gam7
|
Path: /Users/gamteam/bin/gam7
|
||||||
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||||
|
|||||||
Reference in New Issue
Block a user