docs: initial commit

This commit is contained in:
Jay Lee
2023-07-25 23:38:58 +00:00
parent 7d186f2281
commit 7a3b19b64b
145 changed files with 46349 additions and 0 deletions

30
docs/Addresses.md Normal file
View File

@ -0,0 +1,30 @@
# Addresses
- [API documentation](#api-documentation)
- [Display addresses](#display-addresses)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/domains
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/groups
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/resources.calendars
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/users
## Display addresses
Produces a three column CSV file (headers Type, Email, Target) that displays all group and user primary
email addresses and aliases; resource calendar addresses and domain names.
The types are:
```
DomainPrimary, DomainSecondary, DomainAlias
Group, GroupAlias, GroupNEAlias
Resource
SuspendedUser, SuspendedUserAlias, SuspendedUserNEAlias
User, UserAlias, UserNEAlias
```
'NE' is an abbreviation for NonEditable.
```
gam print addresses [todrive <ToDriveAttribute>*]
[domain <DomainName>]
```
By default, groups and users in all domains in the account are selected; this options allows selection of subsets of groups and users:
* `domain <DomainName>` - Limit groups and users to those in `<DomainName>`

890
docs/Administrators.md Normal file
View File

@ -0,0 +1,890 @@
# Administrators
- [Administrator roles documentation](#administrator-roles-documentation)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Display administrative privileges](#display-administrative-privileges)
- [Manage administrative roles](#manage-administrative-roles)
- [Display administrative roles](#display-administrative-roles)
- [Create an administrator](#create-an-administrator)
- [Delete an administrator](#delete-an-administrator)
- [Display administrators](#display-administrators)
## Administrator roles documentation
* https://support.google.com/a/answer/33325?ref_topic=4514341
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/privileges
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/roles
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/roleAssignments
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<GroupItem> ::= <EmailAddress>|<UniqueID>|<String>
<OrgUnitID> ::= id:<String>
<OrgUnitPath> ::= /|(/<String)+
<OrgUnitItem> ::= <OrgUnitID>|<OrgUnitPath>
<Privilege> ::= <String>
<PrivilegeList> ::= "<Privilege>(,<Privilege)*"
<RoleAssignmentID> ::= <String>
<RoleItem> ::= id:<String>|uid:<String>|<String>
<UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
```
## Display administrative privileges
```
gam print privileges [todrive <ToDriveAttribute>*]
gam show privileges
```
Here is the output from `gam show privileges`; use this to find `<Privilege>`.
```
Show 91 Privileges
Privilege: MANAGE_CSE_SETTINGS (1/91)
serviceId: 02pta16n4hxgyp2
serviceName: Unknown
isOuScopable: False
Privilege: MANAGE_PLAY_FOR_WORK_STORE (2/91)
serviceId: 00tyjcwt49hs5nq
serviceName: play_for_work
isOuScopable: False
Privilege: MANAGE_ENTERPRISE_PRIVATE_APPS (3/91)
serviceId: 00tyjcwt49hs5nq
serviceName: play_for_work
isOuScopable: False
Privilege: MANAGE_EXTERNALLY_HOSTED_APK_UPLOAD_IN_PLAY (4/91)
serviceId: 00tyjcwt49hs5nq
serviceName: play_for_work
isOuScopable: False
Privilege: MANAGE_PLAY_FOR_WORK_STORE (5/91)
serviceId: 02w5ecyt3pkeyqi
serviceName: Unknown
isOuScopable: False
Privilege: MANAGE_ENTERPRISE_PRIVATE_APPS (6/91)
serviceId: 02w5ecyt3pkeyqi
serviceName: Unknown
isOuScopable: False
Privilege: MANAGE_EXTERNALLY_HOSTED_APK_UPLOAD_IN_PLAY (7/91)
serviceId: 02w5ecyt3pkeyqi
serviceName: Unknown
isOuScopable: False
Privilege: APP_ADMIN (8/91)
serviceId: 01ci93xb43sd8me
serviceName: Unknown
isOuScopable: True
childPrivileges: 2
Privilege: DELEGATES_READ (1/2)
serviceId: 01ci93xb43sd8me
serviceName: Unknown
isOuScopable: True
Privilege: DELEGATES_WRITE (2/2)
serviceId: 01ci93xb43sd8me
serviceName: Unknown
isOuScopable: True
Privilege: APP_ADMIN (9/91)
serviceId: 03cqmetx3hnlpuf
serviceName: gplus
isOuScopable: False
Privilege: GPLUS_SQUARE_BATCH_ADD (10/91)
serviceId: 03cqmetx3hnlpuf
serviceName: gplus
isOuScopable: False
Privilege: GPLUS_CONTENT_MANAGER_PRIVILEGE (11/91)
serviceId: 03cqmetx3hnlpuf
serviceName: gplus
isOuScopable: False
Privilege: APP_ADMIN (12/91)
serviceId: 039kk8xu49mji9t
serviceName: gmail
isOuScopable: False
Privilege: ACCESS_EMAIL_LOG_SEARCH (13/91)
serviceId: 039kk8xu49mji9t
serviceName: gmail
isOuScopable: False
Privilege: ACCESS_ADMIN_QUARANTINE (14/91)
serviceId: 039kk8xu49mji9t
serviceName: gmail
isOuScopable: False
Privilege: ACCESS_RESTRICTED_QUARANTINE (15/91)
serviceId: 039kk8xu49mji9t
serviceName: gmail
isOuScopable: False
Privilege: APP_ADMIN (16/91)
serviceId: 01tuee744837sjz
serviceName: Unknown
isOuScopable: False
Privilege: MANAGE_COURSE_SETTINGS (17/91)
serviceId: 037m2jsg4g9nirj
serviceName: Unknown
isOuScopable: True
Privilege: MANAGE_LTI_CREDENTIAL_MANAGEMENT_MODE (18/91)
serviceId: 037m2jsg4g9nirj
serviceName: Unknown
isOuScopable: True
Privilege: APP_ADMIN (19/91)
serviceId: 01baon6m1wv6b0p
serviceName: Unknown
isOuScopable: False
Privilege: APP_ADMIN (20/91)
serviceId: 01yyy98l4k9lq4l
serviceName: directory
isOuScopable: False
childPrivileges: 3
Privilege: DIRECTORY_SETTINGS_READONLY (1/3)
serviceId: 01yyy98l4k9lq4l
serviceName: directory
isOuScopable: False
childPrivileges: 2
Privilege: PROFILE_EDITABILITY_READONLY (1/2)
serviceId: 01yyy98l4k9lq4l
serviceName: directory
isOuScopable: False
Privilege: CUSTOM_DIRECTORY_READONLY (2/2)
serviceId: 01yyy98l4k9lq4l
serviceName: directory
isOuScopable: False
Privilege: PROFILE_EDITABILITY_READWRITE (2/3)
serviceId: 01yyy98l4k9lq4l
serviceName: directory
isOuScopable: False
Privilege: CUSTOM_DIRECTORY_READWRITE (3/3)
serviceId: 01yyy98l4k9lq4l
serviceName: directory
isOuScopable: False
Privilege: LDAP_MANAGER (21/91)
serviceId: 02lwamvv18la4iw
serviceName: ldap
isOuScopable: False
Privilege: LDAP_PASSWORD_REBIND (22/91)
serviceId: 02lwamvv18la4iw
serviceName: ldap
isOuScopable: True
childPrivileges: 1
Privilege: LDAP_PASSWORD_REBIND_READONLY
serviceId: 02lwamvv18la4iw
serviceName: ldap
isOuScopable: True
Privilege: APP_ADMIN (23/91)
serviceId: 0319y80a15kueje
serviceName: Unknown
isOuScopable: False
Privilege: APP_ADMIN (24/91)
serviceId: 044sinio4cntx2o
serviceName: Unknown
isOuScopable: False
Privilege: APP_ADMIN (25/91)
serviceId: 01ksv4uv2d2noaq
serviceName: sites
isOuScopable: False
Privilege: ADMIN_DASHBOARD (26/91)
serviceId: 01ci93xb3tmzyin
serviceName: admin
isOuScopable: True
Privilege: SERVICES (27/91)
serviceId: 01ci93xb3tmzyin
serviceName: admin
isOuScopable: False
Privilege: SECURITY_SETTINGS (28/91)
serviceId: 01ci93xb3tmzyin
serviceName: admin
isOuScopable: False
Privilege: SUPPORT (29/91)
serviceId: 01ci93xb3tmzyin
serviceName: admin
isOuScopable: False
Privilege: ADMIN_DOMAIN_SETTINGS (30/91)
serviceId: 01ci93xb3tmzyin
serviceName: admin
isOuScopable: False
Privilege: REPORTS (31/91)
serviceId: 01ci93xb3tmzyin
serviceName: admin
isOuScopable: False
Privilege: ADMIN_DASHBOARD (32/91)
serviceId: 01ci93xb3tmzyin
serviceName: admin
isOuScopable: True
Privilege: SERVICES (33/91)
serviceId: 01ci93xb3tmzyin
serviceName: admin
isOuScopable: False
Privilege: SUPPORT (34/91)
serviceId: 01ci93xb3tmzyin
serviceName: admin
isOuScopable: False
Privilege: REPORTS (35/91)
serviceId: 01ci93xb3tmzyin
serviceName: admin
isOuScopable: False
Privilege: APP_ADMIN (36/91)
serviceId: 03fwokq01e2ht7x
serviceName: Unknown
isOuScopable: False
childPrivileges: 1
Privilege: UDM_NETWORK_ADMIN
serviceId: 03fwokq01e2ht7x
serviceName: Unknown
isOuScopable: True
Privilege: ADMIN_MATTER (37/91)
serviceId: 03l18frh45c63dw
serviceName: vault
isOuScopable: True
Privilege: REMOVE_HOLD (38/91)
serviceId: 03l18frh45c63dw
serviceName: vault
isOuScopable: True
Privilege: MANAGE_SEARCHES (39/91)
serviceId: 03l18frh45c63dw
serviceName: vault
isOuScopable: True
Privilege: MANAGE_EXPORTS (40/91)
serviceId: 03l18frh45c63dw
serviceName: vault
isOuScopable: True
Privilege: MANAGE_RETENTION_POLICY (41/91)
serviceId: 03l18frh45c63dw
serviceName: vault
isOuScopable: False
childPrivileges: 1
Privilege: VIEW_RETENTION_POLICY
serviceId: 03l18frh45c63dw
serviceName: vault
isOuScopable: False
Privilege: AUDIT_SYSTEM (42/91)
serviceId: 03l18frh45c63dw
serviceName: vault
isOuScopable: False
Privilege: ACCESS_ALL_MATTERS (43/91)
serviceId: 03l18frh45c63dw
serviceName: vault
isOuScopable: False
Privilege: APP_ADMIN (44/91)
serviceId: 02afmg282jiquyg
serviceName: device_management
isOuScopable: False
Privilege: APP_ADMIN (45/91)
serviceId: 037m2jsg3ckz96v
serviceName: calendar
isOuScopable: False
childPrivileges: 2
Privilege: CALENDAR_SETTINGS (1/2)
serviceId: 037m2jsg3ckz96v
serviceName: calendar
isOuScopable: False
childPrivileges: 1
Privilege: CALENDAR_SETTINGS_READ
serviceId: 037m2jsg3ckz96v
serviceName: calendar
isOuScopable: False
Privilege: CALENDAR_RESOURCE (2/2)
serviceId: 037m2jsg3ckz96v
serviceName: calendar
isOuScopable: False
childPrivileges: 2
Privilege: ROOM_INSIGHTS_DASHBOARD_ACCESS (1/2)
serviceId: 037m2jsg3ckz96v
serviceName: calendar
isOuScopable: False
Privilege: CALENDAR_RESOURCE_MANAGE (2/2)
serviceId: 037m2jsg3ckz96v
serviceName: calendar
isOuScopable: False
childPrivileges: 1
Privilege: CALENDAR_RESOURCE_READ
serviceId: 037m2jsg3ckz96v
serviceName: calendar
isOuScopable: False
Privilege: APP_ADMIN (46/91)
serviceId: 03dy6vkm2sk0pzo
serviceName: docs
isOuScopable: False
childPrivileges: 5
Privilege: DOCS_TEMPLATE_ADMIN (1/5)
serviceId: 03dy6vkm2sk0pzo
serviceName: docs
isOuScopable: False
Privilege: MIGRATE_TO_TEAM_DRIVE (2/5)
serviceId: 03dy6vkm2sk0pzo
serviceName: docs
isOuScopable: False
Privilege: WRITE_APPS_METADATA_SCHEMAS (3/5)
serviceId: 03dy6vkm2sk0pzo
serviceName: docs
isOuScopable: False
Privilege: VIEW_SITE_DETAILS (4/5)
serviceId: 03dy6vkm2sk0pzo
serviceName: docs
isOuScopable: False
Privilege: MANAGE_CLASSIC_GOOGLE_SITES (5/5)
serviceId: 03dy6vkm2sk0pzo
serviceName: docs
isOuScopable: False
Privilege: APP_ACCESS (47/91)
serviceId: 03cqmetx1vygwki
serviceName: Unknown
isOuScopable: False
Privilege: ORGANIZATION_UNITS_ALL (48/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
childPrivileges: 4
Privilege: ORGANIZATION_UNITS_CREATE (1/4)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: ORGANIZATION_UNITS_RETRIEVE (2/4)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: ORGANIZATION_UNITS_UPDATE (3/4)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: ORGANIZATION_UNITS_DELETE (4/4)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: USERS_ALL (49/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
childPrivileges: 5
Privilege: USERS_CREATE (1/5)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: USERS_RETRIEVE (2/5)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: USERS_UPDATE (3/5)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
childPrivileges: 6
Privilege: USERS_ALIAS (1/6)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: USERS_MOVE (2/6)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: USERS_RESET_PASSWORD (3/6)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: USERS_FORCE_PASSWORD_CHANGE (4/6)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: USERS_ADD_NICKNAME (5/6)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: USERS_SUSPEND (6/6)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: USERS_UPDATE_CUSTOM_ATTRIBUTES_USER_PRIVILEGE_GROUP (4/5)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: USERS_DELETE (5/5)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: GROUPS_ALL (50/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
childPrivileges: 4
Privilege: GROUPS_CREATE (1/4)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: GROUPS_RETRIEVE (2/4)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: GROUPS_UPDATE (3/4)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: GROUPS_DELETE (4/4)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: USER_SECURITY_ALL (51/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: True
Privilege: DATATRANSFER_API_PRIVILEGE_GROUP (52/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: DOMAIN_REGISTRATION_MANAGEMENT (53/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: SCHEMA_MANAGEMENT (54/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
childPrivileges: 1
Privilege: SCHEMA_RETRIEVE
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: LICENSING (55/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
childPrivileges: 1
Privilege: LICENSING_READ
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: BILLING (56/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
childPrivileges: 1
Privilege: BILLING_READ
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: SAML2_SERVICE_PROVIDER (57/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: DOMAIN_MANAGEMENT (58/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: UPGRADE_CONSUMER_CONVERSION (59/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: TRUSTED_DOMAIN_WHITELIST_WRITE (60/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
childPrivileges: 1
Privilege: TRUSTED_DOMAIN_WHITELIST_READ
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: FULL_MIGRATION_ACCESS (61/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
childPrivileges: 1
Privilege: EXECUTE_MIGRATION
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
childPrivileges: 1
Privilege: MODIFY_MIGRATION
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
childPrivileges: 1
Privilege: VIEW_MIGRATION
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: GROUPS_MANAGE_SECURITY_LABEL (62/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: GROUPS_MANAGE_LOCKED_LABEL (63/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: ADMIN_REPORTING_ACCESS (64/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
childPrivileges: 1
Privilege: REPORTING_AUDIT_ACCESS
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: SUPPORT_PRIVILEGE_GROUP (65/91)
serviceId: 00haapch16h1ysv
serviceName: admin_apis
isOuScopable: False
Privilege: APPS_INCIDENTS_FULL_ACCESS (66/91)
serviceId: 02pta16n3efhw69
serviceName: Unknown
isOuScopable: False
childPrivileges: 2
Privilege: APPS_INCIDENTS_READONLY (1/2)
serviceId: 02pta16n3efhw69
serviceName: Unknown
isOuScopable: False
Privilege: APPS_INCIDENTS_VIEW_VIRUSTOTAL_REPORTS (2/2)
serviceId: 02pta16n3efhw69
serviceName: Unknown
isOuScopable: False
Privilege: APP_ADMIN (67/91)
serviceId: 019c6y1840fzfkt
serviceName: classroom
isOuScopable: True
Privilege: ADMIN_OVERSIGHT_MANAGE_CLASSES (68/91)
serviceId: 019c6y1840fzfkt
serviceName: classroom
isOuScopable: True
Privilege: EDU_ANALYTICS_DATA_ACCESS (69/91)
serviceId: 019c6y1840fzfkt
serviceName: classroom
isOuScopable: True
Privilege: APP_ADMIN (70/91)
serviceId: 037m2jsg46www3g
serviceName: Unknown
isOuScopable: False
Privilege: MANAGE_DYNAMITE_SETTINGS (71/91)
serviceId: 03whwml44f3n4vd
serviceName: Unknown
isOuScopable: False
Privilege: MODERATE_DYNAMITE_REPORT (72/91)
serviceId: 03whwml44f3n4vd
serviceName: Unknown
isOuScopable: False
Privilege: MANAGE_DYNAMITE_SPACES (73/91)
serviceId: 03whwml44f3n4vd
serviceName: Unknown
isOuScopable: False
Privilege: APP_ADMIN (74/91)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
childPrivileges: 6
Privilege: MANAGE_CHROME_USER_SETTINGS (1/6)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
childPrivileges: 2
Privilege: MANAGE_CHROME_APPLICATION_SETTINGS (1/2)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: MANAGE_CHROME_WEB_SETTINGS (2/2)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: MANAGE_CHROME_BROWSERS (2/6)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
childPrivileges: 1
Privilege: MANAGED_CHROME_BROWSERS_READ_ONLY
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: VIEW_CHROME_REPORTS (3/6)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
childPrivileges: 4
Privilege: VIEW_CHROME_EXTENSIONS_REPORT (1/4)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: VIEW_CHROME_VERSION_REPORT (2/4)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: VIEW_CHROME_INSIGHTS_REPORT (3/4)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: VIEW_CHROME_PRINTERS_REPORT (4/4)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: MANAGE_PRINTERS (4/6)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: MANAGE_DEVICES (5/6)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
childPrivileges: 2
Privilege: MANAGE_DEVICES_READ_ONLY (1/2)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
childPrivileges: 1
Privilege: TELEMETRY_API
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
childPrivileges: 19
Privilege: TELEMETRY_API_DEVICE (1/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_USER (2/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_AUDIO_REPORT (3/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_BUS_DEVICE_INFO (4/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_OS_REPORT (5/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_CPU_INFO (6/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_CPU_REPORT (7/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_MEMORY_INFO (8/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_MEMORY_REPORT (9/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_GRAPHICS_INFO (10/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_GRAPHICS_REPORT (11/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_BATTERY_INFO (12/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_BATTERY_REPORT (13/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_STORAGE_INFO (14/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_STORAGE_REPORT (15/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_NETWORK_INFO (16/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_NETWORK_REPORT (17/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_DEVICE_ACTIVITY_REPORT (18/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: TELEMETRY_API_PERIPHERALS_REPORT (19/19)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: DEVICE_ACTION_CRD (2/2)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: MANAGE_DEVICE_SETTINGS (6/6)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: True
Privilege: SERVICE_DATA_DOWNLOADER (75/91)
serviceId: 03hv69ve4bjwe54
serviceName: Unknown
isOuScopable: False
Privilege: MANAGE_DIRECTORY_SYNC_SETTINGS (76/91)
serviceId: 0147n2zr1ynkkmf
serviceName: Unknown
isOuScopable: False
childPrivileges: 1
Privilege: READ_DIRECTORY_SYNC_SETTINGS
serviceId: 0147n2zr1ynkkmf
serviceName: Unknown
isOuScopable: False
Privilege: APP_ADMIN (77/91)
serviceId: 0279ka651l5iy5q
serviceName: Unknown
isOuScopable: False
childPrivileges: 1
Privilege: ADMIN_QUALITY_DASHBOARD_ACCESS
serviceId: 0279ka651l5iy5q
serviceName: Unknown
isOuScopable: False
Privilege: SECURITY_SETTINGS (78/91)
serviceId: 00vx122734tbite
serviceName: Unknown
isOuScopable: False
childPrivileges: 1
Privilege: INBOUND_SSO_SETTINGS
serviceId: 00vx122734tbite
serviceName: Unknown
isOuScopable: False
Privilege: VIEW_DLP_RULE (79/91)
serviceId: 02250f4o3hg8pg8
serviceName: Unknown
isOuScopable: False
Privilege: MANAGE_DLP_RULE (80/91)
serviceId: 02250f4o3hg8pg8
serviceName: Unknown
isOuScopable: False
Privilege: APP_ADMIN (81/91)
serviceId: 00nmf14n14wtgcf
serviceName: app_maker
isOuScopable: False
Privilege: VIEW_ALL_PROJECTS (82/91)
serviceId: 00nmf14n14wtgcf
serviceName: app_maker
isOuScopable: False
Privilege: APP_ADMIN (83/91)
serviceId: 02zbgiuw2wdxo5p
serviceName: youtube
isOuScopable: False
Privilege: APP_ADMIN (84/91)
serviceId: 03as4poj2zjehv7
serviceName: Unknown
isOuScopable: False
Privilege: APP_ADMIN (85/91)
serviceId: 02afmg283v5nmx6
serviceName: Unknown
isOuScopable: False
childPrivileges: 1
Privilege: ADMIN_QUALITY_DASHBOARD_ACCESS
serviceId: 02afmg283v5nmx6
serviceName: Unknown
isOuScopable: False
Privilege: APP_ADMIN (86/91)
serviceId: 00upglbi0qz687j
serviceName: takeout
isOuScopable: False
Privilege: CLOUD_PRINT_MANAGER (87/91)
serviceId: 02bn6wsx379ol8g
serviceName: cloud_print
isOuScopable: False
Privilege: MANAGE_AGE_BASED_ACCESS_SETTINGS_AGE_LABEL (88/91)
serviceId: 046r0co22dnadsi
serviceName: Unknown
isOuScopable: True
childPrivileges: 1
Privilege: AGE_BASED_ACCESS_SETTINGS_AGE_LABEL_READ
serviceId: 046r0co22dnadsi
serviceName: Unknown
isOuScopable: True
Privilege: LOGO_PRIVILEGE_GROUP (89/91)
serviceId: 03j2qqm31d4j55e
serviceName: Unknown
isOuScopable: False
Privilege: APP_ADMIN (90/91)
serviceId: 04f1mdlm0ki64aw
serviceName: cros
isOuScopable: True
childPrivileges: 7
Privilege: MANAGE_DEVICES (1/7)
serviceId: 04f1mdlm0ki64aw
serviceName: cros
isOuScopable: True
Privilege: MANAGE_USER_SETTINGS (2/7)
serviceId: 04f1mdlm0ki64aw
serviceName: cros
isOuScopable: True
childPrivileges: 1
Privilege: MANAGE_APPLICATION_SETTINGS
serviceId: 04f1mdlm0ki64aw
serviceName: cros
isOuScopable: True
Privilege: MANAGE_DEVICE_SETTINGS (3/7)
serviceId: 04f1mdlm0ki64aw
serviceName: cros
isOuScopable: True
Privilege: MANAGE_BROWSERS (4/7)
serviceId: 04f1mdlm0ki64aw
serviceName: cros
isOuScopable: True
Privilege: VIEW_EXTENSIONS_REPORT (5/7)
serviceId: 04f1mdlm0ki64aw
serviceName: cros
isOuScopable: True
Privilege: VIEW_VERSION_REPORT (6/7)
serviceId: 04f1mdlm0ki64aw
serviceName: cros
isOuScopable: True
Privilege: MANAGE_PRINTERS (7/7)
serviceId: 04f1mdlm0ki64aw
serviceName: cros
isOuScopable: True
Privilege: APP_ADMIN (91/91)
serviceId: 02et92p02l9sq0n
serviceName: Unknown
isOuScopable: True
```
## Manage administrative roles
```
gam create adminrole <String> privileges all|all_ou|<PrivilegeList> [description <String>]
gam update adminrole <RoleItem> [name <String>] [privileges all|all_ou|<PrivilegeList>] [description <String>]
gam delete adminrole <RoleItem>
```
* `privileges all` - All defined privileges
* `privileges all_ou` - All defined privileges than can be scoped to an OU
* `privileges <PrivilegeList>` - A specific list of privileges
## Display administrative roles
```
gam info adminrole <RoleItem> [privileges]
gam print adminroles|roles [todrive <ToDriveAttribute>*] [privileges]
gam show adminroles|roles [todrive <ToDriveAttribute>*] [privileges]
```
* `privileges` - Display privileges associated with each role
## Create an administrator
```
gam create admin <EmailAddress>|<UniqueID> <RoleItem> customer|(org_unit <OrgUnitItem>)
[condition securitygroup|nonsecuritygroup]
```
* `customer` - The administrator can manage all organization units
* `org_unit <OrgUnitItem>` - The administrator can manage the specified organization unit
The option `condition` limits the conditions for delegate admin access. This currently only works with the _GROUPS_EDITOR_ROLE and _GROUPS_READER_ROLE roles.
* `condition securitygroup` - limit the delegated admin to managing security groups
* `condition nonsecuritygroup` - limit the delegated admin to managing non-security groups
## Delete an administrator
```
gam delete admin <RoleAssignmentId>
```
## Display administrators
```
gam print admins [todrive <ToDriveAttribute>*]
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [privileges]
gam show admins
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [privileges]
```
By default, all administrators and roles are displayed; choose from the following
options to limit the display:
* `user <UserItem>` - Display only this administrator
* `role <RoleItem>` - Display only administrators with this role
* `condition` - Display any conditions associated with a role assignment
* `privileges` - Display privileges associated with each role assignment
In versions prior to 6.07.01, specification of both `user <UserItem>`
and `role <RoleItem>` generated no output due to an undocumented API rule that disallows both.

94
docs/Alert-Center.md Normal file
View File

@ -0,0 +1,94 @@
# Alert Center
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Introduction](#introduction)
- [Manage alerts](#manage-alerts)
- [Display alerts](#display-alerts)
- [Manage alert feedback](#manage-alert-feedback)
- [Display alert feedback](#display-alert-feedback)
## API documentation
* https://developers.google.com/admin-sdk/alertcenter/reference/rest/
* https://developers.google.com/admin-sdk/alertcenter/guides/query-filters
* https://developers.google.com/admin-sdk/alertcenter/reference/filter-fields
## Definitions
```
<AlertID> ::= <String>
<QueryAlert> ::= <String> See: https://developers.google.com/admin-sdk/alertcenter/guides/query-filters
```
## Introduction
For an introduction, start here: https://support.google.com/a/answer/9105393
This API is in beta, most things seem to work although the filter queries don't all work, in particular those that
select alertId and feedbackId.
To use these commands you must update your gam project and service account authorization.
```
gam update project
gam user user@domain.com check serviceaccount
```
## Manage alerts
```
gam delete alert <AlertID>
gam undelete alert <AlertID>
```
## Display alerts
```
gam info alert <AlertID> [formatjson]
gam show alerts [filter <QueryAlert>] [orderby createtime [ascending|descending]]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print alerts [todrive <ToDriveAttributes>*] [filter <QueryAlert>] [orderby createtime [ascending|descending]]
[formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
### Eliminate unwanted fields
You can use [CSV Print Filtering](CSV-Print-Filtering) to reduce the amount of output.
This command will drop all of the data.messages columns.
```
gam config csv_output_header_drop_filter "^data.messages" redirect csv alerts.csv print alerts
```
## Manage alert feedback
```
gam create alertfeedback <AlertID> not_useful|somewhat_useful|very_useful
```
## Display alert feedback
```
gam show alertfeedback [alert <AlertID>] [filter <QueryAlert>] [orderby createtime [ascending|descending]]
[formatjson]
```
By default, Gam displays feedback for all alerts.
* `alert <AlertID>` - Display feedback for the selected alert
* `filter <QueryAlert>` - Display feebback for the filtered alerts
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print alertfeedback [todrive <ToDriveAttributes>*] [alert <AlertID>] [filter <QueryAlert>] [orderby createtime [ascending|descending]]
[formatjson [quotechar <Character>]]
```
By default, Gam displays feedback for all alerts.
* `alert <AlertID>` - Display feedback for the selected alert
* `filter <QueryAlert>` - Display feebback for the filtered alerts
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

163
docs/Aliases.md Normal file
View File

@ -0,0 +1,163 @@
# Aliases
- [API documentation](#api-documentation)
- [Query documentation](#query-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [Create an alias for a target](#create-an-alias-for-a-target)
- [Update an alias to point to a new target](#update-an-alias-to-point-to-a-new-target)
- [Delete an alias regardless of the target](#delete-an-alias-regardless-of-the-target)
- [Remove aliases from a specified target](#remove-aliases-from-a-specified-target)
- [Delete all of a user's aliases](#delete-all-of-a-users-aliases)
- [Display aliases](#display-aliases)
- [Bulk delete aliases](#bulk-delete-aliases)
- [Bulk reassign aliases](#bulk-reassign-aliases)
- [Determine if an address is a user, user alias, group or group alias](#determine-if-an-address-is-a-user-user-alias-group-or-group-alias)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/users.aliases
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/groups.aliases
## Query documentation
* https://developers.google.com/admin-sdk/directory/v1/guides/search-users
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<EmailAddressList> ::= "<EmailAddress>(,<EmailAddress>)*"
<EmailAddressEntity> ::= <EmailAddressList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<UniqueID> ::= id:<String>
```
## Create an alias for a target
```
gam create alias|aliases <EmailAddressEntity> user|group|target <UniqueID>|<EmailAddress>
[verifynotinvitable]
```
`<EmailAddressEntity>` are the aliases, `<EmailAddress>` is the target.
The `verifynotinvitable` option causes GAM to verify that the alias email address being created is not that of an unmanaged account;
if it is, the command is not performed.
### Example
To allow Robert to also receive mail as Bob:
```
gam create alias bob[@yourdomain.com] user robert[@yourdomain.com]
```
## Update an alias to point to a new target
The existing alias is deleted and a new alias is created.
```
gam update alias|aliases <EmailAddressEntity> user|group|target <UniqueID>|<EmailAddress>
[notargetverify]
```
`<EmailAddressEntity>` are the aliases, `<EmailAddress>` is the target.
By default, GAM makes additional API calls to verify that the target email address exists before updating the alias;
if you know that the target exists, you can suppress the verification with `notargetverify.
## Delete an alias regardless of the target
```
gam delete alias|aliases [user|group|target] <EmailAddressEntity>
```
`<EmailAddressEntity>` are the aliases.
## Remove aliases from a specified target
```
gam remove alias|aliases <EmailAddress> user|group <EmailAddressEntity>
```
`<EmailAddress>` is the target, `<EmailAddressEntity>` are the aliases.
## Delete all of a user's aliases
```
gam <UserTypeEntity> delete aliases
```
## Display aliases
Display a specific alise.
```
gam info alias|aliases <EmailAddressEntity>
```
Display selected aliases.
```
gam print aliases [todrive <ToDriveAttribute>*]
[domain <DomainName>] [(query <QueryUser>)|(queries <QueryUserList>)]
[user|users <EmailAddressList>] [group|groups <EmailAddressList>]
[select <UserTypeEntity>]
[aliasmatchpattern <RegularExpression>]
[shownoneditable] [nogroups] [nousers]
[onerowpertarget] [delimiter <Character>]
[suppressnoaliasrows]
(addcsvdata <FieldName> <String>)*
```
By default, group and user aliases in all domains in the account are selected; these options allow selection of subsets of aliases:
* `domain <DomainName>` - Limit aliases to those in `<DomainName>`
* `(query <QueryUser>)|(queries <QueryUserList>)` - Print aliases for selected users
* `user|users <EmailAddressList>` - Print aliases for users in `<EmailAddressList`
* `select <UserTypeEntity>` - Print aliases for users in `<UserTypeEntity>`
* `group|groups <EmailAddressList>` - Print aliases for groups in `<EmailAddressList`
* `aliasmatchpattern <RegularExpression>` - Print aliases that match a pattern
* `nogroups` - Print only user aliases
* `nousers` - Print only group aliases
By default, the CSV output has three columns: `Alias,Target,TargetType`; if a target
has multiple aliases, there will be multiple rows, one per alias.
Use `shownoneditable` to list non-editable alias email addresses; these are typically outside of the account's primary domain or subdomains.
This adds the column `NonEditableAlias`.
Specifying `onerowpertarget` changes the three columns to: `Target,TargetType,Aliases`; all aliases for the target are listed in the
`Aliases` column. If `shownoneditable` is specified, there will be a fourth column `NonEditableAliases` with a list of non-editable aliases.
By default, the aliases in a list are separated by the `csv_output_field_delimiter' from `gam.cfg`.
* `delimiter <Character>` - Separate aliases in a list with `<Character>`
Specifying both `onerowpertarget` and `suppressnoaliasrows` causes GAM to not display any targets that have no aliases.
## Bulk delete aliases
You can bulk delete aliases as follows; use `(query <QueryUser>)|(queries <QueryUserList>)` and
`aliasmatchpattern <RegularExpression>` as desired.
```
gam redirect csv ./OldDomainAliases.csv print aliases aliasmatchpattern ".*@olddomain.com" onerowpertarget suppressnoaliasrows
gam redirect stdout ./DeleteAliases.txt multiprocess redirect stderr stdout csv ./OldDomainAliases.csv gam remove aliases "~Target" "~TargetType" "~Aliases"
```
## Bulk reassign aliases
You can bulk reassign aliases as follows. Make a CSV file ReassignAliases.csv with two columns: OldTarget,NewTarget.
From this CSV file, all of the aliases for the users in the OldTarget column will be listed with an additional column showing the NewTarget.
```
gam redirect stdout ./GetAliases.txt multiprocess redirect stderr stdout redirect csv ./ReassignAliases.csv gam print aliases user "~OldTarget" addcsvdata NewTarget "~NewTarget"
```
If an OldTarget's aliases are to be reassigned to more than the one NewTarget, edit ReassignAliases.csv and make changes as required.
```
gam redirect stdout ./ReassignAliases.txt multiprocess redirect stderr stdout csv ReassignAliases.csv gam update alias "~Alias" user "~NewTarget"
```
## Determine if an address is a user, user alias, group or group alias
```
gam whatis <EmailItem> [noinfo] [noinvitablecheck]
```
The first line of output is: `<TypeOfEmailItem>: <EmailItem>`
There is additional output based on `<TypeOfEmailItem>`:
* User - `gam info user <EmailItem>`
* Group - `gam info group <EmailItem>`
* User Alias - `gam info alias <EmailItem>`
* Group Alias - `gam info alias <EmailItem>`
* User Invitation - `gam info userinvitation <EmailItem>`
The `noinfo` argument suppresses the additional output.
The `noinvitablecheck` argument suppresses the user invitation check
to avoid exceeding quota limits when checking a large number of addresses.
The return code is set based on `<TypeOfEmailItem>`:
* User - 20
* User Alias - 21
* Group - 22
* Group Alias - 23
* User Invitation - 24
* Unknown - 59

984
docs/Authorization.md Normal file
View File

@ -0,0 +1,984 @@
# Authorization
- [Introduction](#introduction)
- [Headless computers and Cloud Shells](#headless-computers-and-cloud-shells)
- [Version 5 Update](#version-5-update)
- [API documentation](#api-documentation)
- [Python Regular Expressions](Python-Regular-Expressions)
- [Definitions](#definitions)
- [Manage Projects](#manage-projects)
- [Authorize a super admin to create projects](#authorize-a-super-admin-to-create-projects)
- [Create a new GCP project folder](#create-a-new-gcp-project-folder)
- [Create a new project for GAM authorization](#create-a-new-project-for-gam-authorization)
- [Use an existing project for GAM authorization](#use-an-existing-project-for-gam-authorization)
- [Update an existing project for GAM authorization](#update-an-existing-project-for-gam-authorization)
- [Delete an existing project for GAM authorization](#delete-an-existing-project-for-gam-authorization)
- [Display projects](#display-projects)
- [Manage Client credentials](#manage-client-credentials)
- [Create Client credentials](#create-client-credentials)
- [Refresh Client credentials](#refresh-client-credentials)
- [Update Client credentials](#update-client-credentials)
- [Delete Client credentials](#delete-client-credentials)
- [Verify Client credentials](#verify-client-credentials)
- [Export Client credentials](#export-client-credentials)
- [Manage Service Accounts](#manage-service-accounts)
- [Add Service Accounts to projects](#add-service-accounts-to-projects)
- [Delete Service Accounts from projects](#delete-service-accounts-from-projects)
- [Display Service Accounts for projects](#display-service-accounts-for-projects)
- [Manage Service Account keys](#manage-service-account-keys)
- [Create a new Service Account key](#create-a-new-service-account-key)
- [Update an existing Service Account key](#update-an-existing-service-account-key)
- [Replace all existing Service Account keys](#replace-all-existing-service-account-keys)
- [Delete Service Account keys](#delete-service-account-keys)
- [Display Service Account keys](#display-service-account-keys)
- [Manage Service Account access](#manage-service-account-access)
- [Full Service Account access](#full-service-account-access)
- [Selective Service Account access](#selective-service-account-access)
- [Configure Limited access](#configure-limited-access)
- [Limited Client access](#limited-client-access)
- [No Client access](#no-client-access)
- [Limited Service Account access](#limited-service-account-access)
- [todrive Service Account access](#todrive-service-account-access)
- [No Service Account access possible](#no-service-account-access-possible)
- [Test Client and Service Account access on your computer](#test-client-and-service-account-access-on-your-computer)
- [Install GAM on the limited users computer](#install-gam-on-the-limited-users-computer)
- [Test Client and Service Account access on the non-administrator computer](#test-client-and-service-account-access-on-the-non-administrator-computer)
- [Unselect limited section on your computer.](#unselect-limited-section-on-your-computer)
## Introduction
GAM requires authorization to perform tasks on your domain; the tasks break down into two categories:
* Client - Manipulate objects in the domain; the Client acts on its own behalf to perform the tasks. Examples: add a user, update a group, delete a class, share a printer.
* Service Account - Manipulate objects that belong to users; the Service Account acts on behalf of the user to perform the tasks. Examples: view user files, calendars.
You create projects that define these authorizations.
Verify the following steps:
* See https://support.google.com/a/answer/9197205?hl=en
* Access the admin console and go to Apps -> Additional Google Services
* Look for the service "Google Cloud Platform", click it
* Expand "Service status"
* Select the OU in the left that contains the super admin you'll be using
* Make sure that "Service status" is ON
* If groups are used to authenticate access, make sure the super admin is in one of the groups
* Collapse "Service status"
* Expand "Cloud Resource Manager API settings"
* Make sure that "Allow users to create projects" is checked
Verify that all scopes are available:
* Access the admin console and go to Apps -> Additional Google Services
* If this line is present: `Access to additional services without individual control for all organizational units is turned Off`
* Click "CHANGE"
* Select "ON for everyone"
* Click "SAVE"
Verify that internal apps are trusted.
* Access the admin console and go to Security -> Access and data control -> API Controls
* Check that "Trust internal, domain-owned apps" is present in the **Settings** section
* Click "SAVE"
If you run a Google Workspace Education SKU, verify that Classroom API is enabled if required.
* Access the admin console and go to Apps -> Google Workspace - Classroom
* Expand "Data access"
* Check "Users can authorize apps to access their Google Classroom data."
* Click "SAVE"
If you run a Google Workspace Education SKU, verify that the super admin you'll be using is in an OU where "All users are 18 or older".
* Access the admin console and go to Accounts -> Account settings
* Expand "Age based access settings"
* Select the OU containing the super admin
* Choose "All users are 18 or older"
* Click "SAVE"
Verify whether the super admin you'll be using is in an OU where reauthentication is required.
* Access the admin console and go to Security -> Overview
* Scroll down and open Google Cloud session control section
* Select the OU containing the super admin
* If Require reauthentication is selected and Exempt Trusted apps is not checked, you'll have to do `gam oauth create` at whatever frequency is specified
* If that sounds unappealing, check Exempt Trusted apps
* Click "OVERRIDE"
* Follow the steps below to mark GAM as a trusted app
Based on your domain policies, you may have to mark GAM as a trusted app. These steps are performed after a project is created.
* Access the admin console and go to Security -> Access and data control -> API controls
* Check Trust internal, domain-owned apps
* Click **Manage third-party app access**
* Click Add app and select **OAuth App Name Or Client ID**
* Paste client_id value from client_secrets.json
* Click Search
* Click Select at right end of line referencing GAM
* Check box to the left of the line with GAM client ID
* Click Select
* Keep the default scope domain.com (all users) or select an org unit that includes your GAM admin
* Click Next/Continue
* Click Trusted: App can request access to all Google data
* Click Next/Continue
* Click Finish
## Headless computers and Cloud Shells
With many thanks to Jay, `gam oauth create` now uses a new client access authentication flow
as required by Google for headless computers/cloud shells; this is required as of February 28, 2022.
* See: https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html
* OAuth out-of-band (oob) flow will be deprecated
## Version 5 Update
GAM version `5.00.00` replaced the deprecated `oauth2client` library with the `google-auth` library.
This change requires a one-time update of the client access file `oauth2.txt`; GAM will continue
to use the old version of `oauth2.txt` until you perform the update. There is a small performance
impact until the update is performed. However, you can't use the updated version of `oauth2.txt`
in prior versions of GAM; if you want to run GAM `5.00.00` and prior versions of GAM,
do not perform the update until you no longer need to run the prior versions of GAM.
If you are running any GAM version `4.85.00` or later, perform the following command
after installing `5.00.00` to perform the update.
```
gam oauth refresh
```
If you are running any GAM version before `4.85.00`, perform the following command
after installing `5.00.00` to perform the update.
```
gam oauth update
```
## API documentation
* https://cloud.google.com/resource-manager/docs/creating-managing-organization#adding_an_organization_administrator
* https://cloud.google.com/service-usage/docs/reference/rest
* https://cloud.google.com/resource-manager/reference/rest/v3/projects/create
* https://cloud.google.com/resource-manager/reference/rest/v3/projects/list
* https://cloud.google.com/resource-manager/reference/rest/v3/projects/getIamPolicy
* https://cloud.google.com/iam/docs/understanding-service-accounts
* https://developers.google.com/identity/protocols/oauth2
* https://developers.google.com/identity/protocols/googlescopes
* https://developers.google.com/admin-sdk/directory/v1/guides/delegation
* https://support.google.com/a/answer/7281227?hl=en#zippy=%2Cmanage-access-to-apps-trusted-limited-or-blocked
## Definitions
```
<APIScopeURL> ::= <String>
<APIScopeURLList> ::= "<APIScopeURL>(,<APIScopeURL>)*"
<ProjectID> ::= <String>
Must match this Python Regular Expression: [a-z][a-z0-9-]{4,28}[a-z0-9]
<ProjectIDList> ::= "<ProjectID>(,<ProjectID>)*"
<ProjectIDEntity> ::=
current | gam | <ProjectID> | (filter <String>) |
(select <ProjectIDList> | <FileSelector> | <CSVFileSelector>)
<ProjectName> ::= <String>
Must match this Python Regular Expression: [a-zA-Z0-9 '"!-]{4,30}
<ServiceAccountName> ::= <String>
Must match this Python Regular Expression: [a-z][a-z0-9-]{4,28}[a-z0-9]
<ServiceAccountDisplayName> ::= <String>
Maximum of 100 characters
<ServiceAccountDescrition> ::= <String>
Maximum of 256 characters
<ServiceAccountEmail> ::= <ServiceAccountName>@<ProjectID>.iam.gserviceaccount.com
<ServiceAccountUniqueID> ::= <Number>
<ServiceAccountKey> ::= <String>
```
## Manage Projects
In all of the project commands, the Google Workspace admin/GCP project manager `<EmailAddress>` can be omitted; you will be prompted for a value.
You must enter a full address, i.e., user@domain.com; you will be required to enter the password.
For `print|show projects`, you can eliminate the password requirement by enabling the following scope in `gam update serviceaccount`;
GAM will then use Service Account access to display projects.
```
[*] 9) Cloud Resource Manager API v3
```
## Authorize a super admin to create projects
If you try to create a project and get an error saying that the admin you specified is not authorized to create projects,
perform these steps and then retry the create project command.
* Login as an existing super admin at cloud.console.google.com
* In the upper left click the three lines to the left of Google Cloud and select IAM & Admin
* Under IAM & Admin select IAM
* Click the down arrow in the box to the right of Google Cloud
* Click the three dots at the right and select IAM/Permissions
* Now you should be at "Permissions for organization ..."
* Click on Grant Access
* Enter the new admin address in Principals
* Click in the Select a role box
* Type project creator in the Filter box
* Click Project Creator
* Click Save
## Create a new GCP project folder
This folder can be used in a subsequent `gam create project parent <String>` command.
```
gam create gcpfolder <String>
gam create gcpfolder [admin <EmailAddress] folder <String>
```
## Create a new project for GAM authorization
Create a new project to create and download two files: `client_secrets.json` for the Client and `oauth2service.json` for the Service Account.
On-screen instructions lead you through the process.
### Default values
* `<AppName>` - "GAM"
* `<ProjectID>` - "gam-project-abc-def-jki" where "abc-def-ghi" are randomly generated
* `<ProjectName>` - "GAM Project"
* `<ServiceAccountName>` - `<ProjectID>`
* `<ServiceAccountDisplayName>` - `<ProjectName>`
* `<ServiceAccountDescription>` - `<ServiceAccountDisplayName>`
### Basic
Create a project with default values for the project and service account.
```
gam create project [<EmailAddress>] [<ProjectID>]
```
* `<EmailAddress>` - Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
* `<ProjectID>` - A new Google project ID; if omitted, a default value will be used
### Advanced
Create a project with user-specified values for the project and service account.
```
gam create project [admin <EmailAddress>] [project <ProjectID>]
[appname <String>] [supportemail <EmailAddress>]
[projectname <ProjectName>] [parent <String>]
[saname <ServiceAccountName>] [sadisplayname <ServiceAccountDisplayName>]
[sadescription <ServiceAccountDescription>]
```
* `admin <EmailAddress>` - Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
* `appname <String>` - Application name, defaults to `GAM`
* `supportemail <EmailAddress>` - Administrator to contact about GAM authentication, defaults to `admin <EmailAddress>`
* `project <ProjectID>` - A new Google project ID; if omitted, a default value will be used
* `projectname <ProjectName>` - Google project name, defaults to "GAM Project"
* `parent <String>` - A Resource Manager folder name
* `saname <ServiceAccountName>` - Service account name; combined with `<ProjectID>` to form `<ServiceAccountEmail>`
* `sadisplayname <ServiceAccountDisplayName>` - Service account display name
* `sadescription <ServiceAccountDescription>` - Service account description
## Use an existing project for GAM authorization
Use an existing project to create and download two files: `client_secrets.json` for the Client and `oauth2service.json` for the Service Account.
### Default values
* `<ServiceAccountName>` - `<ProjectID>`
* `<ServiceAccountDisplayName>` - `<ProjectName>`
* `<ServiceAccountDescription>` - `<ServiceAccountDisplayName>`
### Basic
Use an existing project with default values for the service account. This is typically used when
the system administrators have created a basic project and you now want to configure it as a GAM project.
```
gam use project [<EmailAddress>] [project <ProjectID>]
```
* `<EmailAddress>` - Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
* `<ProjectID>` - An existing Google project ID; if omitted, you will be prompted for the ID
### Advanced
Use an existing project with user-specified values for the service account. If the project is already
a GAM project you must use `saname <ServiceAccountName>` as the existing service account information
can not be re-downloaded.
```
gam use project [admin <EmailAddress>] [project <ProjectID>]
[saname <ServiceAccountName>] [sadisplayname <ServiceAccountDisplayName>]
[sadescription <ServiceAccountDescription>]
```
* `admin <EmailAddress>` - Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
* `project <ProjectID>` - An existing Google project ID; if omitted, you will be prompted for the ID
* `saname <ServiceAccountName>` - Service account name; combined with `<ProjectID>` to form `<ServiceAccountEmail>`
* `sadisplayname <ServiceAccountDisplayName>` - Service account display name
* `sadescription <ServiceAccountDescription>` - Service account description
## Update an existing project for GAM authorization
This command is used when GAM has added new capabilities that require additional APIs to be added to your project.
```
gam update project [[admin] <EmailAddress>] [<ProjectIDEntity>]
```
* `<EmailAddress>` - A Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `current` - The project referenced in `client_secret.json`; this is the default
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
## Delete an existing project for GAM authorization
```
gam delete project [[admin] <EmailAddress>] [<ProjectIDEntity>]
```
* `<EmailAddress>` - A Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `current` - The project referenced in `client_secret.json`; this is the default
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
## Display projects
Display the current Project ID.
```
gam info currentprojectid
```
Display Google API projects as an indented list of keys and values.
```
gam show projects [[admin] <EmailAddress>] [all|<ProjectIDEntity>]
[states all|active|deleterequested] [showiampolicies 0|1|3]
```
* `<EmailAddress>` - A Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `all` - All projects accessible by the administrator; this is the default
* `current` - The project referenced in `client_secret.json`
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
* `states all|active|deleterequested` - Limit display to projects based on state; the default is `active`
Use the `showiampolicies 0|1|3` option to display IAM policy information for the project.
Display Google API projects as columns of fields.
```
gam print projects [[admin] <EmailAddress>] [all|<ProjectIDEntity>] [todrive <ToDriveAttribute>*]
[states all|active|deleterequested] [showiampolicies 0|1|3 [onememberperrow]]
[delimiter <Character>]] [[formatjson [quotechar <Character>]]
```
* `<EmailAddress>` - A Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `all` - All projects accessible by the administrator; this is the default
* `current` - The project referenced in `client_secret.json`
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
* `states all|active|deleterequested` - Limit display to projects based on state; the default is `active`
Use the `showiampolicies 0|1|3` option to display IAM policy information for the project. Each role in the policy will be displayed on
a separate row; by default, all members will be shown on that row. By default, the members are separated by
the `csv_output_field_delimiter` from `gam.cfg`.
* `delimiter <Character>` - Separate list items with `<Character>`
Use the `onememberperrow` option to show separate rows for each role/member combination.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Manage Client credentials
## Create Client credentials
```
gam oauth|oauth2 create|request [<EmailAddress>]
gam oauth|oauth2 create|request [admin <EmailAddress>] [scopes <APIScopeURLList>]
```
* `<EmailAddress>` - A Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
* `scopes <APIScopeURLList>` - A set of specific scopes; if omitted, you will be prompted to select your desired scopes.
You select a list of scopes, GAM uses a browser to get final authorization from Google for these scopes and
writes the credentials into the file oauth2.txt.
```
gam oauth create
Select the authorized scopes by entering a number.
Append an 'r' to grant read-only access or an 'a' to grant action-only access.
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
[*] 2) Chrome Management API - Telemetry read only
[*] 3) Chrome Management API - read only
[*] 4) Chrome Policy API (supports readonly)
[*] 5) Chrome Printer Management API (supports readonly)
[*] 6) Chrome Version History API
[*] 7) Classroom API - Course Announcements (supports readonly)
[*] 8) Classroom API - Course Topics (supports readonly)
[*] 9) Classroom API - Course Work/Materials (supports readonly)
[*] 10) Classroom API - Course Work/Submissions (supports readonly)
[*] 11) Classroom API - Courses (supports readonly)
[*] 12) Classroom API - Profile Emails
[*] 13) Classroom API - Profile Photos
[*] 14) Classroom API - Rosters (supports readonly)
[*] 15) Classroom API - Student Guardians (supports readonly)
[*] 16) Cloud Identity Groups API (supports readonly)
[*] 17) Cloud Storage (Vault Export - read only)
[*] 18) Contact Delegation API (supports readonly)
[*] 19) Contacts API - Domain Shared and Users and GAL
[*] 20) Data Transfer API (supports readonly)
[*] 21) Directory API - Chrome OS Devices (supports readonly)
[*] 22) Directory API - Customers (supports readonly)
[*] 23) Directory API - Domains (supports readonly)
[*] 24) Directory API - Groups (supports readonly)
[*] 25) Directory API - Mobile Devices Directory (supports readonly and action)
[*] 26) Directory API - Organizational Units (supports readonly)
[*] 27) Directory API - Resource Calendars (supports readonly)
[*] 28) Directory API - Roles (supports readonly)
[*] 29) Directory API - User Schemas (supports readonly)
[*] 30) Directory API - User Security
[*] 31) Directory API - Users (supports readonly)
[*] 32) Email Audit API
[*] 33) Groups Migration API
[*] 34) Groups Settings API
[*] 35) License Manager API
[*] 36) People API (supports readonly)
[*] 37) People Directory API - read only
[ ] 38) Pub / Sub API
[*] 39) Reports API - Audit Reports
[*] 40) Reports API - Usage Reports
[ ] 41) Reseller API
[*] 42) Site Verification API
[*] 43) Sites API
[*] 44) Vault API (supports readonly)
s) Select all scopes
u) Unselect all scopes
e) Exit without changes
c) Continue to authorization
Please enter 0-42[a|r] or s|u|e|c:
Enter your Google Workspace admin email address? admin@domain.com
Go to the following link in a browser on this computer or on another computer:
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=423565144751-10lsdt2lgnsch9jmdhl35uq4617u1ifp&redirect_uri=http%3A%2F%2F127.0.0.1%3A8080%2F&scope=...
If you use a browser on another computer, you will get a browser error that the site can't be reached AFTER you
click the Allow button, paste "Unable to connect" URL from other computer (only URL data up to &scope required):
Enter verification code or paste "Unable to connect" URL from other computer (only URL data up to &scope required):
The authentication flow has completed.
Client OAuth2 File: /Users/admin/GAMConfig/oauth2.txt, Created
```
## Update Client credentials
```
gam oauth update [<EmailAddress>]
gam oauth update [admin <EmailAddress>]
```
* `<EmailAddress>` - A Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Read API scopes from any version of `oauth2.txt` and select a list of APIs; GAM uses a browser to get final authorization from Google for these APIs and
writes the credentials into the file `oauth2.txt`.
```
gam oauth update
Select the authorized scopes by entering a number.
Append an 'r' to grant read-only access or an 'a' to grant action-only access.
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
[*] 2) Chrome Management API - Telemetry read only
[*] 3) Chrome Management API - read only
[*] 4) Chrome Policy API (supports readonly)
[*] 5) Chrome Printer Management API (supports readonly)
[*] 6) Chrome Version History API
[*] 7) Classroom API - Course Announcements (supports readonly)
[*] 8) Classroom API - Course Topics (supports readonly)
[*] 9) Classroom API - Course Work/Materials (supports readonly)
[*] 10) Classroom API - Course Work/Submissions (supports readonly)
[*] 11) Classroom API - Courses (supports readonly)
[*] 12) Classroom API - Profile Emails
[*] 13) Classroom API - Profile Photos
[*] 14) Classroom API - Rosters (supports readonly)
[*] 15) Classroom API - Student Guardians (supports readonly)
[*] 16) Cloud Identity Groups API (supports readonly)
[*] 17) Cloud Storage (Vault Export - read only)
[*] 18) Contact Delegation API (supports readonly)
[*] 19) Contacts API - Domain Shared and Users and GAL
[*] 20) Data Transfer API (supports readonly)
[*] 21) Directory API - Chrome OS Devices (supports readonly)
[*] 22) Directory API - Customers (supports readonly)
[*] 23) Directory API - Domains (supports readonly)
[*] 24) Directory API - Groups (supports readonly)
[*] 25) Directory API - Mobile Devices Directory (supports readonly and action)
[*] 26) Directory API - Organizational Units (supports readonly)
[*] 27) Directory API - Resource Calendars (supports readonly)
[*] 28) Directory API - Roles (supports readonly)
[*] 29) Directory API - User Schemas (supports readonly)
[*] 30) Directory API - User Security
[*] 31) Directory API - Users (supports readonly)
[*] 32) Email Audit API
[*] 33) Groups Migration API
[*] 34) Groups Settings API
[*] 35) License Manager API
[*] 36) People API (supports readonly)
[*] 37) People Directory API - read only
[ ] 38) Pub / Sub API
[*] 39) Reports API - Audit Reports
[*] 40) Reports API - Usage Reports
[ ] 41) Reseller API
[*] 42) Site Verification API
[*] 43) Sites API
[*] 44) Vault API (supports readonly)
s) Select all scopes
u) Unselect all scopes
e) Exit without changes
c) Continue to authorization
Please enter 0-42[a|r] or s|u|e|c:
Enter your Google Workspace admin email address? admin@domain.com
Go to the following link in a browser on this computer or on another computer:
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=423565144751-10lsdt2lgnsch9jmdhl35uq4617u1ifp&redirect_uri=http%3A%2F%2F127.0.0.1%3A8080%2F&scope=...
If you use a browser on another computer, you will get a browser error that the site can't be reached AFTER you
click the Allow button, paste "Unable to connect" URL from other computer (only URL data up to &scope required):
Enter verification code or paste "Unable to connect" URL from other computer (only URL data up to &scope required):
The authentication flow has completed.
Client OAuth2 File: /Users/admin/GAMConfig/oauth2.txt, Created
```
If you have multiple sections in `gam.cfg` that reference different `oauth2.txt` files, perform an update on each section:
```
gam select aaa oauth update
gam select bbb oauth update
...
```
## Refresh Client credentials
If necessary, update `oauth2.txt` from versions of GAM before `5.00.00`.
Refresh the expiration time in `oauth2.txt`.
```
gam oauth refresh
```
If you have multiple sections in `gam.cfg` that reference different `oauth2.txt` files, perform a refresh on each section:
```
gam select aaa oauth refresh
gam select bbb oauth refresh
...
```
## Delete Client credentials
```
gam oauth|oauth2 delete|revoke
```
Revoke the credentials in the file `oauth2.txt` and then delete the file.
## Verify Client credentials
```
<AccessToken> ::= <String>
<IDToken> ::= <String>
gam oauth|oauth2 info|verify [showsecret] [accesstoken <AccessToken> idtoken <IDToken>] [showdetails]
```
The Client Secret is not shown by default, user `showsecret` to have it displayed.
These options are used for debugging: `accesstoken <AccessToken> idtoken <IDToken> showdetails`.
## Export Client credentials
Export `oauth2.txt` in JSON form.
```
gam oauth|oauth2 export [<FileName>]
```
For GAM version `5.00.00` and later:
* If `<FileName>` is omitted, the JSON data is written to `oauth2.txt`.
* If `<FileName>` is `-`, the JSON data is written to stdout.
For GAM versions before `5.00.00`:
* If `<FileName>` is omitted, the JSON data is written to stdout.
## Manage Service Accounts
In all of the service account commands, the Google Workspace admin/GCP project manager `<EmailAddress>` can be omitted; you will be prompted for a value.
You must enter a full address, i.e., user@domain.com; you will be required to enter the password.
## Add Service Accounts to projects
You can add additional service accounts to a project and assign it specific access APIs. This command
creates a new `oauth2service.json` file; it will not overwrite an existing file so you must rename the existing
file or define a new section in `gam.cfg` that references a different `oauth2service_json` or `config_dir`.
### Default values
* `<ServiceAccountName>` - "gam-svcacct-abc-def-jki" where "abc-def-ghi" are randomly generated
* `<ServiceAccountDisplayName>` - `<ServiceAccountName>`
* `<ServiceAccountDescription>` - `<ServiceAccountDisplayName>`
```
gam create|add svcacct [[admin] <EmailAddress>] [<ProjectIDEntity>]
[saname <ServiceAccountName>] [sadisplayname <ServiceAccountDisplayName>]
[sadescription <ServiceAccountDescription>]
```
* `<EmailAddress>` - Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `current` - The project referenced in `client_secret.json`; this is the default
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
Use these options to select user-specified values..
* `saname <ServiceAccountName>` - Service account name; combined with `<ProjectID>` to form `<ServiceAccountEmail>`
* `sadisplayname <ServiceAccountDisplayName>` - Service account display name
* `sadescription <ServiceAccountDescription>` - Service account description
After adding an additional service account, you can select specific access APIs for it.
[Selective Service Account access](#selective-service-account-access)
## Delete Service Accounts from projects
```
gam delete svcacct [[admin] <EmailAddress>] [<ProjectIDEntity>]
(saemail <ServiceAccountEmail>)|(saname <ServiceAccountName>)|(sauniqueid <ServiceAccountUniqueID>)
```
* `<EmailAddress>` - Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `current` - The project referenced in `client_secret.json`; this is the default
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
## Display Service Accounts for projects
Display Service Accounts as an indented list of keys and values.
```
gam show svcaccts [[admin] <EmailAddress>] [all|<ProjectIDEntity>]
[showsakeys all|system|user]
```
Display Service Accounts as columns of fields.
```
gam print svcaccts [[admin] <EmailAddress>] [all|<ProjectIDEntity>]
[showsakeys all|system|user]
[todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]
```
* `<EmailAddress>` - Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `all` - All projects accessible by the administrator; this is the default
* `current` - The project referenced in `client_secret.json`
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
By default, no Service Account key information is displayed, use the following options to display keys.
* `showsakeys all` - Display system and user keys; this is the default when keys are displayed
* `showsakeys system` - Display system keys
* `showsakeys user` - Display user keys
## Manage Service Account keys
The `oauth2service.json` file contains a private key that is used to authenticate Service Account access.
This private key will be referred to as the `current` private key.
Each Service Account in a project typically has one private key but it can have multiple keys; this might be the
case if you have several users with Gam access where they will all access the same Service Account but with different keys.
You will distribute different `oauth2service.json` files to each user, each with its own private key.
There are several methods for generating private keys:
* `algorithm KEY_ALG_RSA_1024` - Google generates a 1024 bit key; not recommended
* `algorithm KEY_ALG_RSA_2048` - Google generates a 2048 bit key
* `localkeysize 1024` - Gam generates a 1024 bit key; this is not recommended
* `localkeysize 2048` - Gam generates a 2048 bit key; this is the default
* `localkeysize 4096` - Gam generates a 4096 bit key
When `localkeysize` is specified, the optional argument `validityhours <Number>` sets the length of time during which the key will be valid and should be used when the [GCP constraints/iam.serviceAccountKeyExpiryHours organization policy](https://cloud.google.com/resource-manager/docs/organization-policy/restricting-service-accounts#limit_key_expiry) is in use. Note that in order to account for system clock skew, GAM sets the key to be valid two minutes earlier than the current system time and thus it will also expire two minutes earlier.
Here are some sample values:
```
1 hour
8 hours
24 hours ( 1 day)
168 hours ( 7 days)
336 hours (14 days)
720 hours (30 days)
1440 hours (60 days)
2160 hours (90 days)
```
## Create a new Service Account key
Create a new Service Account private key; all existing private keys remain valid.
The `oauth2service.json` file is updated with the new private key.
Keep a good record of where each Service Account key is used as the keys themselves do not record this information.
The two forms of the command are equivalent; the second form is used by Basic Gam.
```
gam create sakey
(algorithm KEY_ALG_RSA_1024|KEY_ALG_RSA_2048)|
((localkeysize 1024|2048|4096 [validityhours <Number>])|
(yubikey yubikey_pin yubikey_slot AUTHENTICATION
yubikey_serialnumber <Number>
[localkeysize 1024|2048|4096])
gam rotate sakey retain_existing
(algorithm KEY_ALG_RSA_1024|KEY_ALG_RSA_2048)|
((localkeysize 1024|2048|4096 [validityhours <Number>])|
(yubikey yubikey_pin yubikey_slot AUTHENTICATION
yubikey_serialnumber <Number>
[localkeysize 1024|2048|4096])
```
To distribute `oauth2service.json` files with unique private keys perform the following steps:
```
copy oauth2service.json to oauth2service.save
repeat
gam create sakeys retain_existing
distribute updated oauth2service.json file
copy oauth2service.save to oauth2service.json
```
## Update an existing Service Account key
Revoke the current Service Account key and replace it with a new private key; all other private keys remain valid.
The `oauth2service.json` file is updated with the new private key. If you had previously distributed
this `oauth2service.json` file to other users, you must redistribute the updated file as the private key
in the distributed copies has been revoked.
The two forms of the command are equivalent; the second form is used by Basic Gam.
```
gam update sakey
(algorithm KEY_ALG_RSA_1024|KEY_ALG_RSA_2048)|
((localkeysize 1024|2048|4096 [validityhours <Number>])|
(yubikey yubikey_pin yubikey_slot AUTHENTICATION
yubikey_serialnumber <Number>
[localkeysize 1024|2048|4096])
gam rotate sakey replace_existing
(algorithm KEY_ALG_RSA_1024|KEY_ALG_RSA_2048)|
((localkeysize 1024|2048|4096 [validityhours <Number>])|
(yubikey yubikey_pin yubikey_slot AUTHENTICATION
yubikey_serialnumber <Number>
[localkeysize 1024|2048|4096])
```
## Replace all existing Service Account keys
Create a new Service Account private key; all existing private keys are revoked.
The `oauth2service.json` file is updated with the new private key. If you had previously distributed
any `oauth2service.json` file to other users, you must redistribute the updated file as the private key
in the distributed copies has been revoked.
This command can be used if your Service Account keys have been compromised; all existing private keys are revoked.
The two forms of the command are equivalent; the second form is used by Basic Gam.
```
gam replace sakeys
(algorithm KEY_ALG_RSA_1024|KEY_ALG_RSA_2048)|
((localkeysize 1024|2048|4096 [validityhours <Number>])|
(yubikey yubikey_pin yubikey_slot AUTHENTICATION
yubikey_serialnumber <Number>
[localkeysize 1024|2048|4096])
gam rotate sakeys retain_none
(algorithm KEY_ALG_RSA_1024|KEY_ALG_RSA_2048)|
((localkeysize 1024|2048|4096 [validityhours <Number>])|
(yubikey yubikey_pin yubikey_slot AUTHENTICATION
yubikey_serialnumber <Number>
[localkeysize 1024|2048|4096])
```
## Delete Service Account keys
You can delete Service Accounts keys thus revoking access for that key. Generally, you will
delete a service account key for a distributed copy of an `oauth2service.json` file to disable
that user's service account access.
You can disable your current Service Account key if you specify the `doit` argument. This is your
acknowledgement that you will have to manually create a new Service Account key in the Developer's Console.
```
gam delete sakeys <ServiceAccountKeyList>+ [doit]
```
## Display Service Account keys
There are system keys and user keys; user keys are what Gam uses; GCP uses system keys.
Display Service Account keys as an indented list of keys and values.
```
gam show sakeys [all|system|user]
```
* `all` - Display system and user keys; this is the default
* `system` - Display system keys
* `user` - Display user keys
The private key currently being used in `oauth2service.json` will be marked as `usedToAuthenticateThisRequest: True`.
## Manage Service Account access
## Full Service Account access
Verify that the Service Account credentials have been authorized. If they have not, you will be given instructions
as to how to perform the authorization.
By default, the following scopes are verified:
```
https://mail.google.com/
https://sites.google.com/feeds
https://www.google.com/m8/feeds
https://www.googleapis.com/auth/apps.alerts
https://www.googleapis.com/auth/calendar
https://www.googleapis.com/auth/classroom.announcements
https://www.googleapis.com/auth/classroom.coursework.students
https://www.googleapis.com/auth/classroom.profile.emails
https://www.googleapis.com/auth/classroom.rosters
https://www.googleapis.com/auth/classroom.topics
https://www.googleapis.com/auth/cloud-identity
https://www.googleapis.com/auth/cloud-platform
https://www.googleapis.com/auth/cloudprint
https://www.googleapis.com/auth/contacts
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/drive.activity
https://www.googleapis.com/auth/gmail.modify
https://www.googleapis.com/auth/gmail.settings.basic
https://www.googleapis.com/auth/gmail.settings.sharing
https://www.googleapis.com/auth/spreadsheets
```
This scope is verified when `user_service_account_access_only = true` in `gam.cfg`.
```
https://www.googleapis.com/auth/apps.groups.migration
```
Verify/enable service account access for the default list of APIs.
The two forms of the command are equivalent.
```
gam check svcacct <UserTypeEntity> (scope|scopes <APIScopeURLList>)*
gam <UserTypeEntity> check serviceaccount (scope|scopes <APIScopeURLList>)*
```
* `<UserTypeEntity>` - Typically `user <EmailAddress>`, a non-Google Workspace administrator.
* `scopes <APIScopeURLList>` - Verify/enable service account access for a set of specific scopes rather than the default list.
## Selective Service Account access
Verify/enable service account access for a selected list of APIs rather than the default list.
The two forms of the command are equivalent.
If `scopes <APIScopeURLList>` is not specified, you will be prompted to select a list of scopes.
```
gam update svcacct <UserTypeEntity> (scope|scopes <APIScopeURLList>)*
gam <UserTypeEntity> update serviceaccount (scope|scopes <APIScopeURLList>)*
```
* `<UserTypeEntity>` - Typically `user <EmailAddress>`, a non-Google Workspace administrator.
* `scopes <APIScopeURLList>` - Verify/enable service account access for a set of specific scopes rather than selecting the scopes.
## Configure Limited access
You can configure GAM to allow users limited access to your domain via GAM.
You can limit both client and service account access.
You can repeat these steps if you want to configure multiple limited users;
substitute a unique value for `limited` in each of the steps.
On your computer, perform these initial steps:
Make a subdirectory `limited` under the directory specified in `gam.cfg config_dir`
Create a new section at the end of your `gam.cfg` file.
```
[limited]
config_dir = limited
```
Copy `client_secrets.json` to the `limited` subdirectory
Select the `limited` section
```
gam select limited save
```
## Limited Client access
Perform these steps to allow limited client access:
Configure `todrive` to allow uploading of files to the limited user's Google Drive.
```
gam config todrive_user limited@domain.com save
```
If it is not possible to allow the limited user any service account access (this is not common),
perform the following command so that the user can upload files with `todrive` using client access.
```
gam config todrive_clientaccess true save
```
Authorize the desired client access APIs; this will create `oauth2.txt`.
If it is not possible to allow the limited user any service account access,
login as the limited user; you must have assigned Admin API Privileges to the limited user
in the Admin console under Admin roles,
If the limited user will have service account access, login as a Google admin.
```
gam oauth create
```
## No Client access
Perform these steps to allow no client access:
Configure `todrive` to allow uploading of files to the limited user's Google Drive.
```
gam config todrive_user limited@domain.com todrive_clientaccess false save
```
Configure for service account access only.
```
gam config user_service_account_access_only true save
```
Make a `oauth2.txt` file in the `limited` subdirectory with a single line as follows:
```
{}
```
This will prevent the limited user from having any client access.
## Limited Service Account access
Perform these steps:
Create a a new service account in your project that will be used for the limited user;
this will create `outh2service.json`.
```
gam add svcacct saname "gam-limited" sadisplayname "GAM Limited"
```
Authorize the desired APIs; this will update `oauth2service.json` with the list of authorized APIs.
Follow the directions to authorize the APIs; remember, you will login to the Admin console as a current
Google administrator.
```
gam user limited@domain.com update serviceaccount
```
If you disable a scope that was previously enabled, all of the remaining APIs will pass.
However, you should still go to the Admin console and update the client so that only the APIs
you've enabled are authorized.
## todrive Service Account access
If the limited user is going to use `todrive`, authorize these APIs:
```
Drive API - todrive
Gmail API - Send Messages - including todrive
Sheets API - todrive
```
These APIs are only used to process `todrive`, they do not grant access to other user's files/sheets.
If the limited user is allowed access to other user's files/sheets, authorize these APIs:
```
Drive API (supports readonly)
Sheets API (supports readonly)
```
## No Service Account access possible
If it is not possible to allow the limited user any service account access (this is not common),
perform these steps:
Make a `oauth2service.json` file in the `limited` subdirectory with a single line as follows:
```
{}
```
## Test Client and Service Account access on your computer
Issue various Gam commands to verify that the limited user has only the desired access.
Repeat previous steps as required. Once testing is complete, perform the following step
to prevent the limited user from creating/updating `oauth2.txt`.
Edit the `client_secrets.json` file in the `limited` subdirectory to have a single line as follows:
```
{}
```
## Install GAM on the limited users computer
Install GAM on the limited user's computer; it can be a different OS than your computer;
if asked by the installer, indicate:
* that you do not want to set up a project
* that you are performing an update
Make the necessary directories.
* Make the GAM configuration directory; this can be different than on your computer.
* Set the GAMCFGDIR environment variable to point to the GAM configuration directory.
* Make a subdirectory `gamcache` under the GAM configuration directory.
* Make a subdirectory `limited` under the GAM configuration directory.
Copy `gam.cfg` from your computer to the GAM configuration directory on the limited user's computer.
Edit `gam.cfg`
* Remove any sections other than `[DEFAULT]` and `[limited]`
* If the GAM configuration directory on the limited users computer is different than that on yours, update these values in the [DEFAULT] section:
* cache_dir
* config_dir
* You may also want to update the GAM downloads directory:
* drive_dir
Copy `client_secrets.json`, `oauth2.txt` and `oauth2service.json` from the `limited` subdirectory on your computer to the `limited` subdirectory on the limited user's computer.
## Test Client and Service Account access on the non-administrator computer
Issue various Gam commands to verify that the limited user has only the desired access.
If you need to make changes, make them on your computer and then re-copy `client_secrets.json`, `oauth2.txt` and `oauth2service.json` to the limited user's computer.
## Unselect limited section on your computer.
Once you have finished setting up authorizations for the limited user, you need to reset your `gam.cfg` to point to your default section or another section.
```
gam select default save
gam select <Section> save
```

31
docs/BNF-Syntax.md Normal file
View File

@ -0,0 +1,31 @@
# Syntax
## BNF Syntax
This Wiki describes the GAM command line syntax in modified BNF.
* https://en.wikipedia.org/wiki/Backus-Naur_Form
Skip the History section and start reading at Introduction.
Items on the command line are space separated, when an actual space character is required, it will be indicated by ```<Space>```.
If an item contains spaces, it should be surrounded by ".
Metasyntactic symbols
```
[] optional item
() group items
* item may appear zero or more times
+ item may appear one or more times
| separates alternative items
```
## Items
- [Basic](Basic-Items)
- [Lists](List-Items)
## Collections
- [ChromeOS Devices](Collections-of-ChromeOS-Devices)
- [Users](Collections-of-Users)
- [Items](Collections-of-Items)
- [Verify Collections](List)
## Python Regular Expressions
- [Python Regular Expressions](Python-Regular-Expressions)

614
docs/Basic-Items.md Normal file
View File

@ -0,0 +1,614 @@
# Basic Items
- [Primitives](#primitives)
- [Items built from primitives](#items-built-from-primitives)
- [Named items](#named-items)
- [List Items](List-Items)
## Primitives
```
<Character> ::= a single character
<Digit> ::= 0|1|2|3|4|5|6|7|8|9
<Number> ::= <Digit>+
<Float> ::= <Digit>*.<Digit>+
<Hex> ::= <Digit>|a|b|c|d|e|f|A|B|C|D|E|F
<Space> ::= an actual space character
<String> ::= a string of characters, surrounded by " if it contains spaces
<FalseValues>= false|off|no|disabled|0
<TrueValues> ::= true|on|yes|enabled|1
<Charset> ::= ascii|latin1|mbcs|utf-8|utf-8-sig|utf-16|<String>
<CalendarColorIndex> ::= <Number in range 1-24>
<CalendarColorName> ::=
amethyst|avocado|banana|basil|birch|blueberry|
cherryblossom|citron|cobalt|cocoa|eucalyptus|flamingo|
grape|graphite|lavender|mango|peacock|pistachio|
pumpkin|radicchio|sage|tangerine|tomato|wisteria|
<ColorHex> ::= "#<Hex><Hex><Hex><Hex><Hex><Hex>"
<ColorNameGoogle> ::=
asparagus|bluevelvet|bubblegum|cardinal|chocolateicecream|denim|desertsand|
earthworm|macaroni|marsorange|mountaingray|mountaingrey|mouse|oldbrickred|
pool|purpledino|purplerain|rainysky|seafoam|slimegreen|spearmint|
toyeggplant|vernfern|wildstrawberries|yellowcab
<ColorNameWeb> ::=
aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|
blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|
cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|
darkgrey|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|
darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|
darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|
firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|
gray|grey|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|
lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|
lightgoldenrodyellow|lightgray|lightgrey|lightgreen|lightpink|lightsalmon|
lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|
lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|
mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|
mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|
navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|
palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|
peru|pink|plum|powderblue|purple|red|rosybrown|royalblue|saddlebrown|salmon|
sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|
slategrey|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|
wheat|white|whitesmoke|yellow|yellowgreen
<ColorName> ::= <ColorNameGoogle>|<ColorNameWeb>
<ColorValue> ::= <ColorName>|<ColorHex>
<DayOfWeek> ::= mon|tue|wed|thu|fri|sat|sun
<DriveLabelLanguageCode> ::=
ar-sa| # Arabic Saudi Arabia
cs-cz| # Czech Czech Republic
da-dk| # Danish Denmark
de-de| # German Germany
el-gr| # Modern Greek Greece
en-au| # English Australia
en-gb| # English United Kingdom
en-ie| # English Ireland
en-us| # English United States
en-za| # English South Africa
es-es| # Spanish Spain
es-mx| # Spanish Mexico
fi-fi| # Finnish Finland
fr-ca| # French Canada
fr-fr| # French France
he-il| # Hebrew Israel
hi-in| # Hindi India
hu-hu| # Hungarian Hungary
id-id| # Indonesian Indonesia
it-it| # Italian Italy
ja-jp| # Japanese Japan
ko-kr| # Korean Republic of Korea
nl-be| # Dutch Belgium
nl-nl| # Dutch Netherlands
no-no| # Norwegian Norway
pl-pl| # Polish Poland
pt-br| # Portuguese Brazil
pt-pt| # Portuguese Portugal
ro-ro| # Romanian Romania
ru-ru| # Russian Russian Federation
sk-sk| # Slovak Slovakia
sv-se| # Swedish Sweden
th-th| # Thai Thailand
tr-tr| # Turkish Turkey
zh-cn| # Chinese China
zh-hk| # Chinese Hong Kong
zh-tw # Chinese Taiwan
<EventColorIndex> ::= <Number in range 1-11>
<EventColorName> ::=
banana|basil|blueberry|flamingo|graphite|grape|
lavender|peacock|sage|tangerine|tomato
<FileFormat> ::=
csv|doc|dot|docx|dotx|epub|html|jpeg|jpg|mht|odp|ods|odt|
pdf|png|ppt|pot|potx|pptx|rtf|svg|tsv|txt|xls|xlt|xlsx|xltx|zip|
ms|microsoft|openoffice|
<LabelColorHex> ::=
#000000|#076239|#0b804b|#149e60|#16a766|#1a764d|#1c4587|#285bac|
#2a9c68|#3c78d8|#3dc789|#41236d|#434343|#43d692|#44b984|#4a86e8|
#653e9b|#666666|#68dfa9|#6d9eeb|#822111|#83334c|#89d3b2|#8e63ce|
#999999|#a0eac9|#a46a21|#a479e2|#a4c2f4|#aa8831|#ac2b16|#b65775|
#b694e8|#b9e4d0|#c6f3de|#c9daf8|#cc3a21|#cccccc|#cf8933|#d0bcf1|
#d5ae49|#e07798|#e4d7f5|#e66550|#eaa041|#efa093|#efefef|#f2c960|
#f3f3f3|#f691b3|#f6c5be|#f7a7c0|#fad165|#fb4c2f|#fbc8d9|#fcda83|
#fcdee8|#fce8b3|#fef1d1|#ffad47|#ffbc6b|#ffd6a2|#ffe6c7|#ffffff
<LabelBackgroundColorHex> ::=
#16a765|#2da2bb|#42d692|#4986e7|#98d7e4|#a2dcc1|
#b3efd3|#b6cff5|#b99aff|#c2c2c2|#cca6ac|#e3d7ff|
#e7e7e7|#ebdbde|#f2b2a8|#f691b2|#fb4c2f|#fbd3e0|
#fbe983|#fdedc1|#ff7537|#ffad46|#ffc8af|#ffdeb5
<LabelTextColorHex> ::=
#04502e|#094228|#0b4f30|#0d3472|#0d3b44|#3d188e|
#464646|#594c05|#662e37|#684e07|#711a36|#7a2e0b|
#7a4706|#8a1c0a|#994a64|#ffffff
<LanguageCode> ::=
ach|af|ag|ak|am|ar|az|be|bem|bg|bn|br|bs|ca|chr|ckb|co|crs|cs|cy|da|de|
ee|el|en|en-gb|en-us|eo|es|es-419|et|eu|fa|fi|fil|fo|fr|fr-ca|fy|
ga|gaa|gd|gl|gn|gu|ha|haw|he|hi|hr|ht|hu|hy|ia|id|ig|in|is|it|iw|ja|jw|
ka|kg|kk|km|kn|ko|kri|ku|ky|la|lg|ln|lo|loz|lt|lua|lv|
mfe|mg|mi|mk|ml|mn|mo|mr|ms|mt|my|ne|nl|nn|no|nso|ny|nyn|oc|om|or|
pa|pcm|pl|ps|pt-br|pt-pt|qu|rm|rn|ro|ru|rw|
sd|sh|si|sk|sl|sn|so|sq|sr|sr-me|st|su|sv|sw|
ta|te|tg|th|ti|tk|tl|tn|to|tr|tt|tum|tw|
ug|uk|ur|uz|vi|wo|xh|yi|yo|zh-cn|zh-hk|zh-tw|zu
<Language> ::=
<LanguageCode>[+|-]|
<String>
<Locale> ::=
''| #Not defined
ar-eg| #Arabic, Egypt
az-az| #Azerbaijani, Azerbaijan
be-by| #Belarusian, Belarus
bg-bg| #Bulgarian, Bulgaria
bn-in| #Bengali, India
ca-es| #Catalan, Spain
cs-cz| #Czech, Czech Republic
cy-gb| #Welsh, United Kingdom
da-dk| #Danish, Denmark
de-ch| #German, Switzerland
de-de| #German, Germany
el-gr| #Greek, Greece
en-au| #English, Australia
en-ca| #English, Canada
en-gb| #English, United Kingdom
en-ie| #English, Ireland
en-us| #English, U.S.A.
es-ar| #Spanish, Argentina
es-bo| #Spanish, Bolivia
es-cl| #Spanish, Chile
es-co| #Spanish, Colombia
es-ec| #Spanish, Ecuador
es-es| #Spanish, Spain
es-mx| #Spanish, Mexico
es-py| #Spanish, Paraguay
es-uy| #Spanish, Uruguay
es-ve| #Spanish, Venezuela
fi-fi| #Finnish, Finland
fil-ph| #Filipino, Philippines
fr-ca| #French, Canada
fr-fr| #French, France
gu-in| #Gujarati, India
hi-in| #Hindi, India
hr-hr| #Croatian, Croatia
hu-hu| #Hungarian, Hungary
hy-am| #Armenian, Armenia
in-id| #Indonesian, Indonesia
it-it| #Italian, Italy
iw-il| #Hebrew, Israel
ja-jp| #Japanese, Japan
ka-ge| #Georgian, Georgia
kk-kz| #Kazakh, Kazakhstan
kn-in| #Kannada, India
ko-kr| #Korean, Korea
lt-lt| #Lithuanian, Lithuania
lv-lv| #Latvian, Latvia
ml-in| #Malayalam, India
mn-mn| #Mongolian, Mongolia
mr-in| #Marathi, India
my-mn| #Burmese, Myanmar
nl-nl| #Dutch, Netherlands
nn-no| #Nynorsk, Norway
no-no| #Bokmal, Norway
pa-in| #Punjabi, India
pl-pl| #Polish, Poland
pt-br| #Portuguese, Brazil
pt-pt| #Portuguese, Portugal
ro-ro| #Romanian, Romania
ru-ru| #Russian, Russia
sk-sk| #Slovak, Slovakia
sl-si| #Slovenian, Slovenia
sr-rs| #Serbian, Serbia
sv-se| #Swedish, Sweden
ta-in| #Tamil, India
te-in| #Telugu, India
th-th| #Thai, Thailand
tr-tr| #Turkish, Turkey
uk-ua| #Ukrainian, Ukraine
vi-vn| #Vietnamese, Vietnam
zh-cn| #Simplified Chinese, China
zh-hk| #Traditional Chinese, Hong Kong SAR China
zh-tw #Traditional Chinese, Taiwan
<MimeTypeShortcut> ::=
gdoc|gdocument|
gdrawing|
gfile|
gfolder|gdirectory|
gform|
gfusion|
gmap|
gpresentation|
gscript|
gsheet|gspreadsheet|
gshortcut|
g3pshortcut|
gsite|
shortcut
<MimeTypeName> ::= application|audio|font|image|message|model|multipart|text|video
<MimeType> ::= <MimeTypeShortcut>|(<MimeTypeName>/<String>)
<ProductID> ::=
nv:<String> |
101001 |
101005 |
101031 |
101033 |
101034 |
101035 |
101036 |
101037 |
101039 |
101040 |
Google-Apps |
Google-Chrome-Device-Management |
Google-Drive-storage |
Google-Vault
<SKUID> ::=
nv:<String>:<String> |
20gb | drive20gb | googledrivestorage20gb | Google-Drive-storage-20GB |
50gb | drive50gb | googledrivestorage50gb | Google-Drive-storage-50GB |
200gb | drive200gb | googledrivestorage200gb | Google-Drive-storage-200GB |
400gb | drive400gb | googledrivestorage400gb | Google-Drive-storage-400GB |
1tb | drive1tb | googledrivestorage1tb | Google-Drive-storage-1TB |
2tb | drive2tb | googledrivestorage2tb | Google-Drive-storage-2TB |
4tb | drive4tb | googledrivestorage4tb | Google-Drive-storage-4TB |
8tb | drive8tb | googledrivestorage8tb | Google-Drive-storage-8TB |
16tb | drive16tb | googledrivestorage16tb | Google-Drive-storage-16TB |
assuredcontrols | 1010390001 |
bce | beyondcorp | beyondcorpenterprise | 1010400001 |
cdm | chrome | googlechromedevicemanagement | Google-Chrome-Device-Management |
cloudidentity | identity | 1010010001 |
cloudidentitypremium | identitypremium | 1010050001 |
cloudsearch | 1010350001 |
gsuitebasic | gafb | gafw | basic | Google-Apps-For-Business |
gsuitebusiness | gau | gsb | unlimited | Google-Apps-Unlimited |
gsuitebusinessarchived | gsbau | businessarchived | 1010340002 |
gsuiteenterprisearchived | gseau | enterprisearchived | 1010340001 |
gsuiteenterpriseeducation | gsefe | e4e | 1010310002 |
gsuiteenterpriseeducationstudent | gsefes | e4es | 1010310003 |
gsuitegov | gafg | gsuitegovernment | Google-Apps-For-Government |
gsuitelite | gal | gsl | lite | Google-Apps-Lite |
gwep | workspaceeducationplus | 1010310008 |
gwepstaff | workspaceeducationplusstaff | 1010310009 |
gwepstudent | workspaceeducationplusstudent | 1010310010 |
gwes | workspaceeducationstandard | 1010310005 |
gwesstaff | workspaceeducationstandardstaff | 1010310006 |
gwesstudent | workspaceeducationstandardstudent | 1010310007 |
gwetlu | workspaceeducationupgrade | 1010370001 |
meetdialing | googlemeetglobaldialing | 1010360001 |
postini | gams | gsuitegams | gsuitepostini | gsuitemessagesecurity | Google-Apps-For-Postini |
standard | free | Google-Apps |
vault | googlevault | Google-Vault |
vfe | googlevaultformeremployee | Google-Vault-Former-Employee |
voicepremier | gvpremier | googlevoicepremier | 1010330002 |
voicestandard | gvstandard | googlevoicestandard | 1010330004 |
voicestarter | gvstarter | googlevoicestarter | 1010330003 |
wsbizplus | workspacebusinessplus | 1010020025 |
wsbizplusarchived | workspacebusinessplusarchived | 1010340003 |
wsbizstan | workspacebusinessstandard | 1010020028 |
wsbizstarter | workspacebusinessstarter | wsbizstart | 1010020027 |
wsentess | workspaceenterpriseessentials | 1010060003 |
wsentplus | workspaceenterpriseplus | gae | gse | enterprise | gsuiteenterprise | 1010020020 |
wsentstan | workspaceenterprisestandard | 1010020026 |
wsentstanarchived | workspaceenterprisestandardarchived | 1010340004 |
wsess | workspaceesentials | gsuiteessentials | essentials | d4e | driveenterprise | drive4enterprise | 1010060001 |
wsflw | workspacefrontline | workspacefrontlineworker | 1010020030
```
## Items built from primitives
```
<Boolean> ::= <TrueValues>|<FalseValues>
<ByteCount> ::= <Number>[m|k|b]
<CIDRnetmask> ::= <Number>.<Number>.<Number>.<Number>/<Number>
<Year> ::= <Digit><Digit><Digit><Digit>
<Month> ::= <Digit><Digit>
<Day> ::= <Digit><Digit>
<Hour> ::= <Digit><Digit>
<Minute> ::= <Digit><Digit>
<Second> ::= <Digit><Digit>
<MilliSeconds> ::= <Digit><Digit><Digit>
<Date> ::=
<Year>-<Month>-<Day> |
(+|-)<Number>(d|w|y) |
never|
today
<DateTime> ::=
<Year>-<Month>-<Day>(<Space>|T)<Hour>:<Minute> |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
<Time> ::=
<Year>-<Month>-<Day>(<Space>|T)<Hour>:<Minute>:<Second>[.<MilliSeconds>](Z|(+|-(<Hour>:<Minute>))) |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
<RegularExpression> ::= <String>
See: https://docs.python.org/3/library/re.html
<ProjectID> ::= <String>
Must match this Python Regular Expression: [a-z][a-z0-9-]{4,28}[a-z0-9]
<ServiceAccountName> ::= <String>
Must match this Python Regular Expression: [a-z][a-z0-9-]{4,28}[a-z0-9]
<SiteName> ::= [a-z,0-9,-]+
<UniqueID> ::= id:<String>|uid:<String>
```
## Named items
```
<AccessToken> ::= <String>
<AlertID> ::= <String>
<APIScopeURL> ::= <String>
<APPID> ::= <String>
<ASPID> ::= <String>
<AssetTag> ::= <String>
<BrowserTokenPermanentID> ::= <String>
<BuildingID> ::= <String>|id:<String>
<CAALevelName> ::= <String>
<CalendarACLScope> ::=
<EmailAddress>|user:<EmailAddress>|group:<EmailAddress>|
domain:<DomainName>|domain|default
<CalendarItem> ::= <EmailAddress>
<GIGroupAlias> ::= <EmailAddress>
<GIGroupItem> ::= <EmailAddress>|<UniqueID>|groups/<String>
<CIGroupType> ::= customer|group|other|serviceaccount|user
<ChannelCustomerID> ::= <String>
<ChatMember> ::= spaces/<String>/members/<String>
<ChatMessage> ::= spaces/<String>/messages/<String>
<ChatSpace> ::= spaces/<String> | <String>
<ChatThread> ::= spaces/<String>/threads/<String>
<ClassroomInvitationID> ::= <String>
<ClientID> ::= <String>
<CommandID> ::= <String>
<ContactID> ::= <String>
<ContactGroupID> ::= id:<String>
<ContactGroupName> ::= <String>
<ContactGroupItem> ::= <ContactGroupID>|<ContactGroupName>
<CorporaAttribute> ::= alldrives|allteamdrives|domain|onlyteamdrives|user
<CourseAlias> ::= <String>
<CourseAnnouncementID> ::= <Number>
<CourseAnnouncementState> ::= draft|published|deleted
<CourseID> ::= <Number>|d:<CourseAlias>
<CourseMaterialID> ::= <Number>
<CourseMaterialState> ::= draft|published|deleted
<CourseParticipantType> ::= teacher|teachers|student|students
<CourseState> ::= active|archived|provisioned|declined|suspended
<CourseSubmissionID> ::= <Number>
<CourseSubmissionState> ::= new|created|turned_in|returned|reclaimed_by_student
<CourseTopic> ::= <String>
<CourseTopicID> ::= <Number>
<CourseWorkID> ::= <Number>
<CourseWorkState> ::= draft|published|deleted
<CrOSID> ::= <String>
<CustomerID> ::= <String>
<DataStudioAssetID> ::= <String>
<DataStudioPermission> ::=
user:<EmailAddress>|
group:<EmailAddress>|
domain:<DomainName>|
serviceAccount:<EmailAddress>
<DeliverySetting> ::=
allmail|
abridged|daily|
digest|
disabled|
none|nomail
<DeviceID> ::= devices/<String>
<DeviceType> ::= android|chrome_os|google_sync|ios|linux|mac_os|windows
<DeviceUserID> ::= devices/<String>/deviceUsers/<String>
<DomainAlias> ::= <String>
<DomainName> ::= <String>(.<String>)+
<DriveFileACLRole> ::=
commenter|
contentmanager|fileorganizer|
contributor|editor|writer|
manager|organizer|owner|
reader|viewer
<DriveFileACLType> ::= anyone|domain|group|user
<DriveFileID> ::= <String>
<DriveFileURL> ::=
https://drive.google.com/open?id=<DriveFileID>
https://drive.google.com/drive/files/<DriveFileID>
https://drive.google.com/drive/folders/<DriveFileID>
https://drive.google.com/drive/folders/<DriveFileID>?resourcekey=<String>
https://drive.google.com/file/d/<DriveFileID>/<String>
https://docs.google.com/document/d/<DriveFileID>/<String>
https://docs.google.com/drawings/d/<DriveFileID>/<String>
https://docs.google.com/forms/d/<DriveFileID>/<String>
https://docs.google.com/presentation/d/<DriveFileID>/<String>
https://docs.google.com/spreadsheets/d/<DriveFileID>/<String>
<DriveFileItem> ::= <DriveFileID>|<DriveFileURL>
<DriveFolderID> ::= <String>
<DriveFileName> ::= <String>
<DriveFolderName> ::= <String>
<DriveFolderPath> ::= <String>(/<String>)*
<DriveFilePermission> ::=
anyone;<DriveFileACLRole>|
anyonewithlink;<DriveFileACLRole>|
domain:<DomainName>;<DriveFileACLRole>|
domainwithlink:<DomainName>;<DriveFileACLRole>|
group:<EmailAddress>;<DriveFileACLRole>|
user:<EmailAddress>;<DriveFileACLRole>
<DriveFilePermissionID> ::= anyone|anyonewithlink|id:<String>
<DriveFilePermissionIDorEmail> ::= <DriveFilePermissionID>|<EmailAddress>
<DriveFileRevisionID> ::= <String>
<DriveLabelID> ::= <String>
<DriveLabelFieldID> ::= <String>
<DriveLabelSelectionID> ::= <String>
<DriveLabelName> ::= labels/<DriveLabelID>[@latest|@published|@<Number>]
<EmailAddress> ::= <String>@<DomainName>
<EmailItem> ::= <EmailAddress>|<UniqueID>|<String>
<EmailReplacement> ::= <String>
<EventID> ::= <String>
<EventName> ::= <String>
<ExportItem> ::= <UniqueID>|<String>
<ExportStatus> ::= completed|failed|inprogrsss
<FeatureName> ::= <String>
<FieldName> ::= <String>
<FileName> ::= <String>
<FileNamePattern> ::= <String>
<FilterID> ::= <String>
<FloorName> ::= <String>
<GroupItem> ::= <EmailAddress>|<UniqueID>|<String>
<GroupRole> ::= owner|manager|member
<GroupType> ::= customer|group|user
<GuardianItem> ::= <EmailAddress>|<UniqueID>|<String>
<GuardianInvitationID> ::= <String>
<HoldItem> ::= <UniqueID>|<String>
<HostName> ::= <String>
<iCalUID> ::= <String>
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<Key> ::= <String>
<LabelID> ::= Label_<String>
<LabelName> ::= <String>
<LabelReplacement> ::= <String>
<Marker> ::= <String>
<MatterItem> ::= <UniqueID>|<String>
<MatterState> ::= open|closed|deleted
<MessageContent> ::=
(message|textmessage|htmlmessage <String>)|
(file|textfile|htmlfile <FileName> [charset <Charset>])|
(gdoc|ghtml <UserGoogleDoc>)|
(gcsdoc|gcshtml <StorageBucketObjectName>)|
(emlfile <FileName>)
<MessageID> ::= <String>
<Namespace> ::= <String>
<NotesName> ::= notes/<String>
<NotifyMessageContent> ::=
(message|textmessage|htmlmessage <String>)|
(file|textfile|htmlfile <FileName> [charset <Charset>])|
(gdoc|ghtml <UserGoogleDoc>)|
(gcsdoc|gcshtml <StorageBucketObjectName>)
<NumberOfSeats> ::= <Number>
<OrgUnitID> ::= id:<String>
<OrgUnitPath> ::= /|(/<String>)+
<OrgUnitItem> ::= <OrgUnitID>|<OrgUnitPath>
<OtherContactsResourceName> ::= otherContacts/<String>
<ParameterKey> ::= <String>
<ParameterValue> ::= <String>
<Password> ::= <String>
<PeopleResourceName> ::= people/<String>
<PrinterID> ::= <String>
<ProjectID> ::= <String>
Must match this Python Regular Expression: [a-z][a-z0-9-]{4,28}[a-z0-9]
<ProjectName> ::= <String>
Must match this Python Regular Expression: [a-zA-Z0-9 '"!-]{4,30}
<PropertyKey> ::= <String>
<PropertyValue> ::= <String>
<QueryAlert> ::= <String>
See: https://developers.google.com/admin-sdk/alertcenter/guides/query-filters
<QueryBrowser> ::= <String>
See: https://support.google.com/chrome/a/answer/9681204#retrieve_all_chrome_devices_for_an_account
<QueryBrowserToken> ::= <String>
See: https://support.google.com/chrome/a/answer/9949706?ref_topic=9301744
<QueryCalendar> ::= <String>
<QueryCEL> ::= <String>
See: https://cloud.google.com/access-context-manager/docs/custom-access-level-spec
<QueryContact> ::= <String>
See: https://developers.google.com/google-apps/contacts/v3/reference#contacts-query-parameters-reference
<QueryCrOS> ::= <String>
See: https://support.google.com/chrome/a/answer/1698333
<QueryDevice> ::= <String>
See: https://support.google.com/a/answer/7549103
<QueryDriveFile> ::= <String>
See: https://developers.google.com/drive/api/v3/search-files
<QueryDynamicGroup> ::= <String>
See: https://cloud.google.com/identity/docs/reference/rest/v1/groups#dynamicgroupquery
<QueryGmail> ::= <String>
See: https://support.google.com/mail/answer/7190
<QueryGroup> ::= <String>
See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
<QueryMemberRestrictions> ::= <String>
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
<QueryMobile> ::= <String>
See: https://support.google.com/a/answer/7549103
<QueryTeamDrive> ::= <String>
See: https://developers.google.com/drive/api/v3/search-parameters
<QueryUser> ::= <String>
See: https://developers.google.com/admin-sdk/directory/v1/guides/search-users
<QueryVaultCorpus> ::= <String>
See: https://developers.google.com/vault/reference/rest/v1/matters.holds#CorpusQuery
<RequestID> ::= <String>
<ResellerID> ::= <String>
<ResourceID> ::= <String>
<SchemaName> ::= <String>
<Section> ::= <String>
<SendAsContent> ::=
(sig|signature|htmlsig <String>)|
(file|htmlfile <FileName> [charset <Charset>])|
(gdoc|ghtml <UserGoogleDoc>)|
(gcsdoc|gcshtml <StorageBucketObjectName>)
<SerialNumber> ::= <String>
<ServiceAccountName> ::= <String>
Must match this Python Regular Expression: [a-z][a-z0-9-]{4,28}[a-z0-9]
<ServiceAccountDisplayName> ::= <String>
Maximum of 100 characters
<ServiceAccountDescrition> ::= <String>
Maximumof 256 chcracters
<ServiceAccountEmail> ::= <ServiceAccountName>@<ProjectID>.iam.gserviceaccount.com
<ServiceAccountUniqueID> ::= <Number>
<ServiceAccountKey> ::= <String>
<SheetEntity> ::= <String>|id:<Number>
<SignatureContent> ::=
(<String>)|
(file|htmlfile <FileName> [charset <Charset>])|
(gdoc|ghtml <UserGoogleDoc>)|
(gcsdoc|gcshtml <StorageBucketObjectName>)
<SiteACLScope> ::=
<EmailAddress>|user:<EmailAddress>|group:<EmailAddress>|
domain:<DomainName>|domain|default
<SiteItem> ::= [<DomainName>/]<SiteName>
<S/MIMEID> ::= <String>
<SMTPHostName> ::= <String>
<StudentItem> ::= <EmailAddress>|<UniqueID>|<String>
<SharedDriveACLRole> ::=
commenter|
contentmanager|fileorganizer|
contributor|editor|writer|
manager|organizer|owner|
reader|viewer
<SharedDriveID> ::= <String>
<SharedDriveName> ::= <String>
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
<Tag> ::= <String>
<TakeoutBucketName> ::= takeout-export-[a-f,0-9,-]*
<TaskID> ::= <String>
<TaskListID> ::= <String>
<TasklistIDTaskID> ::= <TasklistID>/<TaskID>
<ThreadID> ::= <String>
<TimeZone> ::= <String>
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
<Title> ::= <String>
<ToDriveAttribute> ::=
(tdaddsheet [<Boolean>])|
(tdbackupsheet (id:<Number>)|<String>)|
(tdcellnumberformat text|number)|
(tdcellwrap clip|overflow|wrap)|
(tdclearfilter [<Boolean>])|
(tdcopysheet (id:<Number>)|<String>)|
(tddescription <String>)|
(tdfileid <DriveFileID>)|
(tdlocalcopy [<Boolean>])|
(tdlocale <Locale>)|
(tdnobrowser [<Boolean>])|
(tdnoemail [<Boolean>])|
(tdparent (id:<DriveFolderID>)|<DriveFolderName>)|
(tdshare <EmailAddress> commenter|reader|writer)|
(tdsheet (id:<Number>)|<String>)|
(tdsheettimestamp [<Boolean>] [tdsheettimeformat <String>])
(tdsheettitle <String>)|
([tdsheetdaysoffset <Number>] [tdsheethoursoffset <Number>])|
(tdtimestamp [<Boolean>] [tdtimeformat <String>]
[tddaysoffset <Number>] [tdhoursoffset <Number>])|
(tdtimezone <TimeZone>)|
(tdtitle <String>)|
(tdupdatesheet [<Boolean>])|
(tduploadnodata [<Boolean>])|
(tduser <EmailAddress>)
<TransferID> ::= <String>
<URI> ::= <String>
<URL> ::= <String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
<UserName> ::= <String>
<VacationMessageContent> ::=
(message|textmessage|htmlmessage <String>)|
(file|textfile|htmlfile <FileName> [charset <Charset>])|
(gdoc|ghtml <UserGoogleDoc>)|
(gcsdoc|gcshtml <StorageBucketObjectName>)
```

148
docs/Bulk-Processing.md Normal file
View File

@ -0,0 +1,148 @@
# Bulk Processing
- [Introduction](#introduction)
- [Python Regular Expressions](Python-Regular-Expressions)
- [GAM Configuration](gam.cfg)
- [Meta Commands and File Redirection](Meta-Commands-and-File-Redirection)
- [Definitions](#definitions)
- [Batch files](#batch-files)
- [CSV files](#csv-files)
- [CSV files with redirection and select](#csv-files-with-redirection-and-select)
- [Automatic batch processing](#automatic-batch-processing)
## Introduction
Batch and CSV file processing can improve performance by executing Gam commands in parallel.
The variables `num_threads`, `num_tbatch_threads` and `auto_batch_min` in `gam.cfg` control parallelism.
## Definitions
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
`gdoc <UserGoogleDoc>` and `gsheet <UserGoogleSheet>`
## Batch files
There are two types of batch processing, one that uses processes and one that uses threads. Using processes is higher performance but `gam csv` commands are not supported.
* `gam batch` - gam commands are run as processes, gam csv commands are not allowed in the batch file
* `gam tbatch` - gam commands are run as threads, gam csv commands are allowed in the batch file
```
gam batch <FileName>|-|(gdoc <UserGoogleDoc>) [charset <Charset>] [showcmds [<Boolean>]]
gam tbatch <FileName>|-|(gdoc <UserGoogleDoc>) [charset <Charset>] [showcmds [<Boolean>]]
```
* `<FileName>` - A flat file containing Gam commands
* `-` - Gam commands coming from stdin
* `gdoc <UserGoogleDoc>` - A Google Doc containing Gam commands
* `showcmds` - Write `timestamp,command number/number of commands,command` to stderr when each command starts; write `timestamp, command number/numberof commands,complete` to stderr when command completes
Batch files can contain the following types of lines:
* Blank lines - Ignored
* \# Comment line - Ignored
* gam \<GAMArgumentList\> - Execute a GAM command
* commit-batch
* GAM waits for all running GAM commands to complete
* GAM continues
* commit-batch \<String\>
* GAM waits for all running GAM commands to complete
* GAM prints \<String\> and waits for the user to press any key
* GAM continues
* print \<String\> - Print \<String\> on stderr
* set \<KeywordString\> \<ValueString\>
* Subsequent lines will have %\<KeywordString\>% replaced with \<ValueString\>
* clear \<KeywordString\>
* Subsequent lines will not be scanned for %\<KeywordString\>%
Tbatch files can also contain the following line:
* execute \<Program\> \<ArgumentList\> - Execute an arbitrary command; use the full path to specify \<Program\>
### Example
* You need to create accounts for your new students and assign them to groups based on their graduation year.
* You have a CSV file NewStudents.csv with columns: Email,First,Last,GradYear,Password
* You have a batch file NewStudents.bat containing these commands:
```
gam csv NewStudents.csv gam create user ~Email firstname ~First lastname ~Last org "/Students/~~GradYear~~" password ~Password
commit-batch
gam update group seniors sync members ou /Students/2020
gam update group juniors sync members ou /Students/2021
gam update group sophomores sync members ou /Students/2022
gam update group highschool sync members ous "'/Students/2020','/Students/2021','/Students/2022'"
```
* Execute the batch file
```
gam redirect stdout ./NewStudents.out redirect stderr ./NewStudents.err tbatch NewStudents.bat showcmds
```
## CSV files
```
gam csv <FileName>|-|(gsheet <UserGoogleSheet>)|(gdoc <UserGoogleDoc>) [charset <Charset>] [warnifnodata]
[columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>]
(matchfield|skipfield <FieldName> <RegularExpression>)* [showcmds [<Boolean>]]
[maxrows <Integer>]
gam <GAMArgumentList>
gam loop <FileName>|-|(gsheet <UserGoogleSheet>)|(gdoc <UserGoogleDoc>) [charset <Charset>] [warnifnodata]
[columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>]
(matchfield|skipfield <FieldName> <RegularExpression>)* [showcmds [<Boolean>]]
[maxrows <Integer>]
gam <GAMArgumentList>
```
* `gam csv` - Use parallel processing
* `gam loop` - Use serial processing
* `<FileName>` - A CSV file and the one or more columns that contain data
* `-` - The one or more columns that contain data from stdin
* `gsheet <UserGoogleSheet>` - A Google Sheet and the one or more columns that contain data
* `gdoc <UserGoogleDoc>` - A Google Doc and the one or more columns that contain data
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings.
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `showcmds` - Write `timestamp,command number/number of commands,command` to stderr when each command starts; write `timestamp, command number/numberof commands,complete` to stderr when command completes
* `maxrows <Integer>` - Limit the number of filtered rows processed from the CSV file/Google Sheet.
* `maxrows 0` - All rows are processed, this is the default
* `maxrows N` - N filtered rows are processed
### Use CSV file values in command line
You can make substitutions in `<GAMArgumentList>` with values from the CSV file.
- Reference the field xxx with `~xxx` if the argument contains no other text
- Reference the field xxx with `~~xxx~~` if the argument contains other text
- An argument containing exactly `~xxx` is replaced by the value of field xxx
- An argument containing instances of `~~xxx~~` has `~~xxx~~` replaced by the value of field xxx
- An argument containing instances of `~~xxx~!~pattern~!~replacement~~` has `~~xxx~!~pattern~!~replacement~~` replaced by re.sub(pattern, replacement, value of field xxx) See: https://docs.python.org/3/library/re.html
If an argument is specifying a file path and it starts with a `~`, e.g., `targetfolder "~/Documents/GamWork"`, GAM will flag it as an error:
```
ERROR: Header "/Documents/GamWork/" not found in CSV headers of "Owner,id,title".
```
Put a space in front of the `~`: `targetfolder " ~/Documents/GamWork"` to avoid the error.
### Example
* You need to update the work addresses of a set of users
* You want a note field that shows their email address as name AT domain.com
* You have a CSV file Users.csv with columns: primaryEmail,Street,City,State,ZIP
```
gam csv Users.csv gam update user ~primaryEmail address type work unstructured "~~Street~~, ~~City~~, ~~State~~ ~~ZIP~~" primary note text_plain "~~primaryEmail~!~^(.+)@(.+)$~!~\1 AT \2~~"
```
* You want to do the above using a Google Sheet
```
gam csv gsheet <user> <fileID> "<sheetName>" gam update user "~primaryEmail" address type work unstructured "~~Street~~, ~~City~~, ~~State~~ ~~ZIP~~" primary note text_plain "~~primaryEmail~!~^(.+)@(.+)$~!~\1 AT \2~~"
```
## CSV files with redirection and select
You should use the `multiprocess` option on any redirected files: `csv`, `stdout`, `stderr`.
```
gam redirect csv ./filelistperms.csv multiprocess csv Users.csv gam user ~primaryEmail print filelist fields id,title,permissions,owners.emailaddress
```
If you want to select a `gam.cfg` section for the command, you can select the section at the outer `gam` and save it
or select the section at the inner `gam`.
```
gam select <Section> save redirect csv ./filelistperms.csv multiprocess csv Users.csv gam user ~primaryEmail print filelist fields id,title,permissions,owners.emailaddress
gam redirect csv ./filelistperms.csv multiprocess csv Users.csv gam select <Section> user ~primaryEmail print filelist fields id,title,permissions,owners.emailaddress
```
## Automatic batch processing
You can enable automatic batch (parallel) processing when issuing commands of the form `gam <UserTypeEntity> ...`.
In the following example, if the number of users in group sales@domain.com exceeds 1, then the `print filelist` command will be processed in parallel.
```
gam config auto_batch_min 1 redirect csv ./filelistperms.csv multiprocess group sales@domain.com print filelist fields id,title,permissions,owners.emailaddress
```
With automatic batch processing, you should use the `multiprocess` option on any redirected files: `csv`, `stdout`, `stderr`.
If you want to select a `gam.cfg` section for the command, you must select and save it for it to be processed correctly.
```
gam select <Section> save config auto_batch_min 1 redirect csv ./filelistperms.csv multiprocess group sales@domain.com print filelist fields id,title,permissions,owners.emailaddress
```

259
docs/CSV-Input-Filtering.md Normal file
View File

@ -0,0 +1,259 @@
# CSV Input Filtering
- [Python Regular Expressions](Python-Regular-Expressions) Search function
- [Definitions](#definitions)
- [Quoting rules](#quoting-rules)
- [Column row filtering](#column-row-filtering)
- [Column row limiting](#column-row-limiting)
- [Saving filters in gam.cfg](#saving-filters-in-gamcfg)
- [Validate filters](#validate-filters)
There are two values in `gam.cfg` that can be used to filter the input from `gam csv` commands.
* `csv_input_row_filter` - A list or JSON dictionary used to include specific rows based on column values
* `csv_input_row_drop_filter` - A list or JSON dictionary used to exclude specific rows based on column values
These filters can be used alone or in conjunction with the `matchfield|skipfield <FieldName> <RegularExpression>` options.
* https://github.com/taers232c/GAMADV-XTD3/wiki/Bulk-Processing#csv-files
## Definitions
[Data Selectors](Collections-of-items)
```
<DataSelector> ::=
<ListSelector>|
<FileSelector>|
<CSVFileSelector>
```
```
<Date> ::=
<Year>-<Month>-<Day> |
(+|-)<Number>(d|w|y) |
never|
today
<Time> ::=
<Year>-<Month>-<Day>T<Hour>:<Minute>:<Second>[.<MilliSeconds>](Z|(+|-(<Hour>:<Minute>))) |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
<Operator> ::= <|<=|>=|>|=|!=
<RegularExpression> ::= <String>
See: https://docs.python.org/3/library/re.html>
<FieldNameFilter> :: = <RegularExpression>
<RowValueFilter> ::=
[(any|all):]count<Operator><Number>|
[(any|all):]countrange=<Number>/<Number>|
[(any|all):]countrange!=<Number>/<Number>|
[(any|all):]date<Operator><Date>|
[(any|all):]daterange=<Date>/<Date>|
[(any|all):]daterange!=<Date>/<Date>|
[(any|all):]length<Operator><Number>|
[(any|all):]lengthrange=<Number>/<Number>|
[(any|all):]lengthrange!=<Number>/<Number>|
[(any|all):]text<Operator><String>|
[(any|all):]textrange=<String>/<String>|
[(any|all):]textrange!=<String>/<String>|
[(any|all):]time<Operator><Time>|
[(any|all):]timerange=<Time>/<Time>|
[(any|all):]timerange!=<Time>/<Time>|
[(any|all):]boolean:<Boolean>|
[(any|all):]regex:<RegularExpression>|
[(any|all):]regexcs:<RegularExpression>|
[(any|all):]notregex:<RegularExpression>|
[(any|all):]notregexcs:<RegularExpression>|
[(any|all):]data:<DataSelector>|
[(any|all):]notdata:<DataSelector>|
<RowValueFilterList> ::=
"'<FieldNameFilter>:<RowValueFilter>'(,'<FieldNameFilter>:<RowValueFilter>')*"
<RowValueFilterJSONList> ::=
'{"<FieldNameFilter>": "<RowValueFilter>"(,"<FieldNameFilter>": "<RowValueFilter>")*}' |
"{\"<FieldNameFilter>\": \"<RowValueFilter>\"(,\"<FieldNameFilter>\": \"<RowValueFilter>\")*}"
```
## Quoting rules
Name:value form.
```
<RowValueFilterList> ::=
"'<FieldNameFilter>:<RowValueFilter>'(,'<FieldNameFilter>:<RowValueFilter>')*"
```
* `<RowValueFilterList>`, even if it has one element, should be enclosed in `"`.
* Each `<FieldNameFilter>:<RowValueFilter>` pair should be enclosed in `'`.
* If `<FieldNameFilter>` contains a `:` or a space, it should be enclosed in `\"`.
* If `<RegularExpression>` or `<DataSelector>` in `<RowValueFilter>` contain a space, it should be enclosed in `\"`.
Example:
```
csv_input_row_filter "'\"accounts:used_quota_in_mb\":count>15000'"
csv_input_row_filter "'email:data:\"csvfile gsheet:email user@domain.com FileID Sheet1\"'"
```
JSON form.
```
<RowValueFilterJSONList> ::=
'{"<FieldNameFilter>": "<RowValueFilter>"(,"<FieldNameFilter>": "<RowValueFilter>")*}' |
"{\"<FieldNameFilter>\": \"<RowValueFilter>\"(,\"<FieldNameFilter>\": \"<RowValueFilter>\")*}"
```
* The first JSON form can be used on Linux and Mac OS; it can not be used on Windows.
* The second JSON form can be used on Linux, Mac OS and Windows.
* If `<FieldNameFilter>` contains a `:` or a space, no additional quoting is required
Example:
```
csv_input_row_filter '{"accounts:used_quota_in_mb": "count>=150"}'
csv_input_row_filter "{\"accounts:used_quota_in_mb\": \"count>=150\"}"
```
## Column row filtering
Row filtering includes/excludes rows based on column values.
### Field names
Field names are specified by regular expressions; at its simplest, you specify a complete field name.
Field names are matched in a case insensitive manner.
If the field name doesn't contain any of the following regular expression characters `^$*+|$[{(`,
it will be surrounded with `^$` so that it doesn't match any subfields that begin with the field name as a prefix.
The following filter will match the count field and not the subfields.
```
config csv_input_row_filter "'externalIds:countrange=1/10'"
primaryEmail,externalIds,externalIds.0.type,externalIds.0.value,externalIds.1.type,externalIds.1.value,...
```
### Inclusive filters
You can include rows for gam csv commands based on column values. You specify a list
of fields(headers) and the values they must have. `csv_input_row_filter` is used to specify the
fields and values. Each field name/expression can appear only once in the list.
You specify whether all or any value filters must match for the row to be included in the input.
* `csv_input_row_filter_mode allmatch` - All value filters must match for the row to be included in the input; this is the default
* `csv_input_row_filter_mode anymatch` - Any value filter must match for the row to be included in the input
```
gam config csv_input_row_filter <RowValueFilterList> ...
gam config csv_input_row_filter <RowValueFilterJSONList> ...
```
### Exclusive filters
You can exclude rows for gam csv commands based on column values. You specify a list
of fields(headers) and the values they must not have. `csv_input_row_drop_filter` is used to specify the
fields and values. Each field name/expression can appear only once in the list.
You specify whether all or any value filters must match for the row to be excluded from the input.
* `csv_input_row_filter_drop_mode allmatch` - If all value filters match, the row is excluded from the input
* `csv_input_row_filter_drop_mode anymatch` - If any value filter matches, the row is excluded from the input; this is the default
```
gam config csv_input_row_drop_filter <RowValueFilterList> ...
gam config csv_input_row_drop_filter <RowValueFilterJSONList> ...
```
### Matches
A filter matches if the field has the desired value. lf you specify a regular expression for a field name that matches
several columns, the filter matches if any of the columns has a match. In the case of `notregex|notregexcs|notdata`,
the filter matches if none (not any) of the columns has a match.
`<RowValueFilter>` allows specifying that the filter will match only if all of the columns have a match.
In the case of `notregex|notregexcs|notdata`, the filter matches if some (not all) of the columns have a match.
If neither `any` or `all` is explicitly specified, `any` is the default.
These are the row value filter types:
* `count<Operator><Number>` - Used on fields with numbers; a blank field will not match
* `countrange=<Number>/<Number>` - Used on fields with numbers; a blank field will not match
* The field value must be `>=` the left `<Number>` and `<=` the right `<Number>`
* `countrange!=<Number>/<Number>` - Used on fields with numbers; a blank field will not match
* The field value must be `<` the left `<Number>` or `>` the right `<Number>`
* `date<Operator><Date>` - Used on fields with dates or times; only the date portion of a time field is compared; a blank field will not match
* `daterange=<Date>/<Date>` - Used on fields with dates or times; only the date portion of a time field is compared; a blank field will not match
* The field value must be `>=` the left `<Date>` and `<=` the right `<Date>`
* `daterange!=<Date>/<Date>` - Used on fields with dates or times; only the date portion of a time field is compared; a blank field will not match
* The field value must be `<` the left `<Date>` or `>` the right `<Date>`
* `length<Operator><Number>` - Used on fields with strings; non string fields will not match
* `lengthrange=<Number>/<Number>` - Used on fields with strings; non string fields will not match
* The field length must be `>=` the left `<Number>` and `<=` the right `<Number>`
* `lengthrange!=<Number>/<Number>` - Used on fields with strings; non string fields will not match
* The field length must be `<` the left `<Number>` or `>` the right `<Number>`
* `text<Operator><String>` - Used on fields with text
* `textrange=<String>/<String>` - Used on fields with strings
* The field value must be `>=` the left `<String>` and `<=` the right `<String>`
* `textrange!=<String>/<String>` - Used on fields with strings
* The field value must be `<` the left `<String>` or `>` the right `<String>`
* `time<Operator><Time>` - Used on fields with times; a blank field will not match
* `timerange=<Time>/<Time>` - Used on fields with times; a blank field will not match
* The field value must be `>=` the left `<Time>` and `<=` the right `<Time>`
* `timerange!=<Time>/<Time>` - Used on fields with times; a blank field will not match
* The field value must be `<` the left `<Time>` or `>` the right `<Time>`
* `boolean:<Boolean>` - Used on fields with Boolean values; a blank field is considered False
* `regex:<RegularExpression>` - Used on fields with text; field value must match `<RegularExpression>`; case insensitive
* `regexcs:<RegularExpression>` - Used on fields with text; field value must match `<RegularExpression>`; case sensitive
* `notregex:<RegularExpression>` - Used on fields with text; field value must not match `<RegularExpression>`; case insensitive
* `notregexcs:<RegularExpression>` - Used on fields with text; field value must not match `<RegularExpression>`; case sensitive
* `data:<DataSelector>` - Used on fields with text; field value must match some value in `<DataSelector>`; case sensitive
* `notdata:<DataSelector>` - Used on fields with text; field value must not match any value in `<DataSelector>`; case sensitive
### **Change in behavior.**
In versions prior to `5.12.00`, `regex:<RegularExpression>` and `notregex:<RegularExpression>` were processed in a case sensitive manner;
in many cases this is probably not desirable; e.g., matching file names which are case insensitive.
Now, `regex:<RegularExpression>` and `notregex:<RegularExpression>` are processed in a case insensitive manner.
To get the prior case sensitive processing, use `regexcs:<RegularExpression>` and `notregexcs:<RegularExpression>`.
### Examples
You want to process groups with 100 or more direct members.
```
gam redirect csv GroupInfo.csv print groups fields directmemberscount
gam config csv_input_row_filter "'directMembersCount:count>100'" csv GroupInfo.csv gam group "~email" ...
```
You want to process groups not created by an administrator.
```
gam redirect csv GroupInfo.csv print groups fields admincreated
gam config csv_input_row_drop_filter "'adminCreated:boolean:true'" csv GroupInfo.csv gam group "~email" ...
```
You want to process users created in the last 30 days.
```
gam redirect csv UserInfo.csv print users fields creationtime
gam config csv_input_row_filter "'creationTime:date>=-30d'" csv UserInfo.csv gam user "~primaryEmail" ...
```
You want to process users that are consuming more than 15GB of storage.
Special quoting is required because the field name contains a colon.
```
gam redirect csv UserInfo.csv report user services accounts fields "accounts:used_quota_in_mb"
gam config csv_input_row_filter "'\"accounts:used_quota_in_mb\":count>15000'" csv UserInfo.csv gam user "~primaryEmail" ...
```
## Column row limiting
You can limit the number of rows read from a CSV file.
You want to process the first 10 users that are consuming more than 15GB of storage.
Special quoting is required because the field name contains a colon.
```
gam redirect csv UserInfo.csv report user services accounts fields "accounts:used_quota_in_mb"
gam config csv_input_row_filter "'\"accounts:used_quota_in_mb\":count>15000'" csv_input_row_limit 10 csv UserInfo.csv gam user "~primaryEmail" ...
```
## Saving filters in gam.cfg
If you define a value for `csv_input_row_filter`, `csv_input_row_drop_filter` or `csv_input_row_limit` in the `[DEFAULT]` section of `gam.cfg`,
it will apply to every `gam csv` command which is probably not desirable. You can store them in `gam.cfg` in named sections.
```
[Filter510]
csv_input_row_filter = 'phones.\\\d+.value:regex:(?:^\\\(510\\\) )|(?:^510[- ])\\\d{3}-\\\d{4}'
```
You want to process users with phone numbers in the area code 510; the number can be in the format `(510) ddd-dddd` or `510-ddd-dddd` or `510 ddd-dddd`.
```
gam redirect csv UserInfo.csv print users fields name,phones
gam selectinputfilter Filter510 csv UserInfo.csv gam user "~primaryEmail" ...
```
## Validate filters
Version `6.30.00` added the `gam comment <String>*` command that can be used to validate input row filters.
```
$ more Comment.csv
col1,col2
aaa,111
bbb,222
ccc,333
$ gam config csv_input_row_drop_filter "col1:regex:bbb" csv Comment.csv gam comment "Col1:~~col1~~" "Col2:~~col2~~"
2022-12-16T12:41:50.045-08:00,0/2,Using 2 processes...
Col1:aaa Col2:111
Col1:ccc Col2:333
$ gam config csv_input_row_filter "col1:regex:bbb" csv Comment.csv gam comment "Col1:~~col1~~" "Col2:~~col2~~"
2022-12-18T09:42:26.108-08:00,0/1,Using 1 process...
Col1:bbb Col2:222
```

View File

@ -0,0 +1,353 @@
# CSV Output Filtering
- [Python Regular Expressions](Python-Regular-Expressions) Search function
- [Definitions](#definitions)
- [Quoting rules](#quoting-rules)
- [Column header filtering](#column-header-filtering)
- [Column row filtering](#column-row-filtering)
- [Column row limiting](#column-row-limiting)
- [Saving filters in gam.cfg](#saving-filters-in-gamcfg)
There are five values in `gam.cfg` that can be used to filter the output from `gam print` commands.
* `csv_output_header_filter` - A list of `<RegularExpressions>` used to select specific column headers to include
* `csv_output_header_drop_filter` - A list of `<RegularExpressions>` used to select specific column headers to exclude
* `csv_output_row_filter` - A list or JSON dictionary used to include specific rows based on column values
* `csv_output_row_drop_filter` - A list or JSON dictionary used to exclude specific rows based on column values
* `csv_output_row_limit` - A limit on the number of rows written
The original implementation required that row filters be expressed in JSON notation; these are almost
impossible to enter correctly in Windows; on Mac OS or Linux, it's easy. You can now enter the row filters as lists
on all platforms.
## Definitions
[Data Selectors](Collections-of-items)
```
<DataSelector> ::=
<ListSelector>|
<FileSelector>|
<CSVFileSelector>
```
```
<Date> ::=
<Year>-<Month>-<Day> |
(+|-)<Number>(d|w|y) |
never|
today
<Time> ::=
<Year>-<Month>-<Day>T<Hour>:<Minute>:<Second>[.<MilliSeconds>](Z|(+|-(<Hour>:<Minute>))) |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
<Operator> ::= <|<=|>=|>|=|!=
<RegularExpression> ::= <String>
See: https://docs.python.org/3/library/re.html>
<FieldNameFilter> :: = <RegularExpression>
<ColumnFieldNameFilterList> ::= "<FieldNameFilter>(,<FieldNameFilter>)*"
<RowValueFilter> ::=
[(any|all):]count<Operator><Number>|
[(any|all):]countrange=<Number>/<Number>|
[(any|all):]countrange!=<Number>/<Number>|
[(any|all):]date<Operator><Date>|
[(any|all):]textrange=<String>/<String>|
[(any|all):]textrange!=<String>/<String>|
[(any|all):]daterange=<Date>/<Date>|
[(any|all):]daterange!=<Date>/<Date>|
[(any|all):]length<Operator><Number>|
[(any|all):]lengthrange=<Number>/<Number>|
[(any|all):]lengthrange!=<Number>/<Number>|
[(any|all):]text<Operator><String>|
[(any|all):]time<Operator><Time>|
[(any|all):]timerange=<Time>/<Time>|
[(any|all):]timerange!=<Time>/<Time>|
[(any|all):]boolean:<Boolean>|
[(any|all):]regex:<RegularExpression>|
[(any|all):]regexcs:<RegularExpression>|
[(any|all):]notregex:<RegularExpression>|
[(any|all):]notregexcs:<RegularExpression>|
[(any|all):]data:<DataSelector>|
[(any|all):]notdata:<DataSelector>
<RowValueFilterList> ::=
"'<FieldNameFilter>:<RowValueFilter>'(,'<FieldNameFilter>:<RowValueFilter>')*"
<RowValueFilterJSONList> ::=
'{"<FieldNameFilter>": "<RowValueFilter>"(,"<FieldNameFilter>": "<RowValueFilter>")*}' |
"{\"<FieldNameFilter>\": \"<RowValueFilter>\"(,\"<FieldNameFilter>\": \"<RowValueFilter>\")*}"
```
## Quoting rules
Name:value form.
```
<RowValueFilterList> ::=
"'<FieldNameFilter>:<RowValueFilter>'(,'<FieldNameFilter>:<RowValueFilter>')*"
```
* `<RowValueFilterList>`, even if it has one element, should be enclosed in `"`.
* Each `<FieldNameFilter>:<RowValueFilter>` pair should be enclosed in `'`.
* If `<FieldNameFilter>` contains a `:` or a space, it should be enclosed in `\"`.
* If `<RegularExpression>` or `<DataSelector>` in `<RowValueFilter>` contain a space, it should be enclosed in `\"`.
* If `<FieldNameFilter>` or `<RegularExpression>` in `<RowValueFilter>` contain a `\` to escape a special character
or enter a special sequence, enter `\\\`.
Example:
```
csv_output_row_filter "'\"accounts:used_quota_in_mb\":count>15000'"
csv_output_row_filter "'email:data:\"csvfile gsheet:email user@domain.com FileID Sheet1\"'"
csv_output_row_filter "'phones.\\\d+.value:regex:(?:^\\\(510\\\) )|(?:^510[- ])\\\d{3}-\\\d{4}'"
```
JSON form.
```
<RowValueFilterJSONList> ::=
'{"<FieldNameFilter>": "<RowValueFilter>"(,"<FieldNameFilter>": "<RowValueFilter>")*}' |
"{\"<FieldNameFilter>\": \"<RowValueFilter>\"(,\"<FieldNameFilter>\": \"<RowValueFilter>\")*}"
```
* The first form can be used on Linux and Mac OS; it can not be used on Windows.
* The second form can be used on Linux, Mac OS and Windows.
* If `<FieldNameFilter>` contains a `:`, no additional quoting is required
Example:
```
csv_output_row_filter '{"accounts:used_quota_in_mb": "count>=150"}'
csv_output_row_filter "{\"accounts:used_quota_in_mb\": \"count>=150\"}"
```
## Column header filtering
Gam gives you the ability to select fields(column headers) in its print commands, but there may be cases
where you get more columns than is desirable.
* `csv_output_header_filter` - Used to select the column headers to include in the output
* `csv_output_header_drop_filter` - Used to select the column headers to exclude from the output
Typically, you would use the option that involes typing the fewest column names but both options can be used.
When both options are used, `csv_output_header_drop_filter` is processed first, then `csv_output_header_filter`.
Field names are specified by regular expressions; at its simplest, you specify a complete field name.
Field names are matched in a case insensitive manner.
```
gam config csv_output_header_filter <ColumnFieldNameFilterList> ...
gam config csv_output_header_drop_filter <ColumnFieldNameFilterList> ...
```
### Example
you want a list of user email addresses and full names; you do not need the given or family names.
No filtering.
```
gam print users name
primaryEmail,name.givenName,name.familyName,name.fullName
testuser1@domain.com,Test,User1,Test User1
testuser2@domain.com,Test,User2,Test User2
...
```
With inclusion filtering.
```
gam config csv_output_header_filter "primaryEmail,name.fullName" print users name
primaryEmail,name.fullName
testuser1@domain.com,Test User1
testuser2@domain.com,Test User2
...
```
With exclusion filtering.
```
gam config csv_output_header_drop_filter "name.givenName,name.familyName" print users name
primaryEmail,name.fullName
testuser1@domain.com,Test User1
testuser2@domain.com,Test User2
...
```
## Column row filtering
Row filtering includes/excludes rows based on column values.
### Field names
Field names are specified by regular expressions; at its simplest, you specify a complete field name.
Field names are matched in a case insensitive manner.
If the field name doesn't contain any of the following regular expression characters `^$*+|$[{(`,
it will be surrounded with `^$` so that it doesn't match any subfields that begin with the field name as a prefix.
The following filter will match the count field and not the subfields.
```
config csv_output_row_filter "'externalIds:countrange=1/10'"
primaryEmail,externalIds,externalIds.0.type,externalIds.0.value,externalIds.1.type,externalIds.1.value,...
```
### Inclusive filters
You can include rows generated by gam print commands based on column values. You specify a list
of fields (headers) and the values they must have. `csv_output_row_filter` is used to specify the
fields and values. Each field name/expression can appear only once in the list.
You specify whether all or any value filters must match for the row to be included in the output.
* `csv_output_row_filter_mode allmatch` - All value filters must match for the row to be included in the output; this is the default
* `csv_output_row_filter_mode anymatch` - Any value filter must match for the row to be included in the output
```
gam config csv_output_row_filter <RowValueFilterList> ...
gam config csv_output_row_filter <RowValueFilterJSONList> ...
```
### Exclusive filters
You can exclude rows generated by gam print commands based on column values. You specify a list
of fields (headers) and the values they must not have. `csv_output_row_drop_filter` is used to specify the
fields and values. Each field name/expression can appear only once in the list.
You specify whether all or any value filters must match for the row to be excluded from the output.
* `csv_output_row_filter_drop_mode allmatch` - If all value filters match, the row is excluded from the output
* `csv_output_row_filter_drop_mode anymatch` - If any value filter matches, the row is excluded from the output; this is the default
```
gam config csv_output_row_drop_filter <RowValueFilterList> ...
gam config csv_output_row_drop_filter <RowValueFilterJSONList> ...
```
### Matches
A filter matches if the field has the desired value. lf you specify a regular expression for a field name that matches
several columns, the filter matches if any of the columns has a match. In the case of `notregex|notregexcs|notdata`,
the filter matches if none (not any) of the columns has a match.
`<RowValueFilter>` allows specifying that the filter will match only if all of the columns have a match.
In the case of `notregex|notregexcs|notdata`, the filter matches if some (not all) of the columns have a match.
If neither `any` or `all` is explicitly specified, `any` is the default.
These are the row value filter types:
* `count<Operator><Number>` - Used on fields with numbers; a blank field will not match
* `countrange=<Number>/<Number>` - Used on fields with numbers; a blank field will not match
* The field value must be `>=` the left `<Number>` and `<=` the right `<Number>`
* `countrange!=<Number>/<Number>` - Used on fields with numbers; a blank field will not match
* The field value must be `<` the left `<Number>` or `>` the right `<Number>`
* `date<Operator><Date>` - Used on fields with dates or times; only the date portion of a time field is compared; a blank field will not match
* `daterange=<Date>/<Date>` - Used on fields with dates or times; only the date portion of a time field is compared; a blank field will not match
* The field value must be `>=` the left `<Date>` and `<=` the right `<Date>`
* `daterange!=<Date>/<Date>` - Used on fields with dates or times; only the date portion of a time field is compared; a blank field will not match
* The field value must be `<` the left `<Date>` or `>` the right `<Date>`
* `length<Operator><Number>` - Used on fields with strings; non string fields will not match
* `lengthrange=<Number>/<Number>` - Used on fields with strings; non string fields will not match
* The field length must be `>=` the left `<Number>` and `<=` the right `<Number>`
* `lengthrange!=<Number>/<Number>` - Used on fields with strings; non string fields will not match
* The field length must be `<` the left `<Number>` or `>` the right `<Number>`
* `text<Operator><String>` - Used on fields with text
* `textrange=<String>/<String>` - Used on fields with strings
* The field value must be `>=` the left `<String>` and `<=` the right `<String>`
* `textrange!=<String>/<String>` - Used on fields with strings
* The field value must be `<` the left `<String>` or `>` the right `<String>`
* `time<Operator><Time>` - Used on fields with times; a blank field will not match
* `timerange=<Time>/<Time>` - Used on fields with times; a blank field will not match
* The field value must be `>=` the left `<Time>` and `<=` the right `<Time>`
* `timerange!=<Time>/<Time>` - Used on fields with times; a blank field will not match
* The field value must be `<` the left `<Time>` or `>` the right `<Time>`
* `boolean:<Boolean>` - Used on fields with Boolean values; a blank field is considered False
* `regex:<RegularExpression>` - Used on fields with text; field value must match `<RegularExpression>`; case insensitive
* `regexcs:<RegularExpression>` - Used on fields with text; field value must match `<RegularExpression>`; case sensitive
* `notregex:<RegularExpression>` - Used on fields with text; field value must not match `<RegularExpression>`; case insensitive
* `notregexcs:<RegularExpression>` - Used on fields with text; field value must not match `<RegularExpression>`; case sensitive
* `data:<DataSelector>` - Used on fields with text; field value must match some value in `<DataSelector>`; case sensitive
* `notdata:<DataSelector>` - Used on fields with text; field value must not match any value in `<DataSelector>`; case sensitive
### **Change in behavior.**
In versions prior to `5.12.00`, `regex:<RegularExpression>` and `notregex:<RegularExpression>` were processed in a case sensitive manner;
in many cases this is probably not desirable; e.g., matching file names which are case insensitive.
Now, `regex:<RegularExpression>` and `notregex:<RegularExpression>` are processed in a case insensitive manner.
To get the prior case sensitive processing, use `regexcs:<RegularExpression>` and `notregexcs:<RegularExpression>`.
### Examples
You want a list of groups with 100 or more direct members.
```
gam config csv_output_row_filter "'directMembersCount:count>100'" print groups fields directmemberscount
```
You want a list of users created in the last 30 days.
```
gam config csv_output_row_filter "'creationTime:date>=-30d'" print users fields creationtime
```
You want a list of users in the OU /Test that are consuming more than 15GB of storage.
Special quoting is required because the field name contains a colon.
```
gam config csv_output_row_filter "'\"accounts:used_quota_in_mb\":count>15000'" report users select ou /Test fields accounts:used_quota_in_mb
```
You want the names of users directly in the OU /Test, you do not want users in any sub-OUs of /Test.
* The Google API will only supply users in an OU and sub-OUs, GAM has to filter out the users in the sub-OU.
```
gam config csv_output_row_filter "'orgUnitPath:regex:^/Test$'" print users query "orgUnitPath=/Test" fields name,ou
```
You want the names of female users directly in the OU /Test, you do not want users in any sub-OUs of /Test.
* The Google API will only supply users in an OU and sub-OUs, GAM has to filter out the users in the sub-OU.
```
gam config csv_output_row_filter "'orgUnitPath:regex:^/Test$','gender:regex:female'" print users query "orgUnitPath=/Test" fields name,ou,gender
```
You want a list of groups not created by an administrator.
```
gam config csv_output_row_filter "'adminCreated:boolean:false'" print groups fields admincreated
```
You want a list of users with phone numbers in the area code 510; the number can be in the format `(510) ddd-dddd` or `510-ddd-dddd` or `510 ddd-dddd`.
```
gam config csv_output_header_filter "primaryEmail,name.fullName,phones.*value" csv_output_row_filter "'"'phones.\\\d+.value:regex:(?:^\\\(510\\\) )|(?:^510[- ])\\\d{3}-\\\d{4}'"'" print users name phones
primaryEmail,name.fullName,phones.0.value
testuser1@domain.com,Test User1,(510) 555-1212
testuser2@domain.com,Test User2,510-555-1212
testuser3@domain.com,Test User3,510 555-1212
```
You want a list of users not in the organization cost center "Tech Support".
```
gam config csv_output_header_filter "primaryEmail,name.fullName,orgUnitPath,organizations.*costCenter" csv_output_row_filter 'organizations.*costCenter:notregex:"Tech Support"' print users fields name,ou,organizations
gam config csv_output_header_filter "primaryEmail,name.fullName,orgUnitPath,organizations.*costCenter" csv_output_row_drop_filter 'organizations.*costCenter:regex:"Tech Support"' print users fields name,ou,organizations
primaryEmail,name.fullName,orgUnitPath,organizations.0.costCenter
testuser1@domain.com,Test User1,/Test,Sales
testuser2@domain.com,Test User2,/Test,Development
```
You want a list of recurring events with at least one external guest.
```
gam config csv_output_row_filter "'^attendees$:count>1','recurrence:count>=1','attendees.*email:all:notregex:(^$)|(.+@domain.com)'" csv_output_row_drop_filter "'attendees.*email:regex:.+@resource.calendar.google.com'" redirect csv ./externalrecurringEvents.csv calendar <CalendarEntity> print events
```
## Column row limiting
You can limit the number of rows written to a CSV file.
When single processing, the limit is on the total number of rows written to the file.
When multiprocessing, the limit is on the number of rows written to the file by each subprocess.
### Examples
Display the 10 files with the largest quotaBytesUsed values for a single user.
```
gam config csv_output_row_limit 10 redirect csv ./BigQuotaFiles.csv user user@domain.com print filelist fields id,name,quotabytesused orderby quotabytesused descending
```
Display the 10 files with the largest quotaBytesUsed values for all users
```
gam config csv_output_row_limit 10 auto_batch_min 1 redirect csv ./BigQuotaFiles.csv multiprocess all users print filelist fields id,name,quotabytesused orderby quotabytesused descending
```
## Saving filters in gam.cfg
If you define a value for `csv_output_header_filter`, `csv_output_header_drop_filter`, `csv_output_row_filter`, `csv_output_row_drop_filter` or `csv_output_row_limit` in the `[DEFAULT]` section of `gam.cfg`,
it will apply to every `gam print` command which is probably not desirable. You can store them in `gam.cfg` in named sections.
```
[Filter510]
csv_output_header_filter = primaryEmail,name.fullName,phones.*value
csv_output_row_filter = 'phones.\\\d+.value:regex:(?:^\\\(510\\\) )|(?:^510[- ])\\\d{3}-\\\d{4}'
$ gam selectfilter Filter510 print users name phone
primaryEmail,name.fullName,phones.0.value
testuser1@domain.com,Test User1,(510) 555-1212
testuser2@domain.com,Test User2,510-555-1212
testuser3@domain.com,Test User3,510 555-1212
```
If you have multiple customers or domains in separate sections of gam.cfg, you use `select` to choose the customer/domain
and `selectfilter` to choose a filter.
```
[foo]
domain = foo.com
customer_id = C111111111
config_dir = foo
[goo]
domain = goo.com
customer_id = C222222222
config_dir = goo
[Filter510]
csv_output_header_filter = primaryEmail,name.fullName,phones.*value
csv_output_row_filter = 'phones.\\\d+.value:regex:(?:^\\\(510\\\) )|(?:^510[- ])\\\d{3}-\\\d{4}'
$ gam select foo selectfilter Filter510 print users name phone
primaryEmail,name.fullName,phones.0.value
testuser1@foo.com,Test User1,(510) 555-1212
testuser2@foo.com,Test User2,510-555-1212
testuser3@foo.com,Test User2,510 555-1212
```

80
docs/Calendars-Access.md Normal file
View File

@ -0,0 +1,80 @@
# Calendars - Access
- [Notes](#Notes)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Manage calendar access](#manage-calendar-access)
- [Display calendar access](#display-calendar-access)
- [Old format commands](#old-format-commands)
## Notes
These commands use Client access for all commands except those that reference user's primary calendars
where Service Account access is used. When using Client access on user's secondary calendars, some operations are restricted.
In general, you should use the following commands to manage user's calendars access.
* [Users - Calendars - Access](Users-Calendars-Access)
Client access works when accessing Resource calendars.
Calendar ACL roles (as seen in Calendar GUI):
* `reader` - See all event details
* `writer` & `editor` Make changes to events
* `owner` - Make changes to events and manage sharing
* `freebusy` & `freebusyreader` - See only free/busy (hide details)
## API documentation
* https://developers.google.com/calendar/v3/reference/acl
## Definitions
```
<CalendarItem> ::= <EmailAddress>
<CalendarList> ::= "<CalendarItem>(,<CalendarItem>)*"
<CalendarEntity> ::= <CalendarList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<CalendarACLRole> ::= editor|freebusy|freebusyreader|owner|reader|writer
<CalendarACLScope> ::= <EmailAddress>|user:<EmailAdress>|group:<EmailAddress>|domain:<DomainName>|domain|default
<CalendarACLScopeList> ::= "<CalendarACLScope>(,<CalendarACLScope>)*"
<CalendarACLScopeEntity>::= <CalendarACLScopeList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
```
## Manage calendar access
```
gam calendars <CalendarEntity> add acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
gam calendars <CalendarEntity> update acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
gam calendars <CalendarEntity> delete acls|calendaracls [<CalendarACLRole>] <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.
## Display calendar access
```
gam calendars <CalendarEntity> info acls|calendaracls <CalendarACLScopeEntity> [formatjson]
gam calendars <CalendarEntity> show acls|calendaracls
[noselfowner]
[formatjson]
```
Option `noselfowner` suppresses the display of ACLs that reference the calendar itself as its owner.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam calendars <CalendarEntity> print acls|calendaracls [todrive <ToDriveAttribute>*]
[noselfowner]
[formatjson [quotechar <Character>]]
```
Option `noselfowner` suppresses the display of ACLs that reference the calendar itself as its owner.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
### Old format commands
These commands are backwards compatible with basic GAM.
```
gam calendar <CalendarEntity> add <CalendarACLRole> ([user] <EmailAddress>)|(group <EmailAddress>)|(domain [<DomainName>])|default [sendnotifications <Boolean>]
gam calendar <CalendarEntity> update <CalendarACLRole> ([user] <EmailAddress>)|(group <EmailAddress>)|(domain [<DomainName>])|default [sendnotifications <Boolean>]
gam calendar <CalendarEntity> delete [<CalendarACLRole>] ([user] <EmailAddress>)|(group <EmailAddress>)|(domain [<DomainName>])|default
gam calendar <CalendarEntity> showacl [formatjson]
gam calendar <CalendarEntity> printacl [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]
```
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.

564
docs/Calendars-Events.md Normal file
View File

@ -0,0 +1,564 @@
# Calendars - Events
- [Notes](#Notes)
- [API documentation](#api-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Search function
- [Collections of Users](Collections-of-Users)
- [Definitions](#definitions)
- [Recurrence rules](#recurrence-rules)
- [Event colors](#event-colors)
- [Event selection](#event-selection)
- [Add and import calendar events](#add-and-import-calendar-events)
- [Add calendar attendees](#add-calendar-attendees)
- [Update calendar events](#update-calendar-events)
- [Update calendar attendees](#update-calendar-attendees)
- [Specify calendar attendees with JSON data](#specify-calendar-attendees-with-JSON-data)
- [Delete selected calendar events](#delete-selected-calendar-events)
- [Delete all calendar events](#delete-all-calendar-events)
- [Move calendar events to another calendar](#move-calendar-events-to-another-calendar)
- [Empty calendar trash](#empty-calendar-trash)
- [Display calendar events](#display-calendar-events)
- [Old format commands](#old-format-commands)
## Notes
These commands use Client access for all commands except those that reference user's primary calendars
where Service Account access is used. When using Client access on user's secondary calendars, some operations are restricted.
In general, you should use the following commands to manage user's calendars events.
* [Users - Calendars - Events](Users-Calendars-Events)
Client access works when accessing Resource calendars.
## API documentation:
* https://developers.google.com/calendar/v3/reference/events
* https://developers.google.com/calendar/v3/reference/events/import
## Definitions
```
<Year> ::= <Digit><Digit><Digit><Digit>
<Month> ::= <Digit><Digit>
<Day> ::= <Digit><Digit>
<Hour> ::= <Digit><Digit>
<Minute> ::= <Digit><Digit>
<Second> ::= <Digit><Digit>
<MilliSeconds> ::= <Digit><Digit><Digit>
<Date> ::=
<Year>-<Month>-<Day> |
(+|-)<Number>(d|w|y) |
never|
today
<DateTime> ::=
<Year>-<Month>-<Day>(<Space>|T)<Hour>:<Minute> |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
<Time> ::=
<Year>-<Month>-<Day>(<Space>|T)<Hour>:<Minute>:<Second>[.<MilliSeconds>](Z|(+|-(<Hour>:<Minute>))) |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
<TimeZone> ::= <String>
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<CalendarItem> ::= <EmailAddress>
<CalendarList> ::= "<CalendarItem>(,<CalendarItem>)*"
<CalendarEntity> ::= <CalendarList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<EmailAddressList> ::= "<EmailAddess>(,<EmailAddress>)*"
<EmailAddressEntity> ::= <EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<EventAttachmentsSubfieldName> ::=
attachments.fileid|
attachments.fileurl|
attachments.iconlink|
attachments.mimetype|
attachments.title
<EventAttendeesSubfieldName> ::=
attendees.additionalguests|
attendees.comment|
attendees.displayname|
attendees.email|
attendees.id|
attendees.optional|
attendees.organizer|
attendees.resource|
attendees.responseStatus|
attendees.self
<EventConferenceDataSubfieldName> ::=
conferencedata.conferenceid|
conferencedata.conferencesolution|
conferencedata.createrequest|
conferencedata.entrypoints|
conferencedata.notes|
conferencedata.signature
<EventCreatorSubfieldName> ::=
creator.displayname|
creator.email|
creator.id|
creator.self
<EventOrganizerSubfieldName> ::=
organizer.displayname|
organizer.email|
organizer.id|
organizer.self
<EventWorkingLocationPropertiesSubfieldName> ::=
workinglocationproperties.homeoffice|
workinglocationproperties.customlocation|
workinglocationproperties.officelocation
<EventFieldName> ::=
anyonecanaddself|
attachments|
<EventAttachmentsSubfieldName>|
attendees|
<EventAttendeesSubfieldName>|
attendeesomitted|
colorid|
conferencedata|
<EventConferenceDataSubfieldName>|
created|
creator|
<EventCreatorSubfieldName>|
description|
end|endtime|
endtimeunspecified|
extendedproperties|
eventtype|
gadget|
guestscaninviteothers|
guestscanmodify|
guestscanseeotherguests|
hangoutlink|
htmllink|
icaluid|
id|
location|
locked|
organizer|
<EventOrganizerSubfieldName>|
originalstart|originalstarttime|
privatecopy|
recurrence|
recurringeventid|
reminders|
sequence|
source|
start|starttime|
status|
summary|
transparency|
updated|
visibility|
workinglocationproperties|
<EventFieldNameList> ::= "<EventFieldName>(,<EventFieldName>)*"
<AttendeeAttendance> ::= optional|required
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
<EventSelectProperty> ::=
(after|starttime|timemin <Time>)|
(before|endtime|timemax <Time>)|
(query <QueryCalendar>)|
(privateextendedproperty <String>)|
(sharedextendedproperty <String>)|
showdeletedevents|
showhiddeninvitations|
singleevents|
(updatedmin <Time>)
<EventMatchProperty> ::=
(matchfield attendees <EmailAddressEntity>)|
(matchfield attendeespattern <RegularExpression>)|
(matchfield attendeesstatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddressEntity>)|
(matchfield creatoremail <RegularExpression>)|
(matchfield creatorname <RegularExpression>)|
(matchfield description <RegularExpression>)|
(matchfield hangoutlink <RegularExpression>)|
(matchfield location <RegularExpression>)|
(matchfield organizeremail <RegularExpression>)|
(matchfield organizername <RegularExpression>)|
(matchfield status <RegularExpression>)|
(matchfield summary <RegularExpression>)|
(matchfield transparency <RegularExpression>)|
(matchfield visibility <RegularExpression>)
<EventIDEntity> ::=
(id|eventid <EventId>) |
(event|events <EventIdList> |
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector> | <CSVDataSelector>)
<EventSelectEntity> ::=
(<EventSelectProperty>+ <EventMatchProperty>*)
<EventEntity> ::=
<EventIDEntity> | <EventSelectEntity>
<EventColorIndex> ::= <Number in range 1-11>
<EventColorName> ::=
banana|basil|blueberry|flamingo|graphite|grape|
lavender|peacock|sage|tangerine|tomato
<PropertyKey> ::= <String>
<PropertyValue> ::= <String>
<EventAttribute> ::=
(anyonecanaddself [<Boolean>])|
(attachment <String> <URL>)|
(attendee <EmailAddress>)|
(attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>)|
available|
(color <EventColorName>)|
(colorindex|colorid <EventColorIndex>)|
(description <String>)|
(end (allday <Date>)|<Time>)|
(guestscaninviteothers <Boolean>)|
guestscantinviteothers|
(guestscanmodify <Boolean>)|
(guestscanseeotherguests <Boolean>)|
guestscantseeotherguests|
hangoutsmeet|
<JSONData>|
(jsonattendees [charset <Charset>] <String>)|
(jsonattendees file <FileName> [charset <Charset>])|
(location <String>)|
(noreminders|(reminder email|popup <Number>))|
(optionalattendee <EmailAddress>)|
(originalstart|originalstarttime (allday <Date>)|<Time>)|
(privateproperty <PropertyKey> <PropertyValue>)|
(recurrence <RRULE, EXRULE, RDATE and EXDATE line>)|
(reminder <Number> email|popup))|
(selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>)|
(sequence <Integer>)|
(sharedproperty <PropertyKey> <PropertyValue>)|
(source <String> <URL>)|
(start (allday <Date>)|<Time>)|
(status confirmed|tentative|cancelled)|
(summary <String>)|
tentative|
(timezone <TimeZone>)|
(transparency opaque|transparent)|
(visibility default|public|private)
The following attributes are equivalent:
available - transparency transparent
guestscantinviteothers - guestscaninviteothers False
guestscantseeothers - guestscanseeotherguests False
tentative - status tentative
<EventImportAttribute> ::=
<EventAttribute>|
(organizername <String>)|
(organizeremail <EmailAddress>)
<EventUpdateAttribute> ::=
<EventAttribute>|
clearattachments|
clearattendees|
clearhangoutsmeet|
(clearprivateproperty <PropertyKey>)|
(clearsharedproperty <PropertyKey>)|
(removeattendee <EmailAddress>)|
(replacedescription <RegularExpression> <String>)|
(selectremoveattendees <UserTypeEntity>)
<EventNotificationAttribute> ::=
notifyattendees|(sendnotifications <Boolean>)|(sendupdates all|enternalonly|none)
The following attributes are equivalent:
notifyattendees - sendupdates all
sendnotifications false - sendupdates none
sendnotifications true - sendupdates all
<EventDisplayProperty> ::=
(alwaysincludeemail)|
(icaluid <String>)|
(maxattendees <Integer>)|
(orderby starttime|updated)|
(timezone <TimeZone>)
```
## Recurrence rules
Recurring events require a rule: `recurrence <RRULE, EXRULE, RDATE and EXDATE line>`
* https://tools.ietf.org/html/rfc5545#section-3.8.5
This is dense reading; a simpler approach is to define a test event in Google Calendar with
the recurrence rule that you want, then use `gam info event` to get the recurrence rule and use it in subsequent commands.
```
RRULE:FREQ=DAILY
RRULE:FREQ=DAILY;COUNT=30
RRULE:FREQ=WEEKLY;BYDAY=WE
RRULE:FREQ=WEEKLY;WKST=SU;COUNT=13;BYDAY=WE
```
## Event colors
The event color grid presented in calendar.google.com and `<EventColorIndex>` are related like this:
```
11:tomato 4:flamingo
6:tangerine 5:banana
2:sage 10:basil
7:peacock 9:blueberry
1:lavender 3:grape
8:graphite
```
## Event selection
These are the possible values for `<EventEntity>`; you either specify event IDs or properties used to select events.
If none of the following options are selected, all events are selected.
* `id|eventid <EventId>` - A single event ID
* `event|events <EventIdList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector> | <CSVDataSelector>)` - A collection of event IDs: [Collections of Items](Collections-of-Items)
* `<EventSelectProperty>* <EventMatchProperty>*` - Properties used to select events
The Google Calendar API processes `<EventSelectProperty>*`; you may specify none or multiple properties.
* `after|starttime|timemin <Time>` - Lower bound (inclusive) for an event's end time to filter by. If timeMax is set, timeMin must be smaller than timeMax.
* `before|endtime|timemax <Time>` - Upper bound (exclusive) for an event's start time to filter by. If timeMin is set, timeMax must be greater than timeMin.
* `query <QueryCalendar>` - Free text search terms to find events that match these terms in any field, except for extended properties
* `privateextendedproperty <String>` - A required private property; `<String>` must be of the form `propertyName=value`
* `sharedextendedproperty <String>` - A required shared property; `<String>` must be of the form `propertyName=value`
* `showdeletedevents` - Whether to include deleted events (with status equals "cancelled") in the result
* `showhiddeninvitations` - Whether to include hidden invitations in the result
* `singleevents` - Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves
* `updatedmin <Time>` - Lower bound for an event's last modification time (as a RFC3339 timestamp) to filter by. When specified, entries deleted since this time will always be included regardless of showdeletedevents
GAM processes `<EventMatchProperty>*`; you may specify none or multiple properties.
* `matchfield attendees <EmailAddressEntity>` - All of the attendees in `<EmailAddressEntity>` must be present
* `matchfield attendeespattern <RegularExpression>` - Some attendee must match `<RegularExpression>`
* `matchfield attendeesstatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddressEntity>` - All of the attendees in `<EmailAddressEntity>` must be present
and must have the specified values.
* `<AttendeeAttendance>` - Default is `required`
* `<AttendanceStatus>` - Default is`needsaction`
* `matchfield creatoremail <RegularExpression>` - The creator email address must match `<RegularExpression>`
* `matchfield creatorname <RegularExpression>` - The creator name must match `<RegularExpression>`
* `matchfield description <RegularExpression>` - The description (summary) must match `<RegularExpression>`
* `matchfield location <RegularExpression>` - The location must match `<RegularExpression>`
* `matchfield organizeremail <RegularExpression>` - The organizer email address must match `<RegularExpression>`
* `matchfield organizername <RegularExpression>` - The orgainzer name must match `<RegularExpression>`
* `matchfield status <RegularExpression>` - The summary must match `<RegularExpression>`. The API documented values are:
* `confirmed`
* `tentative`
* `cancelled`
* `matchfield summary <RegularExpression>` - The summary must match `<RegularExpression>`
* `matchfield transparency <RegularExpression>` - The summary must match `<RegularExpression>`. The API documented values are:
* `opaque` - Busy. The API does not seem to return this value; use `"(^$)|opaque"` to match no value or `opaque`.
* `transparent` - Free/Available
* `matchfield visibility <RegularExpression>` - The summary must match `<RegularExpression>`. The API documented values are:
* `default` - The API does not seem to return this value; use `"(^$)|default"` to match no value or `default`.
* `public` - The API does not seem to return this value if it is the default; use `"(^$)|public"` to match no value or `public`.
* `private` - The API does not seem to return this value if it is the default; use `"(^$)|private"` to match no value or `private`.
* `confidential`
## Add and import calendar events
```
gam calendar <CalendarEntity> add event [id <String>] <EventAttribute>+ [<EventNotificationAttribute>]
[showdayofweek]
[csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
gam calendar <CalendarEntity> import event icaluid <iCalUID> <EventImportAttribute>+
[showdayofweek]
[csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
```
By default, when an event is created|imported, GAM outputs the calendar name and event ID.
* `csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]` - Output the event details in CSV format.
You can specify multiple attachments; `<String>` is the title of the attachment and `<URL>` is a sharable link from Google Drive.
You must specify all attachments in each command, you can not incrementally add attachments.
Importing events is similar to adding events; the principal difference
is that you must specify an `iCalUID`. All instances of recurring events will have the same
`iCalUID` but different `EventIDs`. The import command supports two new attributes to set the
event organizer, but the API doesn't seem to honor the values; the organizer is set to
the calendar owner.
## Add calendar attendees
You can specify attendees in the following ways:
* `attendee <EmailAddress>` - The attendee attendance is required with status `needsaction'
* `optionalattendee <EmailAddress>` - The attendee attendance is optional with status `needsaction'
* `attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>` - One attendee
* If `<AttendeeAttendance>` is not specified, the attendee is required to attend
* If `<AttendeeStatus>` is not specified, `needsaction` is chosen
* `jsonattendees [charset <Charset>] <String>`
* `jsonattendees file <FileName> [charset <Charset>]`
* `selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>` - Multiple attendees
* If `<AttendeeAttendance>` is not specified, all attendees are required to attend
* If `<AttendeeStatus>` is not specified, `needsaction` is chosen
To add an attendee to a single recurring calendar event, you need to specify the ID of that specific event.
```
gam calendar <CalendarEntity> update event id xxxxxxx_YYYYMMDDTHHMMSSZ attendee attendee@domain.com
```
For `<UserTypeEntity>` See: [Collections of Users](Collections-of-Users)
## Update calendar events
```
gam calendar <CalendarEntity> update event [<EventEntity>] <EventUpdateAttribute>+ [<EventNotificationAttribute>]
[showdayofweek]
[csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
```
If `<EventEntity>` is not specified, all events in `<CalendarEntity>` are selected. This is not typically used
unless you're trying to change a basic `<EventAttribute>`, e.g., `color`, on all events.
By default, when an event is updated, GAM outputs the calendar name and event ID.
* `csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]` - Output the event details in CSV format.
You can clear/modify existing attributes:
* `clearattachments` - Delete all attachments
* `clearhangoutsmeet` - Clear Hangouts/Meet link
* `clearprivateproperty <PropertyKey>` - Clear private properties
* `clearsharedproperty <PropertyKey>` - Clear shared properties
* `replacedescription <RegularExpression> <String>` - Modify the description
## Update calendar attendees
The default behavior of `gam calendar <CalendarEntity> update events` has been changed regarding attendees.
In versions of GAM before `5.02.00`, updating attendees in calendar events was complicated because you had to
supply the complete attendee list even if you just wanted incremental changes.
The default behavior now is to allow incremental changes to the attendees list;
the current attendee list is downloaded and the specified changes are applied.
The `replacemode` option invokes the previous behavior from versions before `5.02.00`; the current attendee list is replaced.
You can add attendees in the following ways:
* `attendee <EmailAddress>` - The attendee attendance is required with status `needsaction'
* `optionalattendee <EmailAddress>` - The attendee attendance is optional with status `needsaction'
* `attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>` - One attendee
* If `<AttendeeAttendance>` is not specified, the attendee is required to attend
* If `<AttendeeStatus>` is not specified, `needsaction` is chosen
* `jsonattendees [charset <Charset>] <String>`
* `jsonattendees file <FileName> [charset <Charset>]`
* `selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>` - Multiple attendees
* If `<AttendeeAttendance>` is not specified, all attendees are required to attend
* If `<AttendeeStatus>` is not specified, `needsaction` is chosen
You can remove attendees in the following ways:
* `clearattendees` - Clear all current attendees from the attendee list
* `removeattendee <EmailAddress>` - Remove a single attendee from the attendee list
* `selectremoveattendees <UserTypeEntity>` - Remove a selected collection of attendees from the attendee list
For `<UserTypeEntity>` See: [Collections of Users](Collections-of-Users)
## Specify calendar attendees with JSON data
You can predefine lists of attendees and use them when creating/updating events. If you set `responseStatus` to `accepted`, no notifications are sent.
```
$ more attendees.json
{"attendees": [{"email": "testuser2@domain.com", "responseStatus": "needsAction", "optional": "True"}, {"email": "testuser3@domain.com", "responseStatus": "accepted"}, {"email": "testuser4@domain.com", "responseStatus": "accepted"}]}
```
You can use output the attendee information for an event in a calendar and use that data when defining other events.
```
$ gam redirect stdout ./attendees.json calendar testuser1@domain.com info event id 0000h8kk7c9o2tonk73hu2zzzz fields attendees formatjson
$ more attendees.json
{"calendarId": "testuser1@domain.com", "event": {"attendees": [{"email": "testuser3@domain.com", "responseStatus": "accepted"}, {"email": "testuser4@domain.com", "responseStatus": "accepted"}], "id": "0000h8kk7c9o2tonk73hu2zzzz"}}
```
Use `jsonattendees file ./attendees.json` in `create/update event`.
## Delete selected calendar events
```
gam calendar <CalendarEntity> delete events [<EventEntity>] [doit] [<EventNotificationAttribute>]
gam calendar <CalendarEntity> purge events [<EventEntity>] [doit] [<EventNotificationAttribute>]
```
If `<EventEntity>` is not specified, all events in `<CalendarEntity>` are selected. This is not typically used.
No events are deleted unless you specify the `doit` option; omit `doit` to verify that you properly selected the events to delete.
When events are deleted from a calendar, they are moved to the calendar's trash and are only permanently deleted (purged) after 30 days.
Following a suggestion here (https://stackoverflow.com/questions/41043053/how-to-empty-calendar-trash-via-google-services) you can permanently delete
calendar events. This is achieved by creating a temporary calendar, deleting the events, moving the deleted events to the temporary calendar
and then deleting the temporary calendar.
## Delete all calendar events
For a user's primary calendar:
```
gam calendar <CalendarEntity> wipe events
```
For non-primary calendars:
```
gam calendar <CalendarEntity> delete events [doit] [<EventNotificationAttribute>]
```
No events are deleted unless you specify the `doit` option; omit `doit` to verify that you properly selected the events to delete.
## Move calendar events to another calendar
Generally you won't move all events from one calendar to another; typically, you'll move events created by the event creator
using `matchfield creatoremail <RegularExpression>` in conjunction with other `<EventSelectProperty>` and `<EventMatchProperty>` options.
```
gam calendar <CalendarEntity> move event [<EventEntity>] destination|to <CalendarItem> [<EventNotificationAttribute>]
```
## Empty calendar trash
A user signed in to Google Calendar can empty the calendar trash but there is no direct API support for this operation.
To empty the calendar trash a temporary calendar is created, the deleted events are moved to the temporary calendar and then the temporary calendar is deleted.
```
gam calendar|calendars <CalendarEntity> empty calendartrash
```
## Display calendar events
```
gam calendar <CalendarEntity> info events [<EventEntity>] [maxinstances <Number>]
[fields <EventFieldNameList>] [showdayofweek]
[formatjson]
```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
* `maxinstances -1` - Default, display base event
* `maxinstances 0` - Display all instances of a recurring event
* `maxinstances N` - Display first N instances of a recurring event
`showdayofweek` displays `dayOfWeek` when event start and end times are displayed.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam calendar <CalendarEntity> show events [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsonly] [formatjson]
```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
By default, only the base event of a recurring event is displayed. Use the `<EventSelectProperty>`
option `singleevents` to display all instances of a recurring event.
`<EventDisplayProperty> orderby starttime` is only valid with `<EventSelectProperty> singleevents`.
`showdayofweek` displays `dayOfWeek` when event start and end times are displayed.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
By default, Gam displays event details, use `countsonly` to display only the number of events. `formatjson` does not apply in this case.
```
gam calendar <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsonly] [formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
By default, only the base event of a recurring event is displayed. Use the `<EventSelectProperty>`
option `singleevents` to display all instances of a recurring event.
`<EventDisplayProperty> orderby starttime` is only valid with `<EventSelectProperty> singleevents`.
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, Gam displays event details, use `countsonly` to display only the number of events. `formatjson` does not apply in this case.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
### Old format commands
These commands are backwards compatible with basic Gam.
```
gam calendar <CalendarEntity> addevent <EventAttribute>+ [<EventNotificationAttribute>]
gam calendar <CalendarEntity> deleteevent (id|eventid <EventID>)+ [doit] [<EventNotificationAttribute>]
gam calendar <CalendarEntity> moveevent (id|eventid <EventID>)+ destination <CalendarItem> [<EventNotificationAttribute>]
gam calendar <CalendarEntity> updateevent <EventID> <EventAttribute>+ [<EventNotificationAttribute>]
gam calendar <CalendarEntity> wipe
gam calendar <CalendarEntity> printevents <EventSelectProperty>* <EventDisplayProperty>* [fields <EventFieldNameList>]
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
```

65
docs/Calendars.md Normal file
View File

@ -0,0 +1,65 @@
# Calendars
- [Notes](#Notes)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Modify calendar settings](#modify-calendar-settings)
- [Display calendar settings](#display-calendar-settings)
## Notes
These commands use Client access for all commands except those that reference user's primary calendars
where Service Account access is used. When using Client access on user's secondary calendars, some operations are restricted.
In general, you should use the following commands to manage user's calendars.
* [Users - Calendars](Users-Calendars)
Client access works when accessing Resource calendars.
## API documentation
* https://developers.google.com/google-apps/calendar/v3/reference/calendars
## Definitions
```
<CalendarItem> ::= <EmailAddress>
<CalendarList> ::= "<CalendarItem>(,<CalendarItem>)*"
<CalendarEntity> ::= <CalendarList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<TimeZone> ::= <String>
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
<CalendarSettings> ::=
(description <String>)|
(location <String>)|
(summary <String>)|
(timezone <TimeZone>)
<CalendarSettingsField> ::=
conferenceproperties|
description|
id|
location|
summary|
timezone
<CalendarSettingsFieldList> ::= "<CalendarSettingsField>(,<CalendarSettingsField>)*"
```
## Modify calendar settings
```
gam calendar <CalendarEntity> modify <CalendarSettings>+
```
## Display calendar settings
```
gam calendar <CalendarEntity> show settings
[fields <CalendarSettingsFieldList>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam calendar <CalendarEntity> print settings [todrive <ToDriveAttribute>*]
[fields <CalendarSettingsFieldList>]
[formatjson [quotechar <Character>]]
```
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

251
docs/Chat-Bot.md Normal file
View File

@ -0,0 +1,251 @@
# Chat Bot
- [Notes](#notes)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Set up a Chat Bot](#set-up-a-chat-bot)
- [Display Rooms and Chats to which your Bot belongs](#display-rooms-and-chats-to-which-your-bot-belongs)
- [Display Members of a Room or Chat](#display-members-of-a-room-or-chat)
- [Create a Chat Message](#create-a-chat-message)
- [Update a Chat Message](#update-a-chat-message)
- [Delete a Chat Message](#delete-a-chat-message)
- [Display a Chat Message](#display-a-chat-message)
## Notes
This Wiki page was built directly from Jay Lee's Wiki page; my sincere thanks for his efforts.
## API documentation
* https://developers.google.com/chat/concepts
* https://developers.google.com/chat/reference/rest
* https://support.google.com/chat/answer/7655820
## Definitions
* [Drive File Selection](Drive-File-Selection) for symbols not listed here, such as `<DriveFileIDEntity>`
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
```
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
<UserGoogleDoc> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
<ChatContent> ::=
((text <String>)|
(textfile <FileName> [charset <CharSet>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
<ChatMember> ::= spaces/<String>/members/<String>
<ChatMessage> ::= spaces/<String>/messages/<String>
<ChatSpace> ::= spaces/<String> | space <String> | space spaces/<String>
<ChatThread> ::= spaces/<String>/threads/<String>
<ChatMessageID> ::= client-<String>
<String> must contain only lowercase letters, numbers, and hyphens up to 56 characters in length.
```
## Set up a Chat Bot
Since GAM 6.04.00, GAM is capable of acting as a Chat Bot and sending messages to Chat Rooms or direct messages to users. You first need to configure your Chat Bot.
* Run the command `gam setup chat`; it will point you to a URL to configure your Chat Bot.
* Enter an App name and Description of your choosing.
* For the Avatar URL you can use `https://dummyimage.com/384x256/4d4d4d/0011ff.png&text=+GAM` or a public URL to an image of your own choosing.
* In Functionality, uncheck both "Receive 1:1 messages" and "Join spaces and group conversations"
* In Connection settings, choose "Cloud Pub/Sub" and enter "no-topic" for the topic name. GAM doesn't yet listen to pub/sub so this option is not used.
* In Visibility, uncheck "Make this Chat app available to specific people and groups in Domain Workspace".
* Click Save.
----
## Display Rooms and Chats to which your Bot belongs
Display the spaces to which your Chat Bot can send messages.
A space can be a direct message to a user, a chat group or a chat room.
At first you'll have no spaces listed. Try [finding your bot and chatting it](https://support.google.com/chat/answer/7655820) and then your space will be listed.
### Display information about a specific chat space
```
gam info chatspace space <ChatSpace>
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Display information about all chat spaces
```
gam show chatspaces
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print chatspaces [todrive <ToDriveAttribute>*]
[formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
----
## Display Members of a Room or Chat
### Display information about a specific chat member
```
gam info chatmember member <ChatMember>
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Display information about all chat members in a chat space
```
gam show chatmembers space <ChatSpace>
[showinvited [<Boolean>]] [filter <String>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print chatmembers [todrive <ToDriveAttribute>*] space <ChatSpace>
[showinvited [<Boolean>]] [filter <String>]
[formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
By default, only `JOINED` members are displayed; use `showinvited` to also display `INVITED` members.
Use `filter <String>` to filter memberships by a member's role and membertype.
* To filter by role, set role to ROLE_MEMBER or ROLE_MANAGER.
* To filter by type, set member.type to HUMAN or BOT.
* To filter by both role and type, use the AND operator.
* To filter by either role or type, use the OR operator.
For example, the following queries are valid:
```
role = "ROLE_MANAGER" OR role = "ROLE_MEMBER"
member.type = "HUMAN" AND role = "ROLE_MANAGER"
```
The following queries are invalid:
```
member.type = "HUMAN" AND member.type = "BOT"
role = "ROLE_MANAGER" AND role = "ROLE_MEMBER"
```
## Create a Chat Message
Create a chat message in a space. Messages are limited to 4,096 characters and will be trimmed to that length.
Chat supports [simple formatting](https://developers.google.com/chat/reference/message-formats/basic#using_formatted_text_in_messages) allowing you to bold, underline, italics and strikethrough your text.
```
gam create chatmessage space <ChatSpace>
<ChatContent>
[messageId <ChatMessageID>]
[(thread <ChatThread>)|(threadkey <String>) [replyoption fail|fallbacktonew]]
[returnidonly]
```
Specify the text of the message: `<ChatContent>`
* `text <String>` - The message is `<String>`
* `textfile <FileName> [charset <CharSet>]` - The message is read from a local file
* `gdoc <UserGoogleDoc>` - The message is read from a Google Doc.
* `gcsdoc <StorageBucketObjectName>` - The message is read from a Google Cloud Storage file.
By default, a new message thread is created; use `thread <ChatThread>` or `threadkey <String>` to create the message as a reply to an existing thread.
Use `replyoption` to specify what happens if the specified thread does not exist:
* `fail` - If the thread soes not exiat, a `Not Found` error is generated
* `fallbacktonew` - If the thread does not exist, start a new thread
The first time you reply to a thread you must use `thread <ChatThread>`; if you also specify `threadkey <String>`
then you can use just `threadkey <String>` in subsequent replies.
If you specify `thread` or `threadkey` but not `replyoption`, the default is `fail'.
By default, details about the chat message are displayed.
* `returnidonly` - Display the chat message name only
### Examples
This example creates a new chat message in the given room.
```
gam create chatmessage space spaces/iEMj8AAAAAE text "Hello Chat"
```
This example creates a formatted message and posts it to an existing thread
```
gam create chatmessage space spaces/AAAADi-pvqc thread spaces/AAAADi-pvqc/threads/FMNw-iE9jN4 text "*Bold* _Italics_ ~Strikethrough~"
```
This example reads the MotD.txt file and posts its contents to Chat.
```
gam create chatmessage spaces spaces/AAAADi-pvqc textfile MotD.txt
```
This example reads the Google Doc MotD and posts its contents to Chat.
```
gam create chatmessage spaces spaces/AAAADi-pvqc gdoc announcements@domain.com name "MotD"
```
----
## Update a Chat Message
Updates and rewrites an existing Chat message. Message will show as edited and no notification will be sent to members.
```
gam update chatmessage name <ChatMessage>
<ChatContent>
```
Specify the source of the message:
* `text <String>` - The message is `<String>`
* `textfile <FileName> [charset <CharSet>]` - The message is read from a local file
* `gdoc <UserGoogleDoc>` - The message is read from a Google Doc.
* `gcsdoc <StorageBucketObjectName>` - The message is read from a Google Cloud Storage file.
### Example
This example updates an existing chat message with new text.
```
gam update chatmessage name spaces/AAAADi-pvqc/messages/PKJrx90ooIU.PKJrx90ooIU text "HELLO CHAT?"
```
----
## Delete a Chat Message
Deletes the given Chat message. Members will no longer see the message.
```
gam delete chatmessage name <ChatMessage>
```
### Example
```
gam delete chatmessage name spaces/AAAADi-pvqc/messages/PKJrx90ooIU.PKJrx90ooIU
```
----
## Display a Chat Message
Display the given Chat message.
```
gam info chatmessage name <ChatMessage>
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Example
```
gam info chatmessage name spaces/AAAADi-pvqc/messages/PKJrx90ooIU.PKJrx90ooIU
```
----

90
docs/Chrome-AUE-Counts.md Normal file
View File

@ -0,0 +1,90 @@
# Chrome Auto Update Expiration Counts
- [Chrome Auto Update Expiration Counts](#chrome-auto-update-expiration-counts)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Quoting rules](#quoting-rules)
- [Display Chrome auto update expiration counts](#display-chrome-auto-update-expiration-counts)
## API documentation
* https://developers.google.com/chrome/management/reference/rest/v1/customers.reports/countChromeDevicesReachingAutoExpirationDate
## Notes
To use these features you must add the `Chrome Management API` to your project and authorize
the appropriate scope: `Chrome Management API - read only`.
```
gam update project
gam oauth create
```
## Definitions
```
<Date> ::=
<Year>-<Month>-<Day> |
(+|-)<Number>(d|w|y) |
never|
today
<OrgUnitID> ::= id:<String>
<OrgUnitPath> ::= /|(/<String>)+
<OrgUnitItem> ::= <OrgUnitID>|<OrgUnitPath>
<OrgUnitList> ::= "<OrgUnitItem>(,<OrgUnitItem>)*"
```
## Quoting rules
Items in a list can be separated by commas or spaces; if an item itself contains a comma, a space or a single quote, special quoting must be used.
Typically, you will enclose the entire list in double quotes and quote each item in the list as detailed below.
- Items, separated by commas, without spaces, commas or single quotes in the items themselves
* ```"item,item,item"```
- Items, separated by spaces, without spaces, commas or single quotes in the items themselves
* ```"item item item"```
- Items, separated by commas, with spaces, commas or single quotes in the items themselves
* ```"'it em','it,em',\"it'em\""```
- Items, separated by spaces, with spaces, commas or single quotes in the items themselves
* ```"'it em' 'it,em' \"it'em\""```
## Display Chrome auto update expiration counts
These counts are for provisioned devices.
```
gam show chromeaues
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[minauedate <Date>] [maxauedate <Date>]
[formatjson]
```
Use these options to select Chrome devices; if none are chosen, all Chrome devices in the account are selected.
- `ou <OrgUnitItem>` - Select devices directly in the OU `<OrgUnitItem>`
- `ou_and_children <OrgUnitItem>` - Select devices in the OU `<OrgUnitItem>` and its sub OUs
- `ous <OrgUnitList>` - Select devices directly in the OUs `<OrgUnitList>`
- `ous_and_children <OrgUnitList>` - Select devices in the OUs `<OrgUnitList>` and their sub OUs
- `minauedate <Date>` - Devices that have already expired and devices with auto expiration date equal to or later than the minimum date
- `maxauedate <Date>` - Devices that have already expired and devices with auto expiration date equal to or earlier than the maximum date
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print chromeaues [todrive <ToDriveAttribute>*]
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[minauedate <Date>] [maxauedate <Date>]
[formatjson [quotechar <Character>]]
```
Use these options to select Chrome devices; if none are chosen, all Chrome devices in the account are selected.
- `ou <OrgUnitItem>` - Select devices directly in the OU `<OrgUnitItem>`
- `ou_and_children <OrgUnitItem>` - Select devices in the OU `<OrgUnitItem>` and its sub OUs
- `ous <OrgUnitList>` - Select devices directly in the OUs `<OrgUnitList>`
- `ous_and_children <OrgUnitList>` - Select devices in the OUs `<OrgUnitList>` and their sub OUs
- `minauedate <Date>` - Devices that have already expired and devices with auto expiration date equal to or later than the minimum date
- `maxauedate <Date>` - Devices that have already expired and devices with auto expiration date equal to or earlier than the maximum date
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,424 @@
# Chrome Browser Cloud Management
- [Chrome Browser Cloud Management](#chrome-browser-cloud-management)
- [API documentation](#api-documentation)
- [Query documentation](#query-documentation)
- [Collections of ChromeOS Devices](Collections-of-ChromeOS-Devices)
- [Definitions](#definitions)
- [Manage Chrome browsers](#manage-chrome-browsers)
- [Update Chrome browsers](#update-chrome-browsers)
- [Example: Add a new note to existing notes](#example-add-a-new-note-to-existing-notes)
- [Move Chrome browsers from one OU to another](#move-chrome-browsers-from-one-ou-to-another)
- [Delete Chrome browsers](#delete-chrome-browsers)
- [Display Chrome browsers](#display-chrome-browsers)
- [Examples](#examples)
- [Browser Query Searchable Fields](#browser-query-searchable-fields)
- [Manage Chrome browser enrollment tokens](#manage-chrome-browser-enrollment-tokens)
- [Display Chrome browser enrollment tokens](#display-chrome-browser-enrollment-tokens)
## API documentation
* https://support.google.com/chrome/a/answer/9681204
* https://support.google.com/chrome/a/answer/9949706
## Query documentation
* https://support.google.com/chrome/a/answer/9681204#retrieve_all_chrome_devices_for_an_account
## Definitions
```BNF
<BrowserTokenPermanentID> ::= <String>
<OrgUnitPath> ::= /|(/<String)+
<QueryBrowser> ::= <String> See: https://support.google.com/chrome/a/answer/9681204#retrieve_all_chrome_devices_for_an_account
<QueryBrowserList> ::= "<QueryBrowser>(,<QueryBrowser>)*"
<QueryBrowserToken> ::= <String> https://support.google.com/chrome/a/answer/9949706, scroll down to Filter Query Language
<QueryBrowserTokenList> ::= "<QueryBrowserToken>(,<QueryBrowserToken>)*"
<DeviceID> ::= <String>
<DeviceIDList> ::= "<DeviceID>(,<DeviceID>)*"
<BrowserEntity> ::=
<DeviceIDList> |
(query:<QueryBrowser>)|(query:orgunitpath:<OrgUnitPath>)|(query <QueryBrowser>) |
(browserou <OrgUnitItem>) | (browserous <OrgUnitList>) |
<FileSelector> | <CSVFileSelector>
<BrowserAttribute> ::=
(annotatedassetid|asset|assetid <String>)|
(annotatedlocation|location <String>)|
(annotatednotes|notes <String>)|(updatenotes <String>)|
(annotateduser|user <String>
<BrowserFieldName> ::=
annotatedassetid|asset|assetid|
annotatedlocation|location|
annotatednotes|notes|
annotateduser|user|
browsers|
browserversions|
deviceid|
deviceidentifiershistory|
extensioncount|
lastactivitytime|
lastdeviceuser|
lastdeviceusers|
lastpolicyfetchtime|
lastregistrationtime|
laststatusreporttime|
machinename|
machinepolicies|
orgunitpath|org|orgunit|ou|
osarchitecture|
osplatform|
osplatformversion|
osversion|
policycount|
safebrowsingclickthroughcount|
serialnumber|
virtualdeviceid
<BrowserFieldNameList> ::= "<BrowseFieldName>(,<BrowserFieldName>)*"
<BrowserOrderByFieldName> ::=
annotatedassetid|assetassetid|
annotatedlocation|location|
annotatednotes|notes|
annotateduser|user|
browserversionchannel|
browserversionsortable|
deviceid|id|
enrollmentdate|
extensioncount|
lastactivity|
lastsignedinuser|
lastsync|
machinename|
orgunit|ou|org|
osversion|
osversionsortable|
platformmajorversion|
policycount
```
```
<BrowserTokenFieldName> ::=
createtime|
creatorid|
customerid|
expiretime|
org|
orgunit|
orgunitpath|
revoketime|
revokerid|
state|
token|
tokenpermanentid
<BrowserTokenFieldNameList> ::= "<BrowseTokenFieldName>(,<BrowserTokenFieldName>)*"
```
## Manage Chrome browsers
## Update Chrome browsers
There are four attributes that can be set for a browser.
```
gam update browser <BrowserDeviceEntity> <BrowserAttibute>+
```
### Example: Add a new note to existing notes
If you specify the `updatenotes <String>` option and it contains the string `#notes#`, the existing notes value will replace `#notes#`.
This requires an additional API to get the existing value.
If you have a CSV file, UpdateBrowsers.csv with two columns: deviceId,notes
this command will add a new line of notes to the front of the existing notes:
```
gam csv UpdateBrowsers.csv gam update browser ~deviceId updatenotes "~~notes~~\n#notes#"
```
## Move Chrome browsers from one OU to another
```
gam move browsers ou|org|orgunit <OrgUnitPath>
((ids <DeviceIDList>) |
(queries <QueryBrowserList> [querytime.* <Time>]) |
(browserou <OrgUnitItem>) | (browserous <OrgUnitList>) |
<FileSelector> | <CSVFileSelector>)
[batchsize <Integer>]
```
Batches of devices are processed to minimize the number of API calls; `batch_size` controls the number of deviceIds handled in each batch
`batch_size` defaults to the value from `gam.cfg`, its maximum value is 600.
Google performs error checking of the browser deviceIDs, if any deviceID in a batch is invalid, none of the browsers in the batch are moved.
### Example: Move Chrome browsers from one OU to another
```
gam move browsers ou /Students/2021 browserou /Students/2020
```
## Delete Chrome browsers
Deletes a browser; the browser will be removed from Google's admin console and no longer sync policy or reporting. However, existing policies will still be applied until the device registration and dm tokens are removed.
```
gam delete browser <BrowserDeviceEntity>
```
## Display Chrome browsers
```
gam info browser <BrowserEntity>
[basic|full|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
[formatjson]
```
Select the fields to be displayed:
* `annotated` - Display these fields: deviceId,annotatedAssetId,annotatedLocation,annotatedNotes,annotatedUser
* `basic` - Display all fields except: browsers, lastDeviceUsers, lastStatusReportTime, machinePolicies; this is the default
* `allfields/full` - Display all fields
* `<BrowserFieldName>* [fields <BrowserFieldNameList>]` - Display a selected list of fields
By default, Gam displays the information as an indented list of keys and values:
- `formatjson` - Display the fields in JSON format.
```
gam show browsers
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser>)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
[querytime.* <Time>]
[orderby <BrowserOrderByFieldName> [ascending|descending]]
[basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
[formatjson]
```
Use these options to select Chrome browsers; if none are chosen, all Chrome browsers in the account are selected:
* `ou|org|orgunit|browserou <OrgUnitPath>` - Limit browsers to those in the specified OU; this option can be used in conjunction with query
* `(query <QueryBrowser>)|(queries <QueryBrowserList>)` - Limit browsers to those that match a query
* `select <BrowserEntity>` - Select a specific set of browsers to display
Select the fields to be displayed:
* `annotated` - Display these fields: deviceId,annotatedAssetId,annotatedLocation,annotatedNotes,annotatedUser
* `basic` - Display all fields except: browsers, lastDeviceUsers, lastStatusReportTime, machinePloicies; this is the default
* `allfields/full` - Display all fields
* `<BrowserFieldName>* [fields <BrowserFieldNameList>]` - Displaya selected list of fields
By default, Gam displays the information as an indented list of keys and values:
- `formatjson` - Display the fields in JSON format.
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryBrowser>` and `queries <QueryBrowserList>` options.
The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries.
The characters following `querytime` can be any combination of lowercase letters and numbers.
```
gam print browsers [todrive <ToDriveAttribute>*]
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser>)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
[querytime.* <Time>]
[orderby <BrowserOrderByFieldName> [ascending|descending]]
[basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
[sortheaders] [formatjson [quotechar <Character>]]
```
Use these options to select Chrome browsers; if none are chosen, all Chrome browsers in the account are selected:
* `ou|org|orgunit|browserou <OrgUnitPath>` - Limit browsers to those in the specified OU; this option can be used in conjunction with query
* `(query <QueryBrowser>)|(queries <QueryBrowserList>)` - Limit browsers to those that match a query
* `select <BrowserEntity>` - Select a specific set of browsers to display
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryBrowser>` and `queries <QueryBrowserList>` options.
The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries.
The characters following `querytime` can be any combination of lowercase letters and numbers.
For example, query for Chrome browsers last synced more than a year ago:
```
querytime1year -1y query "sync:..#querytime1year#"
```
The first column will always be deviceId; the remaining field names will be sorted if `allfields`, `basic`, `full` or `sortheders` is specified;
otherwise, the remaining field names will appear in the order specified.
Select the fields to be displayed:
* `annotated` - Display these fields: deviceId,annotatedAssetId,annotatedLocation,annotatedNotes,annotatedUser
* `basic` - Display all fields except: browsers, lastDeviceUsers, lastStatusReportTime, machinePloicies; this is the default
* `allfields/full` - Display all fields
* `<BrowserFieldName>* [fields <BrowserFieldNameList>]` - Displaya selected list of fields
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format:
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
### Examples
Print information about Chrome browsers synced more than 30 days ago:
```
gam print browsers query "sync:..#querytime1#" querytime1 -30d
```
Print information about Chrome browsers synced in the last 30 days:
```
gam print browsers query "sync:#querytime1#.." querytime1 -30d
```
Print information about Chrome browsers synced between 45 days ago and 30 days ago:
```
gam print browsers query "sync:#querytime1#..#querytime2#" querytime1 -45d querytime2 -30d
```
## Browser Query Searchable Fields
These are the fields that can be used in a query:
```
Field Description
arch The CPU architecture for the Chrome browser device. (e.g. x86_64)
asset_id The annotated asset ID for the Chrome browser device.
browser_version A reported Chrome browser installed on the Chrome browser device (e.g. 73)
enrollment_token The enrollment token used to register the Chrome browser device.
last_activity The last time the Chrome browser device has shown activity (policy fetch or reporting).
location The annotated location for the Chrome browser device.
machine_name The machine name for the Chrome browser device.
machine_user The last reported user of the Chrome browser device.
note The annotated note for the Chrome browser device.
num_extensions The number of extensions reported by the Chrome browser device.
num_policies The number of policies reported by the Chrome browser device.
os The combine OS platform and major OS version for the Chrome browser device (e.g. "Windows 10")
os_platform The OS platform for the Chrome browser device. (e.g. Windows)
os_version The OS version for the chrome browser device. (e.g. 10.0.16299.904)
register The registration time for the Chrome browser device.
report The last report time for the Chrome browser device
sync The last policy sync time for the Chrome browser device.
user The annotated user for the Chrome browser device.
```
For fields that accept time (register, report, sync, last_activity) the time format is YYYY-MM-DDThh:mm:ss (e.g. 2020-01-01T12:00:00). You may also specify open or closed ranges for the time:
```
datetime exactly on the given date or time, e.g., 2011-03-23 2011-04-26T14:23:05
datetime..datetime within (inclusive) the given interval of date or time, e.g., 2011-03-23..2011-04-26
datetime.. on or after the given date or time; e.g., 2011-04-26T14:23:05..
..datetime on or before the given date or time; e.g., ..2011-04-26T14:23:05
```
To search within a specific field only (for example, to search for a specific user), you can enter an operator followed by an argument -- for example, `user:jsmith`. You can use single words or quoted lists of words as an argument when running an operator query.
To run an operator query, follow these guidelines for each field:
### User
Enter user: as the operator. For example, to match the name Joe, but not Joey, enter the following:
`gam print browsers query "user:joe"`
To match the name Tom Sawyer or A. Tom Sawyer, but not Tom A. Sawyer, enter with quotation marks:
`gam print browsers query "user:'tom sawyer'"`
### Location
Enter location: as the operator. For example, to match Seattle, enter the following:
`gam print browsers query "location:seattle"`
Notes
Enter note: as the operator. For example, to match loaned from John, enter the following with quotation marks:
`gam print browsers query "note:'loaned from john'"`
### Register
This field is not displayed on the Chrome OS settings page. However, you can search for devices that were registered on a given date, or within a given time range.
Enter register: as the operator, and enter a date and time (or time range) as the argument. For example, to search for all devices registered on April 15, 2020, enter the following:
`gam print browsers query "register:2020-04-15"`
For additional examples using dates, times, and ranges, see "Format for date searches" below.
### Last Sync
Enter sync: as the operator and a date or time range as the argument. For example, to search for all devices that were last synced with policy settings on April 15, 2020, enter the following:
`gam print browsers query "sync:2020-04-15"`
For additional examples using dates, times, and ranges, see "Format for date searches" below.
### Format for date searches
* `YYYY-MM-DD` - A single date
* `YYYY-MM-DD..YYYY-MM-DD` - A date range
* `..YYYY-MM-DD` - All dates on or before a date
* `YYYY-MM-DD..` - All dates on or after a date
### Asset ID
Enter asset_id: as the operator. For example, to match the partial Asset ID 1234, enter the following:
`gam print browsers query "asset_id:1234"`
## Manage Chrome browser enrollment tokens
Create a browser enrollment token. The Google API that supports this call always returns an error.
```
gam create browsertoken
[ou|org|orgunit|browserou <OrgUnitPath>] [expire|expires <Time>]
[formatjson]
```
By default, the enrollment token is created for the root OU; use `ou|org|orgunit|browserou <OrgUnitPath>`
to create the token for a specific OU.
By default, Gam displays the created token as an indented list of keys and values:
- `formatjson` - Display the token in JSON format.
Revoke a browser enrollment token.
An enrollment token is revoked by referencing its `tokenPermanentId` which can be obtained
from `gam show|print browsertokens`.
```
gam revoke browsertoken <BrowserTokenPermanentID>
```
## Display Chrome browser enrollment tokens
```
gam show browsertokens
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken)|(queries <QueryBrowserTokenList>)))
[querytime.* <Time>]
[orderby <BrowserTokenFieldName> [ascending|descending]]
[allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
[formatjson]
```
Use these options to select Chrome browsers; if none are chosen, all Chrome browsers in the account are selected:
* `ou|org|orgunit|browserou <OrgUnitPath>` - Limit browsers to those in the specified OU; this option can be used in conjunction with query
* `(query <QueryBrowserToken>)|(queries <QueryBrowserTokenList>)` - Limit browsers to those that match a query
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryBrowserToken>` and `queries <QueryBrowserTokenList>` options.
The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries.
The characters following `querytime` can be any combination of lowercase letters and numbers.
Select the fields to be displayed:
* `allfields` - Display all fields; this is the default
* `<BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]` - Displaya selected list of fields
By default, Gam displays the information as an indented list of keys and values:
- `formatjson` - Display the fields in JSON format.
```
gam print browsertokens [todrive <ToDriveAttribute>*]
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken)|(queries <QueryBrowserTokenList>)))
[querytime.* <Time>]
[orderby <BrowserTokenFieldName> [ascending|descending]]
[allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
[sortheaders] [formatjson [quotechar <Character>]]
```
Use these options to select Chrome browsers; if none are chosen, all Chrome browsers in the account are selected:
* `ou|org|orgunit|browserou <OrgUnitPath>` - Limit browsers to those in the specified OU; this option can be used in conjunction with query
* `(query <QueryBrowserToken>)|(queries <QueryBrowserTokenList>)` - Limit browser s to those that match a query
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryBrowserToken>` and `queries <QueryBrowserTokenList>` options.
The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries.
The characters following `querytime` can be any combination of lowercase letters and numbers.
The first column will always be deviceId; the remaining field names will be sorted if `allfields`, `basic`, `full` or `sortheders` is specified;
otherwise, the remaining field names will appear in the order specified.
Select the fields to be displayed:
* `allfields` - Display all fields; this is the default
* `<BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]` - Displaya selected list of fields
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format:
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,132 @@
# Chrome Installed Apps Counts
- [Chrome Policies](#chrome-policies)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Quoting rules](#quoting-rules)
- [Display Chrome installed apps counts](#display-chrome-installed-apps-counts)
- [Display Chrome devices with a specific installed application](#display-chrome-devices-with-a-specific-installed-application)
## API documentation
* https://developers.google.com/chrome/management/reference/rest/v1/customers.reports/countInstalledApps
* https://developers.google.com/chrome/management/reference/rest/v1/customers.reports/findInstalledAppDevices
## Notes
To use these features you must add the `Chrome Management API` to your project and authorize
the appropriate scope: `Chrome Management API - read only`.
```
gam update project
gam oauth create
```
## Definitions
```
<AppID> ::= <String>
<AppType> ::= extension|app|theme|hostedapp|androidapp
<Date> ::=
<Year>-<Month>-<Day> |
(+|-)<Number>(d|w|y) |
never|
today
<OrgUnitID> ::= id:<String>
<OrgUnitPath> ::= /|(/<String>)+
<OrgUnitItem> ::= <OrgUnitID>|<OrgUnitPath>
```
## Quoting rules
Items in a list can be separated by commas or spaces; if an item itself contains a comma, a space or a single quote, special quoting must be used.
Typically, you will enclose the entire list in double quotes and quote each item in the list as detailed below.
- Items, separated by commas, without spaces, commas or single quotes in the items themselves
* ```"item,item,item"```
- Items, separated by spaces, without spaces, commas or single quotes in the items themselves
* ```"item item item"```
- Items, separated by commas, with spaces, commas or single quotes in the items themselves
* ```"'it em','it,em',\"it'em\""```
- Items, separated by spaces, with spaces, commas or single quotes in the items themselves
* ```"'it em' 'it,em' \"it'em\""```
## Display Chrome installed apps counts
```
gam show chromeapps
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[filter <String>]
[orderby appname|apptype|installtype|numberofpermissions|totalinstallcount]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print chromeapps [todrive <ToDriveAttribute>*]
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[filter <String>]
[orderby appname|apptype|installtype|numberofpermissions|totalinstallcount]
[formatjson [quotechar <Character>]] [delimiter <Character>]
```
Use these options to select Chrome devices; if none are chosen, all Chrome devices in the account are selected.
- `ou <OrgUnitItem>` - Select devices directly in the OU `<OrgUnitItem>`
- `ou_and_children <OrgUnitItem>` - Select devices in the OU `<OrgUnitItem>` and its sub OUs
- `ous <OrgUnitList>` - Select devices directly in the OUs `<OrgUnitList>`
- `ous_and_children <OrgUnitList>` - Select devices in the OUs `<OrgUnitList>` and their sub OUs
- `filter <String>` - The minimum `last_active_date` for the devices
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Chrome devices with a specific installed application
```
gam show chromeappdevices
appid <AppID> apptype <AppType>
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[start <Date>] [end <Date>]
[orderby deviceid|machine]
[formatjson]
```
Use these options to select Chrome devices; if none are chosen, all Chrome devices in the account are selected.
- `ou <OrgUnitItem>` - Select devices directly in the OU `<OrgUnitItem>`
- `ou_and_children <OrgUnitItem>` - Select devices in the OU `<OrgUnitItem>` and its sub OUs
- `ous <OrgUnitList>` - Select devices directly in the OUs `<OrgUnitList>`
- `ous_and_children <OrgUnitList>` - Select devices in the OUs `<OrgUnitList>` and their sub OUs
- `start <Date>` - The minimum `last_active_date` for the devices
- `end <Date>` - The maximum `last_active_date` for the devices
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print chromeappdevices [todrive <ToDriveAttribute>*]
appid <AppID> apptype <AppType)
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[start <Date>] [end <Date>]
[orderby deviceid|machine]
[formatjson [quotechar <Character>]]
```
Use these options to select Chrome devices; if none are chosen, all Chrome devices in the account are selected.
- `ou <OrgUnitItem>` - Select devices directly in the OU `<OrgUnitItem>`
- `ou_and_children <OrgUnitItem>` - Select devices in the OU `<OrgUnitItem>` and its sub OUs
- `ous <OrgUnitList>` - Select devices directly in the OUs `<OrgUnitList>`
- `ous_and_children <OrgUnitList>` - Select devices in the OUs `<OrgUnitList>` and their sub OUs
- `start <Date>` - The minimum `last_active_date` for the devices
- `end <Date>` - The maximum `last_active_date` for the devices
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,78 @@
# Chrome Device Needs Attention Counts
- [Chrome Device Needs Attention Counts](#chrome-device-needs-attention-counts)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Quoting rules](#quoting-rules)
- [Display Chrome Device needs attention counts](#display-chrome-device-needs-attention-counts)
## API documentation
* https://developers.google.com/chrome/management/reference/rest/v1/customers.reports/countChromeDevicesThatNeedAttention
## Notes
To use these features you must add the `Chrome Management API` to your project and authorize
the appropriate scope: `Chrome Management API - read only`.
```
gam update project
gam oauth create
```
## Definitions
```
<OrgUnitID> ::= id:<String>
<OrgUnitPath> ::= /|(/<String>)+
<OrgUnitItem> ::= <OrgUnitID>|<OrgUnitPath>
<OrgUnitList> ::= "<OrgUnitItem>(,<OrgUnitItem>)*"
```
## Quoting rules
Items in a list can be separated by commas or spaces; if an item itself contains a comma, a space or a single quote, special quoting must be used.
Typically, you will enclose the entire list in double quotes and quote each item in the list as detailed below.
- Items, separated by commas, without spaces, commas or single quotes in the items themselves
* ```"item,item,item"```
- Items, separated by spaces, without spaces, commas or single quotes in the items themselves
* ```"item item item"```
- Items, separated by commas, with spaces, commas or single quotes in the items themselves
* ```"'it em','it,em',\"it'em\""```
- Items, separated by spaces, with spaces, commas or single quotes in the items themselves
* ```"'it em' 'it,em' \"it'em\""```
## Display Chrome device needs attention counts
```
gam show chromeneedsattn
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[formatjson]
```
Use these options to select Chrome devices; if none are chosen, all Chrome devices in the account are selected.
- `ou <OrgUnitItem>` - Select devices directly in the OU `<OrgUnitItem>`
- `ou_and_children <OrgUnitItem>` - Select devices in the OU `<OrgUnitItem>` and its sub OUs
- `ous <OrgUnitList>` - Select devices directly in the OUs `<OrgUnitList>`
- `ous_and_children <OrgUnitList>` - Select devices in the OUs `<OrgUnitList>` and their sub OUs
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print chromeneedsattn [todrive <ToDriveAttribute>*]
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[formatjson [quotechar <Character>]]
```
Use these options to select Chrome devices; if none are chosen, all Chrome devices in the account are selected.
- `ou <OrgUnitItem>` - Select devices directly in the OU `<OrgUnitItem>`
- `ou_and_children <OrgUnitItem>` - Select devices in the OU `<OrgUnitItem>` and its sub OUs
- `ous <OrgUnitList>` - Select devices directly in the OUs `<OrgUnitList>`
- `ous_and_children <OrgUnitList>` - Select devices in the OUs `<OrgUnitList>` and their sub OUs
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

5429
docs/Chrome-Policies.md Normal file

File diff suppressed because it is too large Load Diff

182
docs/Chrome-Printers.md Normal file
View File

@ -0,0 +1,182 @@
# Chrome Printers
- [API documentation](#api-documentation)
- [Notes](#notes)
- [Definitions](#definitions)
- [Quoting rules](#quoting-rules)
- [Manage printers](#manage-printers)
- [Display printers](#display-printers)
- [Display printer models](#display-printer-models)
- [Bulk printer updates](#bulk-printer-updates)
## API documentation
* https://developers.google.com/admin-sdk/chrome-printer/reference/rest
## Notes
To use these features you must authorize the appropriate scope: `Directory API - Printers (supports readonly)`.
As of 2021-10-05, `gam update printer` does not work due to some API problem. To update a printer,
you'll have to delete it and create it.
```
gam oauth create
```
## Definitions
```
<OrgUnitID> ::= id:<String>
<OrgUnitPath> ::= /|(/<String)+
<OrgUnitItem> ::= <OrgUnitID>|<OrgUnitPath>
<OrgUnitList> ::= "<OrgUnitItem>(,<OrgUnitItem>)*"
<PrinterID> ::= <String>
<PrinterIDList> ::= "<PrinterID>(,<PrinterID>)*"
<PrinterAttribute> ::=
(description <String>)|
(displayname <String>)|
(json [charset <Charset>] <JSONData>)|(json file <FileName> [charset <Charset>])|
(makeandmodel <String>)|
(ou|org|orgunit <OrgUnitItem>)|
(uri <String>)|
(driverless [<Boolean>])
<PrinterFieldName> ::=
auxiliarymessages|
createtime|
description|
displayname|
id|
makeandmodel|
name|
ou|org|orgunit|orgunitid|
uri|
usedriverlessconfig|
<PrinterFieldNameList> ::= "<PrinterFieldName>(,<PrinterFieldName>)*"
```
```
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
<UserGoogleDoc> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
<FileSelector> ::=
file ((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>]
<CSVFileSelector> ::=
csvfile ((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>]
```
## Quoting rules
Items in a list can be separated by commas or spaces; if an item itself contains a comma, a space or a single quote, special quoting must be used.
Typically, you will enclose the entire list in double quotes and quote each item in the list as detailed below.
- Items, separated by commas, without spaces, commas or single quotes in the items themselves
* ```"item,item,item"```
- Items, separated by spaces, without spaces, commas or single quotes in the items themselves
* ```"item item item"```
- Items, separated by commas, with spaces, commas or single quotes in the items themselves
* ```"'it em','it,em',\"it'em\""```
- Items, separated by spaces, with spaces, commas or single quotes in the items themselves
* ```"'it em' 'it,em' \"it'em\""```
## Manage printers
When creating a printer you must specify: `displayname`, `ou`, `uri` and `makeandmodel` or `driverless`.
```
gam create printer <PrinterAttribute>+ [nodetails]
gam update printer <PrinterID> <PrinterAttribute>+ [nodetails]
gam delete printer
<PrinterIDList>|
<FileSelector>|
<CSVFileSelector>
```
By default, when a printer is created/updated, GAM outputs details of the printer; the `nodetails` option suppresses this output.
## Display printers
Display information about a single printer.
```
gam info printer <PrinterID>
[fields <PrinterFieldNameList>] [formatjson]
```
Display information about multiple printers.
```
gam show printers
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[filter <String>] [showinherited [<Boolean>]]
[fields <PrinterFieldNameList>] [formatjson]
gam print printers [todrive <ToDriveAttribute>*]
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[filter <String>] [showinherited [<Boolean>]]
[fields <PrinterFieldNameList>] [[formatjson [quotechar <Character>]]
```
Use these options to select printers; if none are chosen, all printers in the account are selected.
If only `filter <String>` is specified, the query applies to all printers. If one of the `ou` options
is also specified, the filter applies to printers within the OUs. The `filter <String>` is applied
to the printer `displayName` and `description` fields.
- `filter <String>` - Filter on printer `description` and `displayName'.
- `ou <OrgUnitItem>` - Select printers directly in the OU `<OrgUnitItem>`
- `ou_and_children <OrgUnitItem>` - Select printers in the OU `<OrgUnitItem>` and its sub OUs
- `ous <OrgUnitList>` - Select printers directly in the OUs `<OrgUnitList>`
- `ous_and_children <OrgUnitList>` - Select printers in the OUs `<OrgUnitList>` and their sub OUs
By default, only printers defined in the specified OUs are displayed. Use the `showinherited` option
to display inherited printers in the OUs; three additional fields are displayed.
- `inherited` - False if the printer is defined in the OU, True if the printer is inherited by the OU
- `parentOrgUnitId` - Blank if the printer is defined in the OU, the ID of the defining OU if the printer is inherited by the OU
- `parentOrgUnitPath` - Blank if the printer is defined in the OU, the path of the defining OU if the printer is inherited by the OU
## Display printer models
```
gam show printermodels
[filter <String>]
[formatjson]
gam print printermodels [todrive <ToDriveAttribute>*]
[filter <String>]
[[formatjson [quotechar <Character>]]
```
If `filter <String>` isn't specified, all printer models are displayed.
You can filter by manufacturer: `filter "manufacturer:XYX"`
## Bulk printer updates
Suppose you have replaced one model of printer with another and have to update the make and model.
As of 2021-10-05, you'll have to delete and create the updated printer as `gam update printer` does not work due to some API problem.
Get the list of printers.
```
gam redirect csv ./StudentPrinters.csv print printers formatjson quotechar "'" ou /Students
```
Edit StudentPrinters.csv and add a new column labelled `action`; it does not matter where you place the column.
In each row's JSON data there will be an entry like this: `"makeAndModel": "vendor1 xy abcd"`; replace `vendor1 xy abcd`
with `vendor2 ab wxyz` for the rows of interest and put an `x` in the `action` column.
Delete the marked printers.
```
gam config csv_input_row_filter "action:regex:x" redirect stdout ./DeletePrinters.txt multiprocess redirect stderr stdout csv ./StudentPrinters.csv quotechar "'" gam delete printer "~id"
```
Recreate the marked printers with the updated `makeAndModel`.
```
gam config csv_input_row_filter "action:regex:x" redirect stdout ./CreatetePrinters.txt multiprocess redirect stderr stdout csv ./StudentPrinters.csv quotechar "'" gam create printer json "~JSON"
```

View File

@ -0,0 +1,96 @@
# Chrome Version Counts
- [Chrome Version Counts](#chrome-version-counts)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Quoting rules](#quoting-rules)
- [Display Chrome version counts](#display-chrome-version-counts)
## API documentation
* https://developers.google.com/chrome/management/reference/rest/v1/customers.reports/countChromeVersions
## Notes
To use these features you must add the `Chrome Management API` to your project and authorize
the appropriate scope: `Chrome Management API - read only`.
```
gam update project
gam oauth create
```
## Definitions
```
<Date> ::=
<Year>-<Month>-<Day> |
(+|-)<Number>(d|w|y) |
never|
today
<OrgUnitID> ::= id:<String>
<OrgUnitPath> ::= /|(/<String>)+
<OrgUnitItem> ::= <OrgUnitID>|<OrgUnitPath>
<OrgUnitList> ::= "<OrgUnitItem>(,<OrgUnitItem>)*"
```
## Quoting rules
Items in a list can be separated by commas or spaces; if an item itself contains a comma, a space or a single quote, special quoting must be used.
Typically, you will enclose the entire list in double quotes and quote each item in the list as detailed below.
- Items, separated by commas, without spaces, commas or single quotes in the items themselves
* ```"item,item,item"```
- Items, separated by spaces, without spaces, commas or single quotes in the items themselves
* ```"item item item"```
- Items, separated by commas, with spaces, commas or single quotes in the items themselves
* ```"'it em','it,em',\"it'em\""```
- Items, separated by spaces, with spaces, commas or single quotes in the items themselves
* ```"'it em' 'it,em' \"it'em\""```
## Display Chrome version counts
These counts are for provisioned devices.
```
gam show chromeversions
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[start <Date>] [end <Date>]
[recentfirst [<Boolean>]]
[formatjson]
```
Use these options to select Chrome devices; if none are chosen, all Chrome devices in the account are selected.
- `ou <OrgUnitItem>` - Select devices directly in the OU `<OrgUnitItem>`
- `ou_and_children <OrgUnitItem>` - Select devices in the OU `<OrgUnitItem>` and its sub OUs
- `ous <OrgUnitList>` - Select devices directly in the OUs `<OrgUnitList>`
- `ous_and_children <OrgUnitList>` - Select devices in the OUs `<OrgUnitList>` and their sub OUs
- `start <Date>` - The minimum `last_active_date` for the devices
- `end <Date>` - The maximum `last_active_date` for the devices
By default, the versions are displayed from oldest to most recent; use the `recentfirst` option to reverse this order.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print chromeversions [todrive <ToDriveAttribute>*]
[(ou <OrgUnitItem>)|(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|(ous_and_children <OrgUnitList>)]
[start <Date>] [end <Date>]
[recentfirst [<Boolean>]]
[formatjson [quotechar <Character>]]
```
Use these options to select Chrome devices; if none are chosen, all Chrome devices in the account are selected.
- `ou <OrgUnitItem>` - Select devices directly in the OU `<OrgUnitItem>`
- `ou_and_children <OrgUnitItem>` - Select devices in the OU `<OrgUnitItem>` and its sub OUs
- `ous <OrgUnitList>` - Select devices directly in the OUs `<OrgUnitList>`
- `ous_and_children <OrgUnitList>` - Select devices in the OUs `<OrgUnitList>` and their sub OUs
- `start <Date>` - The minimum `last_active_date` for the devices
- `end <Date>` - The maximum `last_active_date` for the devices
By default, the versions are displayed from oldest to most recent; use the `recentfirst` option to reverse this order.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,166 @@
# Chrome Version History
- [Chrome Version History](#chrome-version-history)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Display Chrome platforms](#display-chrome-platforms)
- [Display Chrome channels](#display-chrome-channels)
- [Display Chrome versions](#display-chrome-versions)
- [Display Chrome releases](#display-chrome-releases)
## API documentation
* https://developer.chrome.com/docs/versionhistory/guide/
* https://developer.chrome.com/docs/versionhistory/reference/#filter
* https://developer.chrome.com/docs/versionhistory/reference/#order
## Definitions
```
<ChromePlatfornType> ::=
all|
android|
ios|
lacros|
linux|
mac|
macarm64|
sebview|
win|
win64
<ChromeChannelType> ::=
beta|
canary|
canaryasan|
dev|
stable
<ChromeVersionsOrderByFieldName> ::=
channel|
name|
platform|
version|
<ChromeReleasesOrderByFieldName> ::=
channel|
endtime|
fraction|
name|
platform|
starttime|
version
```
## Display Chrome platforms
```
gam show chromehistory platforms
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print chromehistory platforms [todrive <ToDriveAttribute>*]
[formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Chrome channels
```
gam show chromehistory channels
[platform <ChromePlatformType>]
[formatjson]
```
By default, channels for all platforms are displayed; use `platform <ChromePlatformType>]`
to select a specific platform.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print chromehistory channels [todrive <ToDriveAttribute>*]
[platform <ChromePlatformType>]
[formatjson [quotechar <Character>]]
```
By default, channels for all platforms are displayed; use `platform <ChromePlatformType>]`
to select a specific platform.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Chrome versions
```
gam show chromehistory versions
[platform <ChromePlatformType>] [channel <ChromeChannelType>]
[filter <String>]
(orderby <ChromeVersionsOrderByFieldName> [ascending|descending])*
[formatjson]
```
By default, versions for all platforms and channels are displayed; use `platform <ChromePlatformType>]`
and/or `channel <ChromeChannelType>` to select a specific platform and/or channel.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print chromehistory versions [todrive <ToDriveAttribute>*]
[platform <ChromePlatformType>] [channel <ChromeChannelType>]
[filter <String>]
(orderby <ChromeVersionsOrderByFieldName> [ascending|descending])*
[formatjson [quotechar <Character>]]
```
By default, versions for all platforms and channels are displayed; use `platform <ChromePlatformType>]`
and/or `channel <ChromeChannelType>` to select a specific platform and/or channel.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Chrome releases
```
gam show chromehistory releases
[platform <ChromePlatformType>] [channel <ChromeChannelType>] [version <String>]
[filter <String>]
(orderby <ChromeReleasessOrderByFieldName> [ascending|descending])*
[formatjson]
```
By default, versions for all platforms, channels and versions are displayed; use `platform <ChromePlatformType>]`
and/or `channel <ChromeChannelType>` and/or `version <String>` to select a specific platform and/or channel and/or version.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print chromehistory releases [todrive <ToDriveAttribute>*]
[platform <ChromePlatformType>] [channel <ChromeChannelType>] [version <String>]
[filter <String>]
(orderby <ChromeReleasessOrderByFieldName> [ascending|descending])*
[formatjson [quotechar <Character>]]
```
By default, versions for all platforms, channels and versions are displayed; use `platform <ChromePlatformType>]`
and/or `channel <ChromeChannelType>` and/or `version <String>` to select a specific platform and/or channel and/or version.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

961
docs/ChromeOS-Devices.md Normal file
View File

@ -0,0 +1,961 @@
# ChromeOS Devices
- [ChromeOS Devices](#chromeos-devices)
- [API documentation](#api-documentation)
- [Query documentation](#query-documentation)
- [Notes](#notes)
- [Collections of ChromeOS Devices](Collections-of-ChromeOS-Devices)
- [Definitions](#definitions)
- [CrOS Query Searchable Fields](#cros-query-searchable-fields)
- [ChromeOS device update OU error handling](#chromeos-device-update-ou-error-handling)
- [Manage ChromeOS devices](#manage-chromeos-devices)
- [Example: Move CrOS devices from one OU to another](#example-move-cros-devices-from-one-ou-to-another)
- [Example: Add a new note to existing notes](#example-add-a-new-note-to-existing-notes)
- [Add ChromeOS devices to an organizational unit](#add-chromeos-devices-to-an-organizational-unit)
- [Example: Add ChromeOS devices to a single OU](#example-add-chromeos-devices-to-a-single-ou)
- [Example: Add ChromeOS devices to multiple OUs](#example-add-chromeos-devices-to-multiple-ous)
- [Action ChromeOS devices](#action-chromeos-devices)
- [Send remote commands to ChromeOS devices](#send-remote-commands-to-chromeos-devices)
- [Action Examples](#action-examples)
- [ChromeOS device lists](#chromeos-device-lists)
- [Display information about ChromeOS devices](#display-information-about-chromeos-devices)
- [Print ChromeOS devices](#print-chromeos-devices)
- [Print no header row and deviceId for specified CrOS devices](#print-no-header-row-and-deviceid-for-specified-cros-devices)
- [Print a header row and fields for selected CrOS devices](#print-a-header-row-and-fields-for-selected-cros-devices)
- [Print a header row and fields for specified CrOS devices](#print-a-header-row-and-fields-for-specified-cros-devices)
- [Display Examples](#display-examples)
- [Print ChromeOS device activity](#print-chromeos-device-activity)
- [Print a header row and activity for selected CrOS devices](#print-a-header-row-and-activity-for-selected-cros-devices)
- [Print a header row and activity for specified CrOS devices](#print-a-header-row-and-activity-for-specified-cros-devices)
- [Download a ChromeOS device file](#download-a-chromeos-device-file)
- [Download Examples](#download-examples)
- [Display ChromeOS telemetry data](#display-chromeos-telemetry-data)
- [Check ChromeOS device serial number validity](#check-chromeos-device-serial-number-validity)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/chromeosdevices
* https://developers.google.com/chrome/management/reference/rest/v1/customers.telemetry.devices
## Query documentation
* https://developers.google.com/admin-sdk/directory/v1/list-query-operators
* https://support.google.com/chrome/a/answer/1698333
Undocumented API query terms.
```
<QueryDate> ::=
YYYY-MM-DD # Specific date
..YYYY-MM-DD # Before a date
YYYY-MM-DD.. # After a date
YYYY-MM-DD..YYYY-MM-DD # Range of dates
aue:<QueryDate>
compliance:compliant|pending_update|not_compliant
last_user_activity:<QueryDate>
policy_status:true|false
public_model_name:<String>
update_status:default_os_up_to_date|pending_update|os_image_download_not_started|os_image_download_in_progress|os_update_need_reboot
```
## Notes
The `crostelemetry` commands were added in 6.13.04; to use them you must authorize an additional scope:
* `Chrome Management API - Telemetry read only`
```
gam oauth create
```
Many commands come in two forms:
```
gam <CrOSTypeEntity> <Command> ...
gam <Command> cros <CrOSEntity> ...
```
The first form allows more powerful selection of devices with `<CrOSTypeEntity>`.
The second form is backwards compatible with Standard GAM and selection with `<CrOSEntity>` is limited.
## Definitions
```BNF
<OrgUnitPath> ::= /|(/<String)+
<QueryCrOS> ::= <String> See: https://support.google.com/chrome/a/answer/1698333
<CommandID> ::= <String>
<CrOSID> ::= <String>
<CrOSIDList> ::= "<CrOSID>(,<CrOSID>)*"
<SerialNumber> ::= <String>
<SerialNumberList> ::= "<SerialNumber>(,<SerialNumber>)*"
<SerialNumberEntity> ::=
<SerialNumberList> | <FileSelector> | <CSVFileSelector>
<CrOSEntity> ::=
<CrOSIDList> | (cros_sn <SerialNumberList>) |
(query:<QueryCrOS>)|(query:orgunitpath:<OrgUnitPath>)|(query <QueryCrOS>)
<CrOSAttribute> ::=
(asset|assetid|tag <String>)|
(location <String>)|
(notes <String>)|(updatenotes <String>)|
(org|ou <OrgUnitPath>)|
(user <Name>)
<CrOSFieldName> ::=
activetimeranges|timeranges|
annotatedassetid|assetid|asset|
annotatedlocation|location|
annotateduser|user|
autoupdateexpiration|
bootmode|
cpustatusreports|
deprovisionreason|
devicefiles|
deviceid|
diskvolumereports|
dockmacaddress|
ethernetmacaddress|
ethernetmacaddress0|
firmwareversion|
firstenrollmenttime|
lastdeprovisiontimestamp|
lastenrollmenttime|
lastknownnetwork|
lastsync|
macaddress|
manufacturedate|
meid|
model|
notes|
ordernumber|
orgunitid|
orgunitpath|org|ou|
osversion|
platformversion|
recentusers|
screenshotfiles|
serialnumber|
status|
supportenddate|
systemramtotal|
systemramfreereports|
tpmversioninfo|
willautorenew
<CrOSFieldNameList> ::= "<CrOSFieldName>(,<CrOSFieldName>)*"
<CrOSListFieldName> ::=
activetimeranges|timeranges|times|
cpustatusreports|
devicefiles|files|
diskvolumereports|
lastknownnetwork|
recentusers|users|
screenshotfiles|
systemramfreereports
<CrOSListFieldNameList> ::= "<CrOSListFieldName>(,<CrOSListFieldName>)*"
<CrOSOrderByFieldName> ::=
lastsync|location|notes|serialnumber|status|supportenddate|user
```
```
<CrOSAction> ::=
deprovision_different_model_replace|
deprovision_retiring_device|
deprovision_same_model_replace|
deprovision_upgrade_transfer|
disable|
reenable|
pre_provisioned_disable|
pre_provisioned_reenable
<CrOSCommand>
reboot|
remote_powerwash|
set_volume <0-100>|
wipe_users|
take_a_screenshot
```
```
<CrOSActivityListFieldName> ::=
activetimeranges|timeranges|times|
devicefiles|files|
recentusers|users
<CrOSActivityListFieldNameList> ::= "<CrOSActivityListFieldName>(,<CrOSActivityListFieldName>)*"
<CrOSTelemetryFieldName> ::=
audiostatusreport|
batteryinfo|
batterystatusreport|
bootPerformancereport|
cpuinfo|
cpustatusreport|
customer|
deviceid|
graphicsinfo|
graphicsstatusreport|
memoryinfo|
memorystatusreport|
name|
networkdiagnosticsreport|
networkinfo|
networkstatusreport|
orgunitid|
osupdatestatus|
peripheralsreport|
serialnumber|
storageinfo|
storagestatusreport|
thunderboltinfo
<CrOSTelemetryFieldNameList> ::= "<CrOSTelemetryFieldName>(,<CrOSTelemetryFieldName>)*"
<CrOSTelemetryListFieldName> ::=
audiostatusreport|
batteryinfo|
batterystatusreport|
bootperformancereport|
cpuinfo|
cpustatusreport|
graphicsstatusreport|
memorystatusreport|
networkdiagnosticsreport|
networkstatusreport|
osupdatestatus|
peripheralsreport|
storagestatusreport|
thunderboltinfo
<CrOSTelemetryListFieldNameList> ::= "<CrOSTelemetryListFieldName>(,<CrOSTelemetryLIstFieldName>)*"
```
For `<OrgUnitEntity>`, see: [Collections of Items](Collections-of-Items)
For `<UserTypeEntity>`, see: [Collections of Users](Collections-Of-Users)
For `<CrOSTypeEntity>`, see: [Collections of ChromeOS Devices](Collections-of-ChromeOS-Devices)
## CrOS Query Searchable Fields
To search within a specific field only (for example, to search for a specific user), you can enter an operator followed by an argument -- for example, `user:jsmith`. You can use single words or quoted lists of words as an argument when running an operator query.
To run an operator query, follow these guidelines for each field:
### Serial Number
Enter `id:` as the operator. For example, if you are searching for the serial number 12345abcdefg, enter the following:
`gam print cros query "id:12345abcdefg"`
Partial serial number searches are supported, as long as you enter at least three characters in the serial number.
### Status
To view all provisioned or deprovisioned devices, select the status from the left drop-down, and all of the devices that fit this criterion will appear in the view. Alternatively, you can do the following searches from the All devices view:
`gam print cros query "status:[provisioned|disable|deprovisioned]"`
### User
Enter user: as the operator. For example, to match the name Joe, but not Joey, enter the following:
`gam print cros query "user:joe"`
To match the name Tom Sawyer or A. Tom Sawyer, but not Tom A. Sawyer, enter with quotation marks:
`gam print cros query "user:'tom sawyer'"`
### Location
Enter location: as the operator. For example, to match Seattle, enter the following:
`gam print cros query "location:seattle"`
Notes
Enter note: as the operator. For example, to match loaned from John, enter the following with quotation marks:
`gam print cros query "note:'loaned from john'"`
### Register
This field is not displayed on the Chrome OS settings page. However, you can search for devices that were registered on a given date, or within a given time range.
Enter register: as the operator, and enter a date and time (or time range) as the argument. For example, to search for all devices registered on April 15, 2020, enter the following:
`gam print cros query "register:2020-04-15"`
For additional examples using dates, times, and ranges, see "Format for date searches" below.
### Last Sync
Enter sync: as the operator and a date or time range as the argument. For example, to search for all devices that were last synced with policy settings on April 15, 2020, enter the following:
`gam print cros query "sync:2020-04-15"`
For additional examples using dates, times, and ranges, see "Format for date searches" below.
### Format for date searches
* `YYYY-MM-DD` - A single date
* `YYYY-MM-DD..YYYY-MM-DD` - A date range
* `..YYYY-MM-DD` - All dates on or before a date
* `YYYY-MM-DD..` - All dates on or after a date
### Asset ID
Enter asset_id: as the operator. For example, to match the partial Asset ID 1234, enter the following:
`gam print cros query "asset_id:1234"`
### WiFi MAC Address
Enter wifi_mac: as the operator. Address should be entered without spaces or colons. Partial address matching is not supported. Be aware that multiple devices may report the same address to the Admin console, and more than one result may be returned. For example, to search for the device(s) with WiFi MAC 6C:29:95:72:4C:50, enter the following:
`gam print cros query "wifi_mac:6c2995724c50"`
### Ethernet MAC Address
Enter ethernet_mac: as the operator. Address should be entered without spaces or colons. Partial address matching is not supported. Be aware that multiple devices may report the same address to the Admin console, and more than one result may be returned. For example, to search for the device(s) with ethernet MAC E8:EA:6A:15:79:81, enter the following:
`gam print cros query "ethernet_mac:e8ea6a157981"`
## ChromeOS device update OU error handling
If you get the following error when trying to update the OU of a ChromeOS device:
```
400: invalidInput - Invalid Input: Inconsistent Orgunit id and path in request
```
issue the following command to work around the Google problem causing the wrror:
```
gam select default config update_cros_ou_with_id true save
```
## Manage ChromeOS devices
```
gam <CrOSTypeEntity> update <CrOSAttribute>+ [quickcrosmove [<Boolean>]] [nobatchupdate]
gam update cros <CrOSEntity> <CrOSAttribute>+ [quickcrosmove [<Boolean>]] [nobatchupdate]
```
Google has introduced a new, faster method for moving CrOS devices to a new OU. The `quickcrosmove` option controls which method Gam uses.
* `quickcrosmove not specified` - use value from `quick_cros_move` in `gam.cfg` to select previous/new batch method
* `quickcrosmove False` - use individual method
* `quickcrosmove True` - use new method
* `quickcrosmove` - use new method
If `quickcrosmove` is False or the OU is not being updated, the individual method is used to update all attributes.
If `quickcrosmove` is True and the OU is the only `<CrOSAttribute>` being updated, the new method is used.
If `quickcrosmove` is True and other `<CrOSAttribute>` are being updated in addition to the OU, the new method is used
to update the OU and the individual method is used to update the other `<CrOSAttribute>`.
With either the individual or new method, batches of devices are processed to minimize the number of API calls.
The `batch_size` value from gam.cfg controls the number of deviceIds handled in each batch by either method.
Use the `nobatchupdate` option to suppress batch processing.
In the new method, Google doesn't seem to do any error checking of the CrOS deviceIds, there is no error message
given if invalid CrOS deviceIds are specified.
### Example: Move CrOS devices from one OU to another
```
gam cros_ou /Students/2021 update ou /Students/2022 quickcrosmove
```
### Example: Add a new note to existing notes
If you specify the `updatenotes <String>` option and it contains the string `#notes#`, the existing notes value will replace `#notes#`.
This requires an additional API to get the existing value.
If you have a CSV file, UpdateCrOS.csv with two columns: deviceId,notes
this command will add a new line of notes to the front of the existing notes:
```
gam csv UpdateCrOS.csv gam update cros ~deviceId updatenotes "~~notes~~\n#notes#"
```
## Add ChromeOS devices to an organizational unit
When adding ChromeOS devices to an OU, Gam uses a batch method to speed up processing.
For `<CrOSTypeEntity>`, see: [Collections of ChromeOS Devices](Collections-of-ChromeOS-Devices)
```
gam update org|ou <OrgUnitPath> add|move <CrOSTypeEntity>
[quickcrosmove [<Boolean>]]
gam update orgs|ous <OrgUnitEntity> add|move <CrOSTypeEntity>
[quickcrosmove [<Boolean>]]
```
Google has introduced a new, faster batch method for moving CrOS devices to a new OU. The `quickcrosmove` option controls which method Gam uses.
* `quickcrosmove not specified` - use value from `quick_cros_move` in `gam.cfg` to select previous/new batch method
* `quickcrosmove False` - use previous batch method
* `quickcrosmove True` - use new batch method
* `quickcrosmove` - use new batch method
The `batch_size` value from gam.cfg controls the number of deviceIds handled in each batch by either method.
In the new method, Google doesn't seem to do any error checking of the CrOS deviceIds, there is no error message
given if invalid CrOS deviceIds are specified.
### Example: Add ChromeOS devices to a single OU
Suppose you have a CSV file cros.csv with a single column: deviceId
```
gam update ou /Students/2022 add cros_csvfile cros.csv:deviceId quickcrosmove
```
### Example: Add ChromeOS devices to multiple OUs
Suppose you have a CSV file cros.csv with a two columns: deviceId,OU
All OUs will be updated with their associated devices.
```
gam update ou csvkmd cros.csv keyfield OU datafield deviceId add croscsvdata deviceId
```
## Action ChromeOS devices
```
<CrOSAction> ::=
deprovision_different_model_replace|
deprovision_retiring_device|
deprovision_same_model_replace|
deprovision_upgrade_transfer|
disable|
reenable|
pre_provisioned_disable|
pre_provisioned_reenable
gam <CrOSTypeEntity> update action <CrOSAction> [acknowledge_device_touch_requirement]
gam update cros <CrOSEntity> action <CrOSAction> [acknowledge_device_touch_requirement]
```
As deprovisioning ChromeOS devices is not reversible, you must enter `acknowledge_device_touch_requirement`
when `<CrOSAction>` is `deprovision_same_model_replace`, `deprovision_different_model_replace`,
`deprovision_retiring_device` or `deprovision_upgrade_transfer`.
Deprovisioning a device means the device will have to be physically wiped and re-enrolled to be managed by
your domain again. This requires physical access to the device and is very time consuming to perform for
each device. Please also be aware that deprovisioning can have an effect on your device license count.
See https://support.google.com/chrome/a/answer/3523633 for full details.
## Send remote commands to ChromeOS devices
Thanks to Jay for most of the following.
Send a remote command to the managed Chrome OS device. It's important to note that the device must be in a proper state to accept the command or an error may be returned.
For example, the `reboot`, `set_volume` and `take_a_screenshot` commands only work if the device is configured in auto-start kiosk app mode.
The `wipe_users` and `remote_powerwash` commands will erase all user data on the device and the `remote_powerwash` command will require that the device is physically reconnected to the
WiFi network and re-enrolled before it can be managed again. These commands require the `doit` argument so that the admin confirms the potential loss of user data and management.
Commands may take some time to execute on the remote device depending on the device state and connectivity to the Internet.
It's strongly recommended that devices be forced to auto-reenroll before performing `remote_powerwash` to prevent the device from falling out of a managed state permanently.
By default, GAM will wait 2 seconds and then check the status of the command before exiting. How many times GAM performs this status check can be configured with the `times_to_check_status` argument and
is configurable from 0 to some large number. If the status reaches `EXPIRED`, `CANCELLED` or `EXECUTED_BY_CLIENT` then the command has finished and no more checks will be performed.
```
<CrOSCommand>
reboot|
remote_powerwash|
set_volume <0-100>|
wipe_users|
take_a_screenshot
gam cros <CrOSTypeEntity> issuecommand command <CrOSCommand> [times_to_check_status <Integer>] [doit]
gam issuecommand cros <CrOSEntity> command <CrOSCommand> [times_to_check_status <Integer>] [doit]
```
If the final status is not reached before GAM exits, you can issue the following commands to continue checking the status.
```
gam cros <CrOSTypeEntity> getcommand commandid <CommandID> [times_to_check_status <Integer>]
gam getcommand cros <CrOSEntity> commandid <CommandID> [times_to_check_status <Integer>]
```
### Action Examples
Remove user profile data from the device; the device will remain enrolled and connected.
User data not synced to the Cloud including Downloads, Android app data and Crostini Linux VMs will be permanently lost.
Commands with issuecommand directly after gam will work with standard GAM & GAMADV-XTD3, whereas commands where the issuecommand is after the cros <CrOSTypeEntity> will work only with GAMADV-XTD3.
```
gam issuecommand cros dd1d659a-0ea4-4e94-905e-4726c7a5f1e9 command wipe_users doit
```
Remove profiles using the annotatedAssetID, which is a user editable field, in this example the device has an asset ID of CB1234.
```
gam cros_query "asset_id:CB1234" issuecommand command wipe_users doit
```
For multiple devices you can sepatete each asset ID with a comma
```
gam cros_queries "asset_id:CB1234,asset_id:CB5678" issuecommand command wipe_users doit
```
Powerwash the device with serial number 143040348.
```
gam issuecommand cros query:id:143040348 command remote_powerwash times_to_check_status 10 doit
gam cros_sn 143040348 issuecommand command remote_powerwash times_to_check_status 10 doit
```
Powerwash all devices in the /StudentCarts OrgUnit. Devices will need to be manually reconnected to WiFi which may mean entering a PSK.
Use `wipe_users` if that's going to create too much work for you.
```
gam issuecommand cros "query:orgunitpath:/StudentCarts" command remote_powerwash times_to_check_status 0 doit
gam cros_ou /StudentCarts issuecommand command remote_powerwash times_to_check_status 0 doit
```
## ChromeOS device lists
ChromeOS devices have lists of data: `<CrOSListFieldName>`, `<CrOSActivityListFieldName>`, `<CrOSTelemetryListFieldName>`.
All lists except `recentusers` are in ascending order (oldest to newest). As these lists can contain many entries,
you can use the `listlimit <Number>` option to limit the amount of data, but you'll get the oldest `<Number>` entries
(except for `recentusers`) which may not be what you want. The `reverselists` option changes the order to descending (newest to oldest);
the `listlimit <Number>` now gets the newest `<Number>` entries.
The `activetimeranges` and `recentusers` lists are independent, they are not aligned. The only alignment that
you can achieve is `activetimeranges recentusers reverselists activetimeranges listlimit 1`; this yields the
most recent user's activity time.
List field name synonyms:
- `activetimeranges` - `timeranges` and `times`
- `devicefiles` - `files`
- `recentusers` - `users`
## Display information about ChromeOS devices
```
gam <CrOSTypeEntity> info
[basic|full|allfields] <CrOSFieldName>* [fields <CrOSFieldNameList>]
[nolists]
[start <Date>] [end <Date>] [listlimit <Number>]
[reverselists <CrOSListFieldNameList>]
[timerangeorder ascending|descending] [showdvrsfp]
[downloadfile latest|<Time>] [targetfolder <FilePath>]
[formatjson]
gam info cros <CrOSEntity>
[basic|full|allfields] <CrOSFieldName>* [fields <CrOSFieldNameList>]
[nolists]
[start <Date>] [end <Date>] [listlimit <Number>]
[reverselists <CrOSListFieldNameList>]
[timerangeorder ascending|descending] [showdvrsfp]
[downloadfile latest|<Time>] [targetfolder <FilePath>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values:
- `reverselists <CrOSListFieldNameList>` - For each list, change order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `listlimit N reverselists activetimeranges`
- `timerangeorder descending` - Change the `activetimeranges` order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `timeranges listlimit N timerangeorder descending`
- `showdvrsfp` - Display a field `diskVolumeReports.volumeInfo.storageFreePercentage` which is calculated as: `(diskVolumeReports.volumeInfo.storageFree/diskVolumeReports.volumeInfo.storageTotal)*100`
- `formatjson` - Display the fields in JSON format.
## Print ChromeOS devices
### Print no header row and deviceId for specified CrOS devices
```
gam <CrOSTypeEntity> print
gam <CrOSTypeEntity> print cros
```
### Print a header row and fields for selected CrOS devices
```
gam print cros [todrive <ToDriveAttribute>*]
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime.* <Time>]
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
[orderby <CrOSOrderByFieldName> [ascending|descending]]
[basic|full|allfields] <CrOSFieldName>* [fields <CrOSFieldNameList>]
[nolists|(<CrOSListFieldName>* [onerow])]
[start <Date>] [end <Date>] [listlimit <Number>]
[reverselists <CrOSListFieldNameList>]
[timerangeorder ascending|descending] [showdvrsfp]
[sortheaders]
[formatjson [quotechar <Character>]]
```
Use these options to select CrOS devices; if none are chosen, all CrOS devices in the account are selected.
If only `(query <QueryCrOS>)|(queries <QueryCrOSList>)` is specified, the query applies to all devices. If one of the `cros_ou` options
is also specified, the query applies to devices within the OUs.
- `(query <QueryCrOS>)|(queries <QueryCrOSList>)` - Select CrOS devices that match a query
- `limittoou|cros_ou <OrgUnitItem>` - Select CrOS devices directly in the OU `<OrgUnitItem>`
- `cros_ou_and_children <OrgUnitItem>` - Select CrOS devices in the OU `<OrgUnitItem>` and its sub OUs
- `cros_ous <OrgUnitList>` - Select CrOS devices directly in the OUs `<OrgUnitList>`
- `cros_ous_and_children <OrgUnitList>` - Select CrOS devices in the OUs `<OrgUnitList>` and their sub OUs
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryCrOS>` and `queries <QueryCrOSList>` options.
The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries.
The characters following `querytime` can be any combination of lowercase letters and numbers.
For example, query for CrOS devices last synced more than a year ago:
```
querytime1year -1y query "sync:..#querytime1year#"
```
The first column will always be deviceId; the remaining field names will be sorted if `allfields`, `basic`, `full` or `sortheaders` is specified;
otherwise, the remaining field names will appear in the order specified.
- `basic` - Output these column headers: deviceId,annotatedAssetId,annotatedLocation,annotatedUser,lastSync,notes,serialNumber,status
- `allfields/full` - Output all column headers including eight list headers: activeTimeRanges, cpuStatusReports, deviceFiles, diskVolumeReports, lastKnownNetwork, recentUsers, screenshotFiles and systemRamFreeReports that repeat with multiple subvalues each, yielding a large number of columns that make the output hard to process.
- `nolists` - Suppresses these six headers; if you want these headers in a more manageable form use the following arguments.
- `<CrOSListFieldName>` - By default, one set of values for all `<CrOSListFieldName>` fields specified will be output on a separate row with all of the other headers.
- `onerow` - Output all of the `<CrOSListFieldName>` on a single row
- `listlimit <Number>` - Limits the number of repetitions to `<Number>`; if not specified or `<Number>` equals zero, there is no limit.
- `start <Date>` and `end <Date>` - Constrain activeTimeRanges, cpuStatusReports, deviceFiles and systemRamFreeReports to fall within the specified `<Dates>`. If a `<Date>` isn't specified, there is no filtering in that range.
- `reverselists <CrOSListFieldNameList>` - For each list, change order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `listlimit N reverselists timeranges`
- `timerangeorder descending` - Change the `activetimeranges` order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `timeranges listlimit N timerangeorder descending`.
- `showdvrsfp` - Display a field `diskVolumeReports.volumeInfo.storageFreePercentage` which is calculated as: `(diskVolumeReports.volumeInfo.storageFree/diskVolumeReports.volumeInfo.storageTotal)*100`
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format:
- `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
### Print a header row and fields for specified CrOS devices
Use [Print a header row and fields for selected CrOS devices](#print-a-header-row-and-fields-for-selected-cros-devices) if
you are specifying devices by OU; it will be much faster.
```
gam <CrOSTypeEntity> print cros [todrive <ToDriveAttribute>*]
[orderby <CrOSOrderByFieldName> [ascending|descending]]
[basic|full|allfields] <CrOSFieldName>* [fields <CrOSFieldNameList>]
[nolists|(<CrOSListFieldName>* [onerow])]
[start <Date>] [end <Date>] [listlimit <Number>]
[reverselists <CrOSListFieldNameList>]
[timerangeorder ascending|descending] [showdvrsfp]
[sortheaders]
[formatjson [quotechar <Character>]]
gam print cros [todrive <ToDriveAttribute>*] select <CrOSTypeEntity>
[orderby <CrOSOrderByFieldName> [ascending|descending]]
[basic|full|allfields] <CrOSFieldName>* [fields <CrOSFieldNameList>]
[nolists|(<CrOSListFieldName>* [onerow])]
[start <Date>] [end <Date>] [listlimit <Number>]
[reverselists <CrOSListFieldNameList>]
[timerangeorder ascending|descending] [showdvrsfp]
[sortheaders]
[formatjson [quotechar <Character>]]
```
The first column will always be deviceId; the remaining field names will be sorted if `allfields`, `basic`, `full` or `sortheaders` is specified;
otherwise, the remaining field names will appear in the order specified.
- `basic` - Output these column headers: deviceId,annotatedAssetId,annotatedLocation,annotatedUser,lastSync,notes,serialNumber,status
- `allfields/full` - Output all column headers including eight list headers: activeTimeRanges, cpuStatusReports, deviceFiles, diskVolumeReports, lastKnownNetwork, recentUsers, screenshotFiles and systemRamFreeReports that repeat with multiple subvalues each, yielding a large number of columns that make the output hard to process.
- `nolists` - Suppresses these six headers; if you want these headers in a more manageable form use the following arguments.
- `<CrOSListFieldName>` - By default, one set of values for all `<CrOSListFieldName>` fields specified will be output on a separate row with all of the other headers.
- `onerow` - Output all of the `<CrOSListFieldName>` on a single row
- `listlimit <Number>` - Limits the number of repetitions to `<Number>`; if not specified or `<Number>` equals zero, there is no limit.
- `start <Date>` and `end <Date>` - Constrain activeTimeRanges, cpuStatusReports, deviceFiles and systemRamFreeReports to fall within the specified `<Dates>`. If a `<Date>` isn't specified, there is no filtering in that range.
- `reverselists <CrOSListFieldNameList>` - For each list, change order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `listlimit N reverselists timeranges`
- `timerangeorder descending` - Change the `activetimeranges` order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `timeranges listlimit N timerangeorder descending`.
- `showdvrsfp` - Display a field `diskVolumeReports.volumeInfo.storageFreePercentage` which is calculated as: `(diskVolumeReports.volumeInfo.storageFree/diskVolumeReports.volumeInfo.storageTotal)*100`
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format:
- `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
### Display Examples
Print CrOS devices with limited free space:
```
gam config csv_output_row_filter "diskVolumeReports.volumeInfo.0.storageFreePercentage:countrange=1/30" redirect csv ./crosdiskusage.csv print cros fields serialnumber,ou,diskvolumereports showdvrsfp
```
Use `countrange=1/15` instead of `count<15` as the latter will display ChromeOS devices with no
diskVolumeReports; a blank entry is treated as a zero. Sustitue for `15` as desired.
ChromeOS devices can have multiple diskVolumeReports; some experimentation may be required to
get the desired results.
Print information about CrOS devices synced more than 30 days ago:
```
gam print cros query "sync:..#querytime1#" querytime1 -30d
```
Print information about CrOS devices synced in the last 30 days:
```
gam print cros query "sync:#querytime1#.." querytime1 -30d
```
Print information about CrOS devices synced between 45 days ago and 30 days ago:
```
gam print cros query "sync:#querytime1#..#querytime2#" querytime1 -45d querytime2 -30d
```
## Print ChromeOS device activity
### Print a header row and activity for selected CrOS devices
```
gam print crosactivity [todrive <ToDriveAttribute>*]
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime.* <Time>]
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
[orderby <CrOSOrderByFieldName> [ascending|descending]]
[recentusers] [timeranges] [both] [devicefiles] [all] [oneuserperrow]
[start <Date>] [end <Date>] [listlimit <Number>]
[reverselists <CrOSActivityListFieldNameList>]
[timerangeorder ascending|descending]
[delimiter <Character>]
[formatjson [quotechar <Character>]]
```
Use these options to select CrOS devices; if none are chosen, all CrOS devices in the account are selected.
If only `(query <QueryCrOS>)|(queries <QueryCrOSList>)` is specified, the query applies to all devices. If one of the `cros_ou` options
is also specified, the query applies to devices within the OUs.
- `(query <QueryCrOS>)|(queries <QueryCrOSList>)` - Select CrOS devices that match a query
- `limittoou|cros_ou <OrgUnitItem>` - Select CrOS devices directly in the OU `<OrgUnitItem>`
- `cros_ou_and_children <OrgUnitItem>` - Select CrOS devices in the OU `<OrgUnitItem>` and its sub OUs
- `cros_ous <OrgUnitList>` - Select CrOS devices directly in the OUs `<OrgUnitList>`
- `cros_ous_and_children <OrgUnitList>` - Select CrOS devices in the OUs `<OrgUnitList>` and their sub OUs
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryCrOS>` and `queries <QueryCrOSList>` options.
The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries.
The characters following `querytime` can be any combination of lowercase letters and numbers.
For example, query for CrOS devices last synced more than a year ago:
```
querytime1year -1y query "sync:..#querytime1year#"
```
- `reverselists <CrOSListFieldNameList>` - For each list, change order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `listlimit N reverselists timeranges`
- `timerangeorder descending` - Change the `activetimeranges` order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `timeranges listlimit N timerangeorder descending`.
### Print a header row and activity for specified CrOS devices
Use [Print a header row and activity for selected CrOS devices](#print-a-header-row-and-activity-for-selected-cros-devices)
you are specifying devices by OU; it will be much faster.
```
gam <CrOSTypeEntity> print crosactivity [todrive <ToDriveAttribute>*]
[orderby <CrOSOrderByFieldName> [ascending|descending]]
[recentusers] [timeranges] [both] [devicefiles] [all] [oneuserperrow]
[start <Date>] [end <Date>] [listlimit <Number>]
[reverselists <CrOSActivityListFieldNameList>]
[timerangeorder ascending|descending]
[delimiter <Character>]
[formatjson [quotechar <Character>]]
gam print crosactivity [todrive <ToDriveAttribute>*] select <CrOSTypeEntity>
[orderby <CrOSOrderByFieldName> [ascending|descending]]
[recentusers] [timeranges] [both] [devicefiles] [all] [oneuserperrow]
[start <Date>] [end <Date>] [listlimit <Number>]
[reverselists <CrOSActivityListFieldNameList>]
[timerangeorder ascending|descending]
[delimiter <Character>]
[formatjson [quotechar <Character>]]
```
- The basic column headers are: deviceId,annotatedAssetId,annotatedLocation,serialNumber,orgUnitPath.
- `recentusers` - All of the recent users email addresses, separated by the delimiter `<Character>`, with header recentUsers.email, are output with the basic headers.
- The delimiter defaults to `gam.cfg/csv_output_field_delimiter`.
- If `oneuserperrow` is specified, each recent user is output on a separate row with header recentUsers.email and the basic headers.
- `activetimeranges` - For each time range entry, activeTimeRanges.date, activeTimeRanges.duration and activeTimeRanges.minutes are output on a separate row with the basic headers.
- `devicefiles` - For each device file, the columns deviceFiles.type and deviceFiles.createTime are output on a separate row with the basic headers.
- `both` - Specifies `recentusers` and `activetimeranges`.
- `all` - Specifies `recentusers`, `activetimeranges` and `devicefiles`.
- The default is to include both `recentusers` and `activetimeranges`.
- `listlimit <Number>` - Limits the number of repetitions to `<Number>`; if not specified or `<Number>` equals zero, there is no limit.
- `start <Date>` and `end <Date>` - Filter the time ranges and device files to fall with in the specified `<Dates>`. If a `<Date>` isn't specified, there is no filtering in that range.
- `reverselists <CrOSListFieldNameList>` - For each list, change order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `listlimit N reverselists timeranges`
- `timerangeorder descending` - Change the `activetimeranges` order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `timeranges listlimit N timerangeorder descending`.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format:
- `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Download a ChromeOS device file
```
gam <CrOSTypeEntity> info downloadfile latest|<Time> [targetfolder <FilePath>]
gam info cros <CrOSEntity> downloadfile latest|<Time> [targetfolder <FilePath>]
```
Select the device file to download by its timestamp.
- `downloadfile latest` - Download the device file with the most recent timestamp.
- `downloadfile <Time>` - Download the device file with the `<`Time>` timestamp.
By default, when getting a device file, it is downloaded to the directory specified in `gam.cfg/drive_dir`.
- `targetfolder <FilePath>` - Specify an alternate location for the downloaded file.
### Download Examples
Suppose that you have an OU "/Kiosk Chromebooks" that contains ChromeOS devices running in kiosk mode and you want to download their device files.
Get the list of device files.
```
gam redirect csv ./CrOSDeviceFiles.csv print cros cros_ou "/Kiosk ChromeBooks" fields deviceId,devicefiles
```
Download the device files serially.
```
gam redirect stdout ./CrOSDeviceFiles.out redirect stderr stdout csvkmd cros ./CrOSDeviceFiles.csv keyfield deviceId matchfield deviceFiles.type LOG_FILE datafield deviceFiles.createTime get devicefile select csvdata deviceFiles.createTime
```
Download the device files in parallel.
```
gam redirect stdout ./CrOSDeviceFiles.out multiprocess redirect stderr stdout csv ./CrOSDeviceFiles.csv matchfield deviceFiles.type LOG_FILE gam cros ~deviceId get devicefile select ~deviceFiles.createTime
```
Suppose you want only the last device file for each Chromebook.
Download the device files serially.
```
gam redirect stdout ./CrOSDeviceFiles.out redirect stderr stdout cros_ou "/Kiosk ChromeBooks" get devicefile select last 1
```
Download the device files in parallel
```
gam config auto_batch_min 1 redirect stdout ./CrOSDeviceFiles.out multiprocess redirect stderr stdout cros_ou "/Kiosk ChromeBooks" get devicefile select last 1
```
## Display ChromeOS telemetry data
### Display data about a specific device.
```
gam info crostelemetry <SerialNumber>
<CrOSTelemetryFieldName>* [fields <CrOSTelemetryFieldNameList>]
[start <Date>] [end <Date>] [listlimit <Number>]
[reverselists <CrOSTelemetryListFieldNameList>]
[formatjson]
```
### Display data about all or selected devices.
```
gam show crostelemetry
[(ou|org|orgunit <OrgUnitItem>)|(cros_sn <SerialNumber>)|(filter <String>)]
<CrOSTelemetryFieldName>* [fields <CrOSTelemetryFieldNameList>]
[start <Date>] [end <Date>] [listlimit <Number>]
[reverselists <CrOSTelemetryListFieldNameList>]
[formatjson]
```
Use these options to select CrOS devices; if none are chosen, all CrOS devices in the account are selected.
- `ou|org|orgunit <OrgUnitItem>` - Select CrOS devices directly in the OU `<OrgUnitItem>`
- `cros_sn <SerialNumber>` - Select the CrOS device with serial number `<SerialNumber>`.
- `filter <String>` - Select the CrOS device with a filter.
- `listlimit <Number>` - Limits the number of repetitions to `<Number>`; if not specified or `<Number>` equals zero, there is no limit.
- `start <Date>` and `end <Date>` - Constrain list `reportTime` to fall within the specified `<Dates>`. If a `<Date>` isn't specified, there is no filtering in that range.
- `reverselists <CrOSTelemetryListFieldNameList>` - For each list, change order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `listlimit N reverselists cpustatusreport,memorystatusreport`
By default, all telemetry data is displayed, use the following to select specific fields:
- `<CrOSTelemetryFieldName>*` - Specify fields individually
- `fields <CrOSTelemetryFieldNameList>` - Specify a list of fields
By default, Gam displays the information as an indented list of keys and values:
- `formatjson` - Display the fields in JSON format.
### Print data about all or selected devices.
```
gam print crostelemetry [todrive <ToDriveAttribute>*]
[(ou|org|orgunit <OrgUnitItem>)|(cros_sn <SerialNumber>)|(filter <String>)]
<CrOSTelemetryFieldName>* [fields <CrOSTelemetryFieldNameList>]
[reverselists <CrOSTelemetryListFieldNameList>]
[start <Date>] [end <Date>] [listlimit <Number>]
[formatjson [quotechar <Character>]]
```
Use these options to select CrOS devices; if none are chosen, all CrOS devices in the account are selected.
- `ou|org|orgunit <OrgUnitItem>` - Select CrOS devices directly in the OU `<OrgUnitItem>`
- `cros_sn <SerialNumber>` - Select the CrOS device with serial number `<SerialNumber>`.
- `filter <String>` - Select the CrOS device with a filter.
- `listlimit <Number>` - Limits the number of repetitions to `<Number>`; if not specified or `<Number>` equals zero, there is no limit.
- `start <Date>` and `end <Date>` - Constrain list `reportTime` to fall within the specified `<Dates>`. If a `<Date>` isn't specified, there is no filtering in that range.
- `reverselists <CrOSTelemetryListFieldNameList>` - For each list, change order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `listlimit N reverselists cpustatusreport,memorystatusreport`
By default, all telemetry data is displayed, use the following to select specific fields:
- `<CrOSTelemetryFieldName>*` - Specify fields individually
- `fields <CrOSTelemetryFieldNameList>` - Specify a list of fields
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format:
- `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Check ChromeOS device serial number validity
Use this command to check the validity of ChromeOS device serial numbers.
```
gam print chromesnvalidity [todrive <ToDriveAttribute>*]
cros_sn <SerialNumberEntity> [listlimit <Number>]
[delimiter <Character>]
```
You specify serial numbers and GAM performs a query to see how many devices match; serial number matches are case-insensitive.
There are are two types of matches:
- Exact - A device has the exact serial number
- Prefix - A device has a serial number that has the specified value as a prefix
The column headers are: serialNumber,exactMatches,exactMatchDeviceIds,prefixMatches,prefixMatchDeviceIds.
- serialNumber - The serial number specified
- exactMatches - The number of exact matches
- exactMatchDeviceIds - The list of device IDs with exact match serial numbers
- prefixMatches - The number of prefix matches
- prefixMatchDeviceIds - The list of device IDs with prefix match serial numbers
The device IDs are separated by the delimiter `<Character>` that defaults to `gam.cfg/csv_output_field_delimiter`.
By default, all matching device IDs are displayed:
- `listlimit <Number>` - Limits the number of device IDs in a list to `<Number>`; if not specified or `<Number>` equals zero, there is no limit. `exactMatches` and `prefixmatches`
display the total number of matches.
### Examples
Specify serial numbers in the command.
```
$ gam print chromesnvalidity crossn DPCVLB3X,5CD9326FW0,5CD92055W listlimit 2 delimiter "|"
Getting all CrOS Devices that match query (id:DPCVLB3X), may take some time on a large Google Workspace Account...
Got 0 CrOS Devices...
Getting all CrOS Devices that match query (id:5CD9326FW0), may take some time on a large Google Workspace Account...
Got 1 CrOS Device...
Getting all CrOS Devices that match query (id:5CD92055W), may take some time on a large Google Workspace Account...
Got 5 CrOS Devices...
serialNumber,exactMatches,exactMatchDeviceIds,prefixMatches,prefixMatchDeviceIds
DPCVLB3X,0,,0,
5CD9326FW0,1,bfaef389-a1d5-4e7b-b9af-bfc6cdbdb5b2,0,
5CD92055W,0,,5,0123a16d-3884-4829-9324-df92d8fc1ad4|899d2b95-7914-4b6b-8428-d416ef900728
```
Specify serial numbers in a flat file.
```
$ more CrosSN.txt
DPCVLB3X
5CD9326FW0
5CD92055W
$ gam print chromesnvalidity crossn file CrosSN.txt listlimit 2 delimiter "|"
Getting all CrOS Devices that match query (id:DPCVLB3X), may take some time on a large Google Workspace Account...
Got 0 CrOS Devices...
Getting all CrOS Devices that match query (id:5CD9326FW0), may take some time on a large Google Workspace Account...
Got 1 CrOS Device...
Getting all CrOS Devices that match query (id:5CD92055W), may take some time on a large Google Workspace Account...
Got 5 CrOS Devices...
serialNumber,exactMatches,exactMatchDeviceIds,prefixMatches,prefixMatchDeviceIds
DPCVLB3X,0,,0,
5CD9326FW0,1,bfaef389-a1d5-4e7b-b9af-bfc6cdbdb5b2,0,
5CD92055W,0,,5,0123a16d-3884-4829-9324-df92d8fc1ad4|899d2b95-7914-4b6b-8428-d416ef900728```
```
Specify serial numbers in a CSV file.
```
$ more CrosSN.csv
serialNumber
DPCVLB3X
5CD9326FW0
5CD92055W
$ gam print chromesnvalidity crossn csvfile CrosSN.csv:serialNumber listlimit 2 delimiter "|"
Getting all CrOS Devices that match query (id:DPCVLB3X), may take some time on a large Google Workspace Account...
Got 0 CrOS Devices...
Getting all CrOS Devices that match query (id:5CD9326FW0), may take some time on a large Google Workspace Account...
Got 1 CrOS Device...
Getting all CrOS Devices that match query (id:5CD92055W), may take some time on a large Google Workspace Account...
Got 5 CrOS Devices...
serialNumber,exactMatches,exactMatchDeviceIds,prefixMatches,prefixMatchDeviceIds
DPCVLB3X,0,,0,
5CD9326FW0,1,bfaef389-a1d5-4e7b-b9af-bfc6cdbdb5b2,0,
5CD92055W,0,,5,0123a16d-3884-4829-9324-df92d8fc1ad4|899d2b95-7914-4b6b-8428-d416ef900728
```

655
docs/Classroom-Courses.md Normal file
View File

@ -0,0 +1,655 @@
# Classroom - Courses
- [API documentation](#api-documentation)
- [Notes](#notes)
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [Special quoting for course aliases and topics](#special-quoting-for-course-aliases-and-topics)
- [Updating course owner](#updating-course-owner)
- [Create and update courses](#create-and-update-courses)
- [Delete courses](#delete-courses)
- [Manage course aliases](#manage-course-aliases)
- [Manage course topics](#manage-course-topics)
- [Display courses](#display-courses)
- [Display course announcements](#display-course-announcements)
- [Display course materials](#display-course-materials)
- [Display course topics](#display-course-topics)
- [Display course work](#display-course-work)
- [Display course submissions](#display-course-submissions)
## API documentation
* https://developers.google.com/classroom/reference/rest/
* https://developers.google.com/classroom/reference/rest/v1/courses.students
* https://developers.google.com/classroom/reference/rest/v1/courses.teachers
* https://developers.google.com/classroom/reference/rest/v1/courses.announcements/list
* https://developers.google.com/classroom/reference/rest/v1/courses.topics/list
* https://developers.google.com/classroom/reference/rest/v1/courses.courseWork/list
* https://developers.google.com/classroom/reference/rest/v1/courses.courseWorkMaterials/list
* https://developers.google.com/classroom/reference/rest/v1/courses.courseWork.studentSubmissions/list
## Notes
In this document, `course materials` refers to stand-alone materials, not the materials associated with
`course announcements` or `course work`. Google added support for stand-alone materials in early 2021.
To use the course materials features you must authorize the appropriate scope: `Classroom API - Course Work/Materials`.
```
gam oauth create
gam user user@domain.com check|update serviceaccount
```
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
<CourseAlias> ::= <String>
<CourseAliasList> ::= "<CourseAlias>(,<CourseAlias>)*"
<CourseAliasEntity> ::=
<CourseAliasList>|<FileSelector>|<CSVFileSelector>|<CSVkmdSelector>|<CSVDataSelector>
<CourseAnnouncementID> ::= <Number>
<CourseAnnouncementIDList> ::= "<CourseAnnouncementID>(,<CourseAnnouncementID>)*"
<CourseAnnouncementIDEntity> ::=
<CourseAnnouncementIDList>|<FileSelector>|<CSVFileSelector>|<CSVkmdSelector>|<CSVSubkeySelector>|<CSVDataSelector>
<CourseAnnouncementState> ::= draft|published|deleted
<CourseAnnouncementStateList> ::= all|"<CourseAnnouncementState>(,<CourseAnnouncementState>)*"
<CourseID> ::= <Number>|d:<CourseAlias>
<CourseIDList> ::= "<CourseID>(,<CourseID>)*"
<CourseEntity> ::=
<CourseIDList>|<FileSelector>|<CSVFileSelector>|<CSVkmdSelector>
<CourseMaterialID> ::= <Number>
<CourseMaterialIDList> ::= "<CourseMaterialID>(,<CourseMaterialID>)*"
<CourseMaterialState> ::= draft|published|deleted
<CourseMaterialStateList> ::= all|"<CourseMaterialState>(,<CourseMaterialState>)*"
<CourseMaterialIDEntity> ::= <CourseMaterialIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector> | <CSVDataSelector>
<CourseState> ::= active|archived|provisioned|declined|suspended
<CourseStateList> ::= all|"<CourseState>(,<CourseState>)*"
<CourseSubmissionID> ::= <Number>
<CourseSubmissionIDList> ::= "<CourseSubmissionID>(,<CourseSubmissionID>)*"
<CourseSubmissionIDEntity> ::=
<CourseSubmissionIDList>|<FileSelector>|<CSVFileSelector>|<CSVDataSelector>
<CourseSubmissionState> ::= new|created|turned_in|returned|reclaimed_by_student
<CourseSubmissionStateList> ::= all|"<CourseSubmissionState>(,<CourseSubmissionState>)*"
<CourseTopic> ::= <String>
<CourseTopicList> ::= "<CourseTopic>(,<CourseTopic>)*"
<CourseTopicEntity> ::= <CourseTopicList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<CourseTopicID> ::= <Number>
<CourseTopicIDList> ::= "<CourseTopicID>(,<CourseTopicID>)*"
<CourseTopicIDEntity> ::=
<CourseTopicIDList>|<FileSelector>|<CSVFileSelector>|<CSVkmdSelector>|<CSVSubkeySelector>|<CSVDataSelector>
<CourseWorkID> ::= <Number>
<CourseWorkIDList> ::= "<CourseWorkID>(,<CourseWorkID>)*"
<CourseWorkIDEntity> ::=
<CourseWorkIDList>|<FileSelector>|<CSVFileSelector>|<CSVkmdSelector>|<CSVSubkeySelector>|<CSVDataSelector>
<CourseWorkState> ::= draft|published|deleted
<CourseWorkStateList> ::= all|"<CourseWorkState>(,<CourseWorkState>)*"
<CourseAttribute> ::=
(description <String>)|
(descriptionheading|heading <String>)|
(name <String>)|
(room <String>)|
(section <string>)|
(state|status <CourseState>)|
(owner|ownerid|teacher <UserItem>)
<CourseFieldName> ::=
alternatelink|
coursegroupemail|
coursematerialsets|
coursestate|
creationtime|
description|
descriptionheading|heading|
enrollmentcode|
gradebooksettings|
guardiansenabled|
id|
name|
owneremail|
ownerid|
room|
section|
teacherfolder|
teachergroupemail|
updatetime
<CourseFieldNameList> ::= '<CourseFieldName>(,<CourseFieldName>)*'
<CourseAnnouncementFieldName> ::=
alternatelink|
assigneemode|
courseid|
courseannouncementid|
creationtime|
creator|creatoruserid|
id|
materials|
scheduledtime|
state|
text|
updatetime
<CourseAnnouncementFieldNameList> ::= "<CourseAnnouncementFieldName>(,<CourseAnnouncementFieldName>)*"
<CourseAnnouncementOrderByFieldName> ::=
updatetime|
updatedate
<CourseMaterialFieldName> ::=
alternatelink|
assigneemode|
courseid|
courseworkmaterialid|
creationtime|
creator|creatoruserid|
description|
id|
materials|
scheduledtime|
state|
title|
topicid|
updatetime|
workmaterialid
<CourseMaterialFieldNameList> ::= "<CourseMaterialFieldName>(,<CourseMaterialFieldName>)*"
<CourseMaterialOrderByFieldName> ::=
updatetime|
updatedate
<CourseWorkFieldName> ::=
alternatelink|
assigneemode|
courseid|
courseworkid|
courseworktype|
creationtime|
creator|creatoruserid|
description|
duedate|
duetime|
id|
materials|
maxpoints|
scheduledtime|
state|
submissionmodificationmode|
title|
topicid|
updatetime|
worktype
<CourseWorkFieldNameList> ::= "<CourseWorkFieldName>(,<CourseWorkFieldName>)*"
<CourseWorkOrderByFieldName> ::=
duedate|
updatetime|
updatedate
<CourseSubmissionFieldName> ::=
alternatelink|
assignedgrade|
courseid|
courseworkid|
courseworktype|
creationtime|
draftgrade|
id|
late|
state|
submissionhistory|
updatetime|
userid|
worktype
<CourseSubmissionFieldNameList> ::= "<CourseSubmissionFieldName>(,<CourseSubmissionFieldName>)*"
```
## Special quoting for course aliases and topics
As course aliases and topics can contain spaces, some care must be used when entering `<CourseAliasList>` and `<CourseTopicList>`.
Suppose you have a course with the alias `Math Class`. To get information about it you enter the command: `gam info course "d:Math Class"`
The shell strips the `"` leaving a single argument `d:Math Class`; gam correctly processes the argument as it is expecting a single course.
Suppose you enter the command: `gam info courses "d:Math Class"`
The shell strips the `"` leaving a single argument `d:Math Class`; as gam is expecting a list, it splits the argument on space leaving two items and then tries to process `d:Math` and `Class`, not what you want.
You must enter: `gam info courses "'d:Math Class'"`
The shell strips the `"` leaving a single argument `'d:Math Class'`; as gam is expecting a list, it splits the argument on space while honoring the `'` leaving one item `d:Math Class` and correctly processes the item.
For multiple aliases you must enter: `gam info courses "'d:Math Class','d:Science Class'"`
See: [Lists and Collections](Lists-and-Collections)
## Updating course owner
When updating a course owner, the Classroom API generates an error if the new owner is not a co-teacher
or is the current owner.
Prior to version 5.31.08, if `<UserItem>` was not a co-teacher, you got this error:
```
$ gam update course 123929046789 teacher newteacher@domain.com
Course: 123929046789, Update Failed: @IneligibleOwner Only a co-teacher can be invited as owner of the course
```
GAM now adds `<UserItem>` as a co-teacher of the course, pauses 10 seconds, and then updates them to be the owner.
```
$ gam update course 123929046789 teacher newteacher@domain.com
Course Name: Test, Course: 123929046789, Updated with new teacher as owner: newteacher@domain.com
```
Prior to version 5.31.08, if `<UserItem>` is the current owner, you got this error:
```
$ gam update course 123929046789 teacher newteacher@domain.com
Course: 123929046789, Update Failed: @UserAlreadyOwner Cannot transfer course to the user who is already the owner
```
GAM now reports that the current owner was retained.
```
$ gam update course 123929046789 teacher newteacher@domain.com
Course Name: Test, Course: 123929046789, Updated with current owner: newteacher@domain.com
```
In the normal case when `<UserItem>` is a co-teacher, GAM now reports the change.
```
$ gam update course 123929046789 teacher newteacher@domain.com
Course Name: Test, Course: 123929046789, Updated with co-teacher as owner: newteacher@domain.com
```
## Create and update courses
The options `name <String>` and `teacher <UserItem>` are required when creating a class.
```
gam create|add course [id|alias <CourseAlias>] <CourseAttribute>*
[copyfrom <CourseID>
[announcementstates <CourseAnnouncementStateList>]
[materialstates <CourseMaterialStateList>]
[workstates <CourseWorkStateList>]
[removeduedate [<Boolean>]]
[mapsharemodestudentcopy edit|none|view]
[copymaterialsfiles [<Boolean>]]
[copytopics [<Boolean>]]
[markdraftaspublished [<Boolean>]]
[markpublishedasdraft [<Boolean>]]
[members none|all|students|teachers]]
[logdrivefileids [<Boolean>>]]
gam update course <CourseID> <CourseAttribute>+
[copyfrom <CourseID>
[announcementstates <CourseAnnouncementStateList>]
[materialstates <CourseMaterialStateList>]
[workstates <CourseWorkStateList>]
[removeduedate [<Boolean>]]
[mapsharemodestudentcopy edit|none|view]
[copymaterialsfiles [<Boolean>]]
[copytopics [<Boolean>]]
[markdraftaspublished [<Boolean>]]
[markpublishedasdraft [<Boolean>]]
[members none|all|students|teachers]]
[logdrivefileids [<Boolean>>]]
gam update courses <CourseEntity> <CourseAttribute>+
[copyfrom <CourseID>
[announcementstates <CourseAnnouncementStateList>]
[materialstates <CourseMaterialStateList>]
[workstates <CourseWorkStateList>]
[removeduedate [<Boolean>]]
[mapsharemodestudentcopy edit|none|view]
[copymaterialsfiles [<Boolean>]]
[copytopics [<Boolean>]]
[markdraftaspublished [<Boolean>]]
[markpublishedasdraft [<Boolean>]]
[members none|all|students|teachers]]
[logdrivefileids [<Boolean>>]]
```
`copyfrom <CourseID>` allows copying of course announcements, work, topics and members from one course to another.
* Accouncements - By default, no course announcements are copied
* `announcementstates <CourseAnnouncementStateList>` - Copy class announcements with the specified states
* Materials - By default, no course materials are copied
* `materialstates <CourseMaterialsStateList>` - Copy class materials with the specified states
* Work - By default, no course work is copied
* `workstates <CourseWorkStateList>` - Copy class work with the specified states
* `removeduedate false` - Remove due dates before the current time; this is the default
* `removeduedate|removeduedate true` - Remove all due dates
* Announcements, Materials and Work Materials files
* `copymaterialsfiles false` - Copy links to files referenced by materials in the `copyfrom` course; this is the default
* `copymaterialsfiles|copymaterialsfiles true` - Copy files referenced by materials in the `copyfrom` course
* You must verify that the teacher of the course being created/updated has access to the files in the `copyfrom` course
* Files can only be copied to a course that is ACTIVE; GAM will adjust the course state as necessary
* Topics - By default, no course topics are copied; if topics are not copied, references to them will be deleted from class work that is copied
* `copytopics false` - No course topics are copies
* `copytopics|copytopics true` - Copy topics
* Published Material and Work - By default, published material and work is not relabeled
* `markdraftaspublished false` - Do not relabel draft material/work as published; this is the default
* `markdraftaspublished|markpublishedasdraft true` - Relabel draft material/work as published
* `markpublishedasdraft false` - Do not relabel published material/work as draft; this is the default
* `markpublishedasdraft|markpublishedasdraft true` - Relabel published material/work as draft
* Members - By default, no course members are copied
* `members none` - No course members are copied
* `members all` - Copy course students and teachers
* `members students` - Copy students
* `members teachers` - Copy teachers
When true, `logdrivefileids [<Boolean>>]` generates a CSV file with headers `courseId,ownerId,fileId' that
lists all drive files in the course.
The Classroom API does not support course materials of type `form`, they will not be copied.
Drive files with `shareMode` `Each student will get a copy` don't seem to be able to be copied.
* `mapsharemodestudentcopy edit` - Map `Each student will get a copy` to `Students can edit file`
* `mapsharemodestudentcopy view` - Map `Each student will get a copy` to `Students can view file`
* `mapsharemodestudentcopy none` or not specified - No `shareMode` mapping is performed, you may get an error
## Delete courses
Classes can only be deleted when they are in the ARCHIVED state; to delete a class, you can update its state to ARCHIVED
and then delete it or you can specify that it be archived as part of the delete command.
```
gam delete course <CourseID> [archived]
gam delete courses <CourseEntity> [archived]
```
## Manage course aliases
These commands can process a single course.
```
gam course <CourseID> add alias <CourseAlias>
gam course <CourseID> delete alias <CourseAlias>
```
These commands can process multiple courses.
```
gam courses <CourseEntity> add alias <CourseAliasEntity>
gam courses <CourseEntity> delete alias <CourseAliasEntity>
```
## Manage course topics
These commands can process a single course.
```
gam course <CourseID> add topic <CourseTopic>
gam course <CourseID> delete topic <CourseTopicID>
```
These commands can process multiple courses.
```
gam courses <CourseEntity> add topic <CourseTopicEntity>
gam courses <CourseEntity> delete topic <CourseTopicIDEntity>
```
## Display courses
```
gam info course <CourseID> [owneremail] [alias|aliases] [show all|students|teachers] [countsonly]
[fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>] [formatjson]
gam info courses <CourseEntity> [owneremail] [alias|aliases] [show all|students|teachers] [countsonly]
[fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>] [formatjson]
gam print courses [todrive <ToDriveAttribute>*]
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] [states <CourseStateList>])
[owneremail] [owneremailmatchpattern <RegularExpression>]
[alias|aliases|aliasesincolumns [delimiter <Character>]]
[show all|students|teachers] [countsonly]
[fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>] [formatjson [quotechar <Character>]]
[timefilter creationtime|updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
```
By default, the `print courses` command displays information about all courses.
To get information about a specific set of courses, use the following option; it can be repeated to select multiple courses.
* `(course|class <CourseEntity>)*` - Display courses with the IDs specified in `<CourseEntity>`.
To get information about courses based on its owner's emailaddress, use the `owneremailmatchpattern <RegularExpression>` option.
* `foo@bar.com` - Display courses with a specific owner emailaddress.
* `.*test.*` - Display courses with an owner emailaddress that matches a pattern.
* `Unknown user` - Display courses where the owner emailaddress has been deleted.
To get information about courses based on their having a particular participant, use the following options. Both options can be specified.
* `teacher <UserItem>` - Display courses with the specified teacher.
* `student <UserItem>` - Display courses with the specified student.
To get information about courses based on their state, use the following option. This option can be combined with the `teacher` and `student` options.
By default, all course states are selected.
* `states <CourseStateList>` - Display courses with any of the specified states.
To get information about courses created/updated within a particular time frame, use the following options.
* `timefilter creationtime|updatetime` - select which event to filter
* `start|starttime <Date>|<Time>` - specify the start of the time frame; if not specified, the time frame will be open ended at the start
* `end|endtime <Date>|<Time>` - specify the end of the time frame; if not specified, the time frame will be open ended at the end
For the filter to apply, `timefilter` and at least one of `start|starttime` and `end|endtime` must be specified.
By default, all basic course fields are displayed; use the following options to modify the output.
* `owneremail` - Display course owner email; requires an additional API call per course.
* `alias|aliases` - Display course aliases; all aliases are in the single column `Aliases` separated by a delimiter; requires an additional API call per course.
* `delimiter <Character>` - Delimiter between aliases with `print` command.
* `aliasesincolumn` - Display course aliases; the `Aliases` column contains the number of aliases and `Aliases.0`, `Aliases.1`, ... contain the individual aliases; requires an additional API call per course.
* `show all|students|teachers` - Show class participants profile information; requires an additional API call per course.
* `countsonly` - Eliminates the student/teacher profile information and outputs only the student/teacher counts.
* `fields <CourseFieldNameList>` - Select specific basic fields to display.
* `skipfields <CourseFieldNameList>` - Select specific basic fields to eliminate from display; typically used with `coursematerialsets`.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display course announcements
```
gam print course-announcements [todrive <ToDriveAttribute>*]
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
(courseannouncementids <CourseAnnouncementIDEntity>)|(announcementstates <CourseAnnouncementStateList>)*
(orderby <CourseAnnouncementOrderByFieldName> [ascending|descending])*)
[creatoremail] [fields <CourseAnnouncementFieldNameList>] [formatjson [quotechar <Character>]]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
```
By default, the `print course-announcements` command displays course announcement information for all courses.
To get course announcements for a specific set of courses, use the following option; it can be repeated to select multiple courses.
* `(course|class <CourseEntity>)*` - Display courses with the IDs specified in `<CourseEntity>`.
To get course announcements for courses based on their having a particular participant, use the following options. Both options can be specified.
* `teacher <UserItem>` - Display courses with the specified teacher.
* `student <UserItem>` - Display courses with the specified student.
To get course announcements for courses based on their state, use the following option. This option can be combined with the `teacher` and `student` options.
By default, all course states are selected.
* `states <CourseStateList>` - Display courses with any of the specified states.
By default, all published course announcements for a course are displayed; use the following options to select specific course announcements.
* `courseannouncementids <CourseAnnouncementIDEntity>` - Display course announcements with the IDs specified in `<CourseAnnouncementIDEntity>`.
* `announcementstates <CourseAnnouncementStateList>` - Display course announcements with any of the specified states.
To get information about course announcements created/updated/scheduled within a particular time frame, use the following options.
* `timefilter creationtime|updatetime|scheduledtime` - select which event to filter
* `start|starttime <Date>|<Time>` - specify the start of the time frame; if not specified, the time frame will be open ended at the start
* `end|endtime <Date>|<Time>` - specify the end of the time frame; if not specified, the time frame will be open ended at the end
For the filter to apply, `timefilter` and at least one of `start|starttime` and `end|endtime` must be specified.
By default, all course announcement fields are displayed; use the following options to modify the output.
* `creatoremail` - Display course announcement creator email; requires an additional API call per course announcement.
* `fields <CourseAnnouncementFieldNameList>` - Select specific fields to display.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display course materials
```
gam print course-materials [todrive <ToDriveAttribute>*]
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
(materialids <CourseMaterialIDEntity>)|(materialstates <CourseMaterialStateList>)*
(orderby <CourseMaterialOrderByFieldName> [ascending|descending])*)
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>] [formatjson [quotechar <Character>]]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
```
By default, the `print course-materials` command displays course materials information for all courses.
To get course materials information for a specific set of courses, use the following option; it can be repeated to select multiple courses.
* `(course|class <CourseEntity>)*` - Display courses with the IDs specified in `<CourseEntity>`.
To get course materials information for courses based on their having a particular participant, use the following options. Both options can be specified.
* `teacher <UserItem>` - Display courses with the specified teacher.
* `student <UserItem>` - Display courses with the specified student.
To get course materials information for courses based on their state, use the following option. This option can be combined with the `teacher` and `student` options.
By default, all course states are selected.
* `states <CourseStateList>` - Display courses with any of the specified states.
To get information about course materials created/updated/scheduled within a particular time frame, use the following options.
* `timefilter creationtime|updatetime|scheduledtime` - select which event to filter
* `start|starttime <Date>|<Time>` - specify the start of the time frame; if not specified, the time frame will be open ended at the start
* `end|endtime <Date>|<Time>` - specify the end of the time frame; if not specified, the time frame will be open ended at the end
For the filter to apply, `timefilter` and at least one of `start|starttime` and `end|endtime` must be specified.
By default, all published course materials for a course are displayed; use the following options to select specific course materials.
* `materialsids <CourseMaterialsIDEntity>` - Display course materials with the IDs specified in `<CourseMaterialsIDEntity>`.
* `materialsstates <CourseMaterialsStateList>` - Display course materials with any of the specified states.
By default, all course materials fields are displayed; use the following options to modify the output.
* `showcreatoremails` - Display course materials creator email; requires an additional API call per course materials.
* `showtopicnames` - Display topic names; requires and additional API call per course.
* `fields <CourseMaterialsFieldNameList>` - Select specific fields to display.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display course topics
```
gam print course-topics [todrive <ToDriveAttribute>*]
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
(coursetopicids <CourseTopicIDEntity>)
[formatjson [quotechar <Character>]]
[timefilter updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
```
By default, the `print course-topics` command displays course topic information for all courses.
To get course topics for a specific set of courses, use the following option; it can be repeated to select multiple courses.
* `(course|class <CourseEntity>)*` - Display courses with the IDs specified in `<CourseEntity>`.
To get course topics for courses based on their having a particular participant, use the following options. Both options can be specified.
* `teacher <UserItem>` - Display courses with the specified teacher.
* `student <UserItem>` - Display courses with the specified student.
To get course topics for courses based on their state, use the following option. This option can be combined with the `teacher` and `student` options.
By default, all course states are selected.
* `states <CourseStateList>` - Display courses with any of the specified states.
By default, all published course topics for a course are displayed; use the following options to select specific course topics.
* `coursetopicids <CourseTopicIDEntity>` - Display course topics with the IDs specified in `<CourseTopicIDEntity>`.
* `topicstates <CourseTopicStateList>` - Display course topics with any of the specified states.
To get information about course topics updated within a particular time frame, use the following options.
* `timefilter updatetime` - select which event to filter
* `start|starttime <Date>|<Time>` - specify the start of the time frame; if not specified, the time frame will be open ended at the start
* `end|endtime <Date>|<Time>` - specify the end of the time frame; if not specified, the time frame will be open ended at the end
For the filter to apply, `timefilter` and at least one of `start|starttime` and `end|endtime` must be specified.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display course work
```
gam print course-work [todrive <ToDriveAttribute>*]
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
(workids <CourseWorkIDEntity>)|(workstates <CourseWorkStateList>)*
(orderby <CourseWorkOrderByFieldName> [ascending|descending])*)
[showcreatoremails] [showtopicnames] [fields <CourseWorkFieldNameList>] [formatjson [quotechar <Character>]]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
```
By default, the `print course-work` command displays course work information for all courses.
To get course work information for a specific set of courses, use the following option; it can be repeated to select multiple courses.
* `(course|class <CourseEntity>)*` - Display courses with the IDs specified in `<CourseEntity>`.
To get course work information for courses based on their having a particular participant, use the following options. Both options can be specified.
* `teacher <UserItem>` - Display courses with the specified teacher.
* `student <UserItem>` - Display courses with the specified student.
To get course work information for courses based on their state, use the following option. This option can be combined with the `teacher` and `student` options.
By default, all course states are selected.
* `states <CourseStateList>` - Display courses with any of the specified states.
To get information about course work created/updated/scheduled within a particular time frame, use the following options.
* `timefilter creationtime|updatetime|scheduledtime` - select which event to filter
* `start|starttime <Date>|<Time>` - specify the start of the time frame; if not specified, the time frame will be open ended at the start
* `end|endtime <Date>|<Time>` - specify the end of the time frame; if not specified, the time frame will be open ended at the end
For the filter to apply, `timefilter` and at least one of `start|starttime` and `end|endtime` must be specified.
By default, all pub`lished course work for a course is displayed; use the following options to select specific course work.
* `workids <CourseWorkIDEntity>` - Display course work with the IDs specified in `<CourseWorkIDEntity>`.
* `workstates <CourseWorkStateList>` - Display course work with any of the specified states.
By default, all course work fields are displayed; use the following options to modify the output.
* `showcreatoremails` - Display course work creator email; requires an additional API call per course work.
* `showtopicnames` - Display topic names; requires and additional API call per course.
* `fields <CourseWorkFieldNameList>` - Select specific fields to display.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display course submissions
```
gam print course-submissions [todrive <ToDriveAttribute>*]
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
(workids <CourseWorkIDEntity>)|(workstates <CourseWorkStateList>)*
(orderby <CourseWorkOrderByFieldName> [ascending|descending])*)
(submissionids <CourseSubmissionIDEntity>)|(submissionstates <CourseSubmissionStateList>)*) [late|notlate]
[fields <CourseSubmissionFieldNameList>] [showuserprofile] [formatjson [quotechar <Character>]]
[timefilter creationtime|updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
```
By default, the `print course-submissions` command displays course submission information for all course work for all courses.
To get course submission information for a specific set of courses, use the following option; it can be repeated to select multiple courses.
* `(course|class <CourseEntity>)*` - Display courses with the IDs specified in `<CourseEntity>`.
To get course submission information for courses based on their having a particular participant, use the following options. Both options can be specified.
* `teacher <UserItem>` - Display courses with the specified teacher.
* `student <UserItem>` - Display courses with the specified student.
To get course submission information for courses based on their state, use the following option. This option can be combined with the `teacher` and `student` options.
By default, all course states are selected.
* `states <CourseStateList>` - Display courses with any of the specified states.
By default, all course work for a course is displayed; use the following options to select specific course work.
* `workids <CourseWorkIDEntity>` - Display course work with the IDs specified in `<CourseWorkIDEntity>`.
* `workstates <CourseWorkStateList>` - Display course work with any of the specified states.
By default, all course submissions for a course work is displayed; use the following options to select specific course submissions.
* `submissionids <CourseSubmissionIDEntity>` - Display course submissions with the IDs specified in `<CourseSubmissionIDEntity>`.
* `submissionstates <CourseSubmissionStateList>` - Display course submissions with any of the specified states.
* `late` - Display course submissions marked late.
* `notlate` - Display course submissions not marked late.
To get information about course submissionss created/updated within a particular time frame, use the following options.
* `timefilter creationtime|updatetime` - select which event to filter
* `start|starttime <Date>|<Time>` - specify the start of the time frame; if not specified, the time frame will be open ended at the start
* `end|endtime <Date>|<Time>` - specify the end of the time frame; if not specified, the time frame will be open ended at the end
For the filter to apply, `timefilter` and at least one of `start|starttime` and `end|endtime` must be specified.
By default, all course submission fields are displayed; use the following options to modify the output.
* `fields <CourseSubmissionFieldNameList>` - Select specific fields to display.
By default, only the numeric userId is displayed; use the `showuserprofile` option to get the user email address and name.
You can only get profile information if the scope `https://www.googleapis.com/auth/classroom.profile.emails` is enabled
for service account access; verify with `gam <UserTypeEntity> update serviceaccount`.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

185
docs/Classroom-Guardians.md Normal file
View File

@ -0,0 +1,185 @@
# Classroom - Guardians
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Create guardian invitations](#create-guardian-invitations)
- [Delete guardian invitations](#delete-guardian-invitations)
- [Display guardian invitations](#display-guardian-invitations)
- [Delete guardians](#delete-guardians)
- [Synchronize guardians](#synchronize-guardians)
- [Display guardians, indented keys and values](#display-guardians-indented-keys-and-values)
- [Display guardians, CSV format](#display-guardians-csv-format)
## API documentation
* https://developers.google.com/classroom/reference/rest/v1/userProfiles.guardianInvitations
* https://developers.google.com/classroom/reference/rest/v1/userProfiles.guardians
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<UniqueID> ::= id:<String>
<GuardianItem> ::= <EmailAddress>|<UniqueID>|<String>
<GuardianItemList> ::= "<GuardianItem>(,<GuardianItem>)*"
<GuardianEntity> ::= <GuardianList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<StudentItem> ::= <EmailAddress>|<UniqueID>|<String>
<GuardianInvitationID> ::= <String>
<GuardianInvitationIDList> ::= "<GuardianInvitationId>(,<GuardianInvitationID>)*"
<GuardianInvitationIDEntity> ::= <GuardianInvitationIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<GuardianState> ::= complete|pending
<GuardianStateList> ::= "<GuardianState>(,<GuardianState>)*"
```
## Create guardian invitations
### Selected students, new style
```
gam <UserTypeEntity> create|add guardian|guardianinvite|inviteguardian <GuardianEntity>
```
### Selected students, old style
```
gam create guardian|guardianinvite|inviteguardian <EmailAddress> <StudentItem>
```
## Delete guardian invitations
### Selected students, new style
```
gam <UserTypeEnfity> cancel guardianinvitation|guardianinvitations <GuardianInvitationIDEntity>
gam <UserTypeEntity> delete guardian|guardians <GuardianEntity> invitations
gam <UserTypeEntity> clear guardian|guardians invitations
```
### Selected students, old style
```
gam cancel guardianinvitation|guardianinvitations <GuardianInvitationID> <StudentItem>
gam delete guardian|guardians <GuardianItem> <StudentItem> invitations
```
## Display guardian invitations
### All students
```
gam show guardian|guardians invitations [states <GuardianInvitationStateList>] [invitedguardian <EmailAddress>]
[showstudentemails] [formatjson]
gam print guardian|guardians [todrive <ToDriveAttribute>*] invitations [states <GuardianInvitationStateList>] [invitedguardian <EmailAddress>]
[showstudentemails] [formatjson [quotechar <Character>]]
```
The Classroom API does not return the student email address, use the `showstudentemails` option to get the student email address. This requires an additional API call per student.
### Selected students, new style
```
gam <UserTypeEntity> show guardian|guardians invitations [states <GuardianInvitationStateList>] [invitedguardian <EmailAddress>]
[formatjson]
gam <UserTypeEntity> print guardian|guardians [todrive <ToDriveAttribute>*] invitations [states <GuardianInvitationStateList>] [invitedguardian <EmailAddress>]
[formatjson [quotechar <Character>]]
```
### Selected students, old style
```
gam show guardian|guardians invitations [showstudentemails] [states <GuardianStateList>] [invitedguardian <EmailAddress>]
[student <StudentItem>] [<UserTypeEntity>]
[formatjson]
gam print guardian|guardians [todrive <ToDriveAttribute>*] invitations [showstudentemails] [states <GuardianStateList>] [invitedguardian <EmailAddress>]
[student <StudentItem>] [<UserTypeEntity>]
[formatjson [quotechar <Character>]]
```
By default, Gam displays informations for all guardian invitations; you can limit the display with the following options.
* `states <GuardianStateList>` - Display guardian invitations with the specified state
* `invitedguardian <EmailAddress>` - Display guardians invitations with `<EmailAddress>`
## Delete guardians
### Selected students, new style
```
gam <UserTypeEntity> delete guardian|guardians <GuardianEntity> [accepted|invitations|all]
gam <UserTypeEntity> clear guardian|guardians [accepted|invitations|all]
```
* `accepted` - Delete accepted invitations
* `invitations` - Delete pending invitations
* `all` - Delete accepted and pending invitations
### Selected students, old style
```
gam delete guardian|guardians <GuardianItem> <StudentItem>
```
## Synchronize guardians
Gam deletes any pending guardian invitations and accepted guardians that are not in `<GuardianEntity>` and sends
invitations to the members in `<GuardianEntity>` that don't have a pending invitation or have not accepted.
```
gam <UserTypeEntity> sync guardian|guardians <GuardianEntity>
```
### Example
Your school SIS produces a CSV file, StudentGuardians.csv, each evening with two columns: Student,Guardian.
There is no indication as to what changes have been made from the night before. The following command will perform the
necessary changes.
```
gam csvkmd users StudentGuardians.csv keyfield Student datafield Guardian sync guardians csvdata Guardian
```
## Display guardians, indented keys and values
### All students
```
gam show guardian|guardians [accepted|invitations|all]
[states <GuardianInvitationStateList>] [invitedguardian <EmailAddress>]
[showstudentemails] [formatjson]
```
### Selected students, new style
```
gam <UserTypeEntity> show guardian|guardians [accepted|invitations|all]
[states <GuardianInvitationStateList>] [invitedguardian <EmailAddress>]
[formatjson]
```
### Selected students, old style
```
gam show guardian|guardians [accepted|invitations|all] [invitedguardian <EmailAddress>]
[states <GuardianInvitationStateList>] [invitedguardian <EmailAddress>]
[student <StudentItem>] [<UserTypeEntity>]
[showstudentemails] [formatjson]
```
Use these options to control what information is displayed:
* `accepted` - Display accepted guardians; this is the default
* `invitations` - Display invitations
* `states <GuardianInvitationStateList>` - Filter the invitations by state
* `all` - Display accepted guardians and pending invitations
* `states <GuardianInvitationStateList>` - Filter the invitations by state
By default, Gam displays informations for all guardians; you can limit the display with the following option:
* `invitedguardian <EmailAddress>` - Display guardians with `<EmailAddress>`.
The Classroom API does not return the student email address, use the `showstudentemails` option to get the student email address. This requires an additional API call per student.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
## Display guardians, CSV format
### All students
```
gam print guardian|guardians [todrive <ToDriveAttribute>*] [accepted|invitations|all]
[states <GuardianInvitationStateList>] [invitedguardian <EmailAddress>]
[showstudentemails] [formatjson [quotechar <Character>]]
```
### Selected students, new style
```
gam <UserTypeEntity> print guardian|guardians [todrive <ToDriveAttribute>*] [accepted|invitations|all]
[states <GuardianInvitationStateList>] [invitedguardian <EmailAddress>]
[formatjson [quotechar <Character>]]
```
### Selected students, old style
```
gam print guardian|guardians [todrive <ToDriveAttribute>*] [accepted|invitations|all]
[states <GuardianInvitationStateList>] [invitedguardian <EmailAddress>]
[student <StudentItem>] [<UserTypeEntity>]
[showstudentemails] [formatjson [quotechar <Character>]]
```
Use these options to control what information is displayed:
* `accepted` - Display accepted guardians; this is the default
* `invitations` - Display invitations
* `states <GuardianInvitationStateList>` - Filter the invitations by state
* `all` - Display accepted guardians and pending invitations
* `states <GuardianInvitationStateList>` - Filter the invitations by state
By default, Gam displays informations for all guardians; you can limit the display with the following options.
* `invitedguardian <EmailAddress>` - Display guardians with `<EmailAddress>`.
The Classroom API does not return the student email address, use the `showstudentemails` option to get the student email address. This requires an additional API call per student.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,135 @@
# Classroom - Invitations
- [API documentation](#api-documentation)
- [Notes](#notes)
- [Definitions](#definitions)
- [Create classroom invitations](#create-classroom-invitations)
- [Accept classroom invitations](#accept-classroom-invitations)
- [Delete classroom invitations](#delete-classroom-invitations)
- [Display classroom invitations by user](#display-classroom-invitations-by-user)
- [Display classroom invitations by course](#display-classroom-invitations-by-course)
## API documentation
* https://developers.google.com/classroom/reference/rest/v1/invitations
## Notes
You must authorize an additional Service Account scope to use these commands.
Do this command; sustitute a valid email address for user@domain.com.
```
gam user user@domain.com check serviceaccount
```
You should see the following scope fail:
```
Scope: https://www.googleapis.com/auth/classroom.rosters , Checked: FAIL (6/15)
```
Follow the directions to authorize the Service Account scopes.
The Classroom API does not support inviting users from outside your domain.
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<UniqueID> ::= id:<String>
<ClassroomInvitationID> ::= <String>
<ClassroomInvitationIDList> ::= "<ClassroomInvitationID>(,<ClassroomInvitationID>)*"
<ClassroomInvitationIDEntity> ::= <ClassroomInvitationIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<CourseAlias> ::= <String>
<CourseID> ::= <Number>|d:<CourseAlias>
<CourseIDList> ::= "<CourseID>(,<CourseID>)*"
<CourseEntity> ::= <CourseIDList> | <FileSelector> | <CSVFileSelector | <CSVkmdSelector>
<CourseState> ::= active|archived|provisioned|declined|suspended
<CourseStateList> ::= all|"<CourseState>(,<CourseState>)*"
```
## Create classroom invitations
Invite users to classes.
```
gam <UserTypeEntity> create classroominvitation courses <CourseEntity> [role owner|student|teacher]
[adminaccess|asadmin] [csvformat] [todrive <ToDriveAttributes>*] [formatjson [quotechar <Character>]]
```
If `role` is not specified, `student` will be used.
By default, classroom invitations are issued by the owner of the course, the `adminaccess` option causes the invitations to be issued by the admin named in `oauth2.txt`.
### Example
Suppose you have a CSV file CourseStudent.csv with two columns: Course,Student.
This command will invite all students to their courses serially by student.
```
gam redirect stdout ./Invites.out redirect stderr stdout csvkmd users CourseStudent.csv keyfield Student datafield Course create classroominvitation role student course csvdata Course
```
This command will invite all students to their courses in parallel
```
gam redirect stdout ./Invites.out multiprocess redirect stderr stdout multiprocess csv CourseStudent.csv gam user ~Student create classroominvitation role student course ~Course
```
## Accept classroom invitations
Accept classroom invitations for users. You can only invite a co-teacher to be an owner of a course.
```
gam <UserTypeEntity> accept classroominvitation (ids <ClassroomInvitationIDEntity>)|([courses <CourseEntity>] [role all|owner|student|teacher])
```
By default, all invitations for the specified users will be accepted.
Select specific invitations to accept:
* `ids <ClassroomInvitationIDEntity>` - Specify invitation IDs
Select courses and accept invitations for those courses.
* `courses <CourseEntity>` - Specify courses
By default, invitations for all roles will be accepted; you can limit the acceptances to invitations of a specific role.
## Delete classroom invitations
Delete classroom invitations for users.
```
gam <UserTypeEntity> delete classroominvitation (ids <ClassroomInvitationIDEntity>)|([courses <CourseEntity>] [role all|owner|student|teacher])
```
By default, all invitations for the specified users will be deleted.
Select specific invitations to delete:
* `ids <ClassroomInvitationIDEntity>` - Specify invitation IDs
Select courses and delete invitations for those courses.
* `courses <CourseEntity>` - Specify courses
By default, invitations for all roles will be deleted; you can limit the deletions to invitations of a specific role.
## Display classroom invitations by user
Display classroom invitations for users.
```
gam <UserTypeEntity> show classroominvitations [role all|owner|student|teacher]
[formatjson]
gam <UserTypeEntity> print classroominvitations [todrive <ToDriveAttributes>*] [role all|owner|student|teacher]
[formatjson [quotechar <Character>]]
```
By default, invitations for all roles will be displayed; you can limit the display to invitations of a specific role.
## Display classroom invitations by course
```
gam show classroominvitations (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] [states <CourseStateList>])
[role all|owner|student|teacher] [formatjson]
gam print classroominvitations [todrive <ToDriveAttributes>*] (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] [states <CourseStateList>])
[role all|owner|student|teacher] [formatjson [quotechar <Character>]]
```
By default, classroom invitations for all courses are displayed.
To get classroom invitations for a specific set of courses, use the following option; it can be repeated to select multiple courses.
* `(course|class <CourseEntity>)*` - Display classroom invitations from the courses with the IDs specified in `<CourseEntity>`.
To get classroom invitations for courses based on their having a particular participant, use the following options. Both options can be specified.
* `teacher <UserItem>` - Display courses with the specified teacher.
* `student <UserItem>` - Display courses with the specified student.
To get classroom invitations for courses based on their state, use the following option. This option can be combined with the `teacher` and `student` options.
By default, all course states are selected.
* `states <CourseStateList>` - Display courses with any of the specified states.
By default, for `show`, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
By default, for `print`, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,131 @@
# Classroom - Membership
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Special quoting for course aliases](#special-quoting-for-course-aliases)
- [Manage membership for courses](#manage-membership-for-courses)
- [Legacy manage membership](#legacy-manage-membership)
- [Bulk membership changes](#bulk-membership-changes)
- [Display course membership](#display-course-membership)
## API documentation
* https://developers.google.com/classroom/reference/rest/
* https://developers.google.com/classroom/reference/rest/v1/courses.students
* https://developers.google.com/classroom/reference/rest/v1/courses.teachers
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
<CourseAlias> ::= <String>
<CourseID> ::= <Number>|d:<CourseAlias>
<CourseIDList> ::= "<CourseID>(,<CourseID>)*"
<CourseEntity> ::= <CourseIDList> | <FileSelector> | <CSVFileSelector | <CSVkmdSelector>
<CourseState> ::= active|archived|provisioned|declined|suspended
<CourseStateList> ::= all|"<CourseState>(,<CourseState>)*"
```
## Special quoting for course aliases
As course aliases can contain spaces, some care must be used when entering `<CourseAliasList>`, `<CourseID>`, `<CourseIDList>` and `<CourseEntity>`.
Suppose you have a course with the alias `Math Class`. To get information about it you enter the command: `gam info course "d:Math Class"`
The shell strips the `"` leaving a single argument `d:Math Class`; gam correctly processes the argument as it is expecting a single course.
Suppose you enter the command: `gam info courses "d:Math Class"`
The shell strips the `"` leaving a single argument `d:Math Class`; as gam is expecting a list, it splits the argument on space leaving two items and then tries to process `d:Math` and `Class`, not what you want.
You must enter: `gam info courses "'d:Math Class'"`
The shell strips the `"` leaving a single argument `'d:Math Class'`; as gam is expecting a list, it splits the argument on space while honoring the `'` leaving one item `d:Math Class` and correctly processes the item.
For multiple aliases you must enter: `gam info courses "'d:Math Class','d:Science Class'"`
See: [Lists and Collections](Lists-and-Collections)
## Manage membership for courses
These commands can process multiple courses and `add` and `delete` can process multiple students/teachers.
```
gam courses <CourseEntity> add teachers [makefirstteacherowner] <UserTypeEntity>
gam courses <CourseEntity> add students <UserTypeEntity>
gam courses <CourseEntity> delete|remove teachers|students <UserTypeEntity>
gam courses <CourseEntity> clear teachers|students
gam courses <CourseEntity> sync teachers [addonly|removeonly] [makefirstteacherowner] <UserTypeEntity>
gam courses <CourseEntity> sync students [addonly|removeonly] <UserTypeEntity>
```
When `makefirstteacherowner` is specified, the first/only user in `<UserTypeEntity>` will be updated to be the
owner of the Course(s).
### Clear
A `clear` operation deletes all of the members of the specified type. The owner teacher will not deleted.
### Sync
A `sync` operation gets the current roster for a course and compares it to the proposed roster.
Current/Default:
* members in the proposed roster that are not in the current roster will be added
* members in the current roster that are not in the proposed roster will deleted
When the `addonly` option is specified:
* members in the proposed roster that are not in the current roster will be added
* members in the current roster that are not in the proposed roster will not be deleted
When the `removeonly` option is specified:
* members in the proposed roster that are not in the current roster will not be added
* members in the current roster that are not in the proposed roster will be deleted
## Bulk membership changes
Suppose you have a CSV file (CourseStudents.csv) with headers: courseId,email
Each row contains a course ID and a student email address.
The following command will synchronize the membership for all courses.
```
gam redirect stdout ./CourseUpdates.txt redirect stderr stdout courses csvkmd CourseStudents.csv keyfield courseId datafield email sync students csvdata email
```
You can also do `add` and `delete` in this manner.
## Legacy manage membership
These commands are for backward compatibility; only one course can be processed and `add` and `delete` can only process a single student/teacher.
```
gam course <CourseID> add [makefirstteacherowner] teachers <UserItem>
gam course <CourseID> add students <UserItem>
gam course <CourseID> delete|remove teachers|students <UserItem>
gam course <CourseID> clear teachers|students
gam course <CourseID> sync teachers [addonly|removeonly] [makefirstteacherowner] <UserTypeEntity>
gam course <CourseID> sync students [addonly|removeonly] <UserTypeEntity>
```
When `makefirstteacherowner` is specified, the only/first user in `<UserItem>` or `<UserTypeEntity>` will be updated to be the
owner of the Course.
## Display course membership
```
gam print course-participants [todrive <ToDriveAttribute>*]
(course|class <CourseID>)*|([teacher <UserItem>] [student <UserItem>]) [states <CourseStateList>]
[show all|students|teachers] [formatjson [quotechar <Character>]]
```
By default, the `print course-participants` command displays participant information about all courses.
To get participant information for a specific set of courses, use the following option; it can be repeated to select multiple courses.
* `(course|class <CourseID>)*` - Display courses with the specified `<CourseID>`.
To get participant information for courses based on their having a particular participant, use the following options. Both options can be specified.
* `teacher <UserItem>` - Display courses with the specified teacher.
* `student <UserItem>` - Display courses with the specified student.
To get participant information for courses based on their state, use the following option. This option can be combined with the `teacher` and `student` options.
By default, all course states are selected.
* `states <CourseStateList>` - Display courses with any of the specified states.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

318
docs/Cloud-Channel.md Normal file
View File

@ -0,0 +1,318 @@
# Cloud Channel
- [API documentation](#api-documentation)
- [Notes](#notes)
- [Definitions](#definitions)
- [Display Channel Customers](#display-channel-customers)
- [Display Channel Customer Entitlements](#display-channel-customer-entitlements)
- [Display Channel Offers](#display-channel-offers)
- [Display Channel Products](#display-channel-products)
- [Display Channel SKUs](#display-channel-skus)
## API documentation
* https://cloud.google.com/channel/docs/reference/rest
* https://cloud.google.com/channel/docs/concepts/google-cloud/filter-customers
## Notes
To use these commands you must add the 'Cloud Channel API' to your project and update your client authorization.
```
gam update project
gam oauth create
```
The Customer ID value that the Cloud Channel API describes is not the Google Workspace Customer ID value; it is unique to the Cloud Channel API.
## Definitions
```
<ChannelCustomerID> ::= <String>
<ProductID> ::= <String>
<ResellerID> ::= <String>
<LanguageCode> ::=
ach|af|ag|ak|am|ar|az|be|bem|bg|bn|br|bs|ca|chr|ckb|co|crs|cs|cy|da|de|
ee|el|en|en-gb|en-us|eo|es|es-419|et|eu|fa|fi|fil|fo|fr|fr-ca|fy|
ga|gaa|gd|gl|gn|gu|ha|haw|he|hi|hr|ht|hu|hy|ia|id|ig|in|is|it|iw|ja|jw|
ka|kg|kk|km|kn|ko|kri|ku|ky|la|lg|ln|lo|loz|lt|lua|lv|
mfe|mg|mi|mk|ml|mn|mo|mr|ms|mt|my|ne|nl|nn|no|nso|ny|nyn|oc|om|or|
pa|pcm|pl|ps|pt-br|pt-pt|qu|rm|rn|ro|ru|rw|
sd|sh|si|sk|sl|sn|so|sq|sr|sr-me|st|su|sv|sw|
ta|te|tg|th|ti|tk|tl|tn|to|tr|tt|tum|tw|
ug|uk|ur|uz|vi|wo|xh|yi|yo|zh-cn|zh-hk|zh-tw|
<ChannelCustomerField> ::=
alternateemail |
channelpartnerid |
cloudidentityid |
cloudidentityinfo |
createtime |
domain |
languagecode |
name |
orgdisplayname |
orgpostaladdress |
primarycontactinfo |
updatetime
<ChannelCustomerFieldList> ::= "<ChannelCustomerField>(,<ChannelCustomerField>)*"
<ChannelCustomerEntitlementField> ::=
associationinfo |
commitmentsettings |
createtime |
name |
offer |
parameters |
provisionedservice |
provisioningstate |
purchaseorderid |
suspensionreasons |
trialsettings |
updatetime
<ChannelCustomerEntitlementFieldList> ::= "<ChannelCustomerEntitlementField>(,<ChannelCustomerEntitlementField>)*"
```
```
<ChannelCustomerOfferField> ::=
constraints |
endtime |
marketinginfo |
name |
parameterdefinitions |
plan |
pricebyresources |
sku |
starttime
<ChannelOfferFieldList> ::= "<ChannelOfferField>(,<ChannelOfferField>)*"
<ChannelProductField> ::=
marketinginfo |
name
<ChannelProductFieldList> ::= "<ChannelProductField>(,<ChannelProductField>)*"
<ChannelSKUField> ::=
marketinginfo |
name |
product
<ChannelSKUFieldList> ::= "<ChannelSKUField>(,<ChannelSKUField>)*"
```
## Display Channel Customers
```
gam show channelcustomers
[resellerid <ResellerID>] [filter <String>]
[fields <ChannelCustomerFieldList>]
[maxresults <Number>]
[formatjson]
```
If `resellerId <ResellerID>` is omitted, the `reseller_id` value from `gam.cfg` is used.
Cloud Channel API documentation for `filter <String>`:
* https://cloud.google.com/channel/docs/concepts/google-cloud/filter-customers
The filters will contain `"`, you must quote `<String>` as follows:
* Linux and MacOS
* Surround `<String>` with single quotes `'`
* Embedded `"` in `<String>` are entered as is
* Example: `gam show channelcustomers filter 'cloud_identity_id="someid"'`
* Windows Command Prompt
* Surround `<String>` with double quotes `"`
* Embedded `"` in `<String>` are entered as `\"`
* Example: `gam show channelcustomers filter "cloud_identity_id=\"someid\""`
* Windows PowerShell
* Surround `<String>` with single quotes `'`
* Embedded `"` in `<String>` are entered as `\"`
* Example: `gam show channelcustomers filter "cloud_identity_id=\"someid\""`
When retrieving lists of customers from Cloud Channel API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many customers to retrieve in each API call; default is 50, the maximum.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print channelcustomers [todrive <ToDriveAttribute>*]
[resellerid <ResellerID>] [filter <String>]
[fields <ChannelCustomerFieldList>]
[maxresults <Number>]
[formatjson [quotechar <Character>]]
```
If `resellerId <ResellerID>` is omitted, the `reseller_id` value from `gam.cfg` is used.
Cloud Channel API documentation for `filter <String>`:
* https://cloud.google.com/channel/docs/concepts/google-cloud/filter-customers
The filters will contain `"`, you must quote `<String>` as follows:
* Linux and MacOS
* Surround `<String>` with single quotes `'`
* Embedded `"` in `<String>` are entered as is
* Windows Command Prompt
* Surround `<String>` with double quotes `"`
* Embedded `"` in `<String>` are entered as `\"`
* Windows PowerShell
* Surround `<String>` with single quotes `'`
* Embedded `"` in `<String>` are entered as `\"`
When retrieving lists of customers from Cloud Channel API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many customers to retrieve in each API call; default is 50, the maximum.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Channel Customer Entitlements
```
gam show channelcustomerentitlements
([resellerid <ResellerID>] [customerid <ChannelCustomerID>])|
(name accounts/<ResellerID>/customers/<ChannelCustomerID>)
[fields <ChannelCustomerEntitlementsFieldList>]
[maxresults <Number>]
[formatjson]
```
If `name accounts/<ResellerID>/customers/<ChannelCustomerID>` is specified, `resellerId <ResellerID>` and `customerid <ChannelCustomerID>`
are ignored.
If `resellerId <ResellerID>` is omitted, the `reseller_id` value from `gam.cfg` is used.
If `customerid <ChannelCustomerID>` is omitted, the `channel_customer_id` value from `gam.cfg` is used.
When retrieving lists of customer entitlements from Cloud Channel API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many customer entitlements to retrieve in each API call; default is 100, the maximum.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print channelcustomerentitlements [todrive <ToDriveAttribute>*]
([resellerid <ResellerID>] [customerid <ChannelCustomerID>])|
(name accounts/<ResellerID>/customers/<ChannelCustomerID>)
[fields <ChannelCustomerEntitlementsFieldList>]
[maxresults <Number>]
[formatjson [quotechar <Character>]]
```
If `name accounts/<ResellerID>/customers/<ChannelCustomerID>` is specified, `resellerId <ResellerID>` and `customerid <ChannelCustomerID>`
are ignored.
If `resellerId <ResellerID>` is omitted, the `reseller_id` value from `gam.cfg` is used.
If `customerid <ChannelCustomerID>` is omitted, the `channel_customer_id` value from `gam.cfg` is used.
When retrieving lists of customer entitlements from Cloud Channel API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many customer entitlements to retrieve in each API call; default is 100, the maximum.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Channel Offers
```
gam show channeloffers
[resellerid <ResellerID>] [filter <String>] [language <LanguageCode>]
[fields <ChannelOfferFieldList>]
[maxresults <Number>]
[formatjson]
```
If `resellerId <ResellerID>` is omitted, the `reseller_id` value from `gam.cfg` is used.
Cloud Channel API documentation for `filter <String>`:
```
The expression to filter results by name (name of the Offer), sku.name (name of the SKU), or sku.product.name (name of the Product).
* Example 1: sku.product.name=products/p1 AND sku.name!=products/p1/skus/s1
* Example 2: name=accounts/a1/offers/o1
```
When retrieving lists of offers from Cloud Channel API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many offers to retrieve in each API call; default is 1000, the maximum.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print channeloffers [todrive <ToDriveAttribute>*]
[resellerid <ResellerID>] [filter <String>] [language <LanguageCode>]
[fields <ChannelOfferFieldList>]
[maxresults <Number>]
[formatjson [quotechar <Character>]]
```
If `resellerId <ResellerID>` is omitted, the `reseller_id` value from `gam.cfg` is used.
Cloud Channel API documentation for `filter <String>`:
```
The expression to filter results by name (name of the Offer), sku.name (name of the SKU), or sku.product.name (name of the Product).
* Example 1: sku.product.name=products/p1 AND sku.name!=products/p1/skus/s1
* Example 2: name=accounts/a1/offers/o1
```
When retrieving lists of offers from Cloud Channel API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many offers to retrieve in each API call; default is 1000, the maximum.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Channel Products
```
gam show channelproducts
[resellerid <ResellerID>] [language <LanguageCode>]
[fields <ChannelProductFieldList>]
[maxresults <Number>]
[formatjson]
```
If `resellerId <ResellerID>` is omitted, the `reseller_id` value from `gam.cfg` is used.
When retrieving lists of products from Cloud Channel API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many products to retrieve in each API call; default is 1000, the maximum.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print channelproducts [todrive <ToDriveAttribute>*]
[resellerid <ResellerID>] [language <LanguageCode>]
[fields <ChannelProductFieldList>]
[maxresults <Number>]
[formatjson [quotechar <Character>]]
```
If `resellerId <ResellerID>` is omitted, the `reseller_id` value from `gam.cfg` is used.
When retrieving lists of products from Cloud Channel API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many products to retrieve in each API call; default is 1000, the maximum.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Channel SKUs
```
gam show channelskus
[resellerid <ResellerID>] [language <LanguageCode>] [productid <ProductID>]
[fields <ChannelSKUFieldList>]
[maxresults <Number>]
[formatjson]
```
If `resellerId <ResellerID>` is omitted, the `reseller_id` value from `gam.cfg` is used.
If `productid <ProductID>` is omitted, SKUs for all products are displayed.
When retrieving lists of SKUs from Cloud Channel API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many SKUs to retrieve in each API call; default is 1000, the maximum.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print channelskus [todrive <ToDriveAttribute>*]
[resellerid <ResellerID>] [language <LanguageCode>] [productid <ProductID>]
[fields <ChannelSKUFieldList>]
[maxresults <Number>]
[formatjson [quotechar <Character>]]
```
If `resellerId <ResellerID>` is omitted, the `reseller_id` value from `gam.cfg` is used.
If `productid <ProductID>` is omitted, SKUs for all products are displayed.
When retrieving lists of SKUs from Cloud Channel API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many SKUs to retrieve in each API call; default is 1000, the maximum.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,302 @@
# Cloud Identity Devices
- [API documentation](#api-documentation)
- [Query documentation](#query-documentation)
- [Definitions](#definitions)
- [Create a company device](#create-a-company-device)
- [Delete devices](#delete-devices)
- [Wipe devices](#wipe-devices)
- [Perform device actions](#perform-device-actions)
- [Synchronize devices](#synchronize-devices)
- [Display devices](#display-devices)
- [Print devices](#print-devices)
- [Approve or block device users](#approve-or-block-device-users)
- [Delete device users](#delete-device-users)
- [Wipe device users](#wipe-device-users)
- [Perform device user actions](#perform-device-user-actions)
- [Display device users](#display-device-users)
- [Print device users](#print-device-users)
- [Display device user client state](#display-device-user-client-state)
- [Update device user client state](#update-device-user-client-state)
## API documentation
* https://cloud.google.com/identity/docs/reference/rest/v1/devices
* https://cloud.google.com/identity/docs/reference/rest/v1/devices.deviceUsers
* https://cloud.google.com/identity/docs/reference/rest/v1/devices.deviceUsers.clientStates
* https://cloud.google.com/endpoint-verification/docs/overview
## Query documentation
* https://developers.google.com/admin-sdk/directory/v1/search-operators
* https://support.google.com/a/answer/7549103
## Definitions
```
<AssetTag> ::= <String>
<AssetTagList> ::= "<AssetTag>(,<AssetTag>)*"
<QueryDevice> ::= <String>
See: https://support.google.com/a/answer/7549103
<QueryDeviceList> ::= "<QueryDevice>(,<QueryDevice>)*"
<DeviceID> ::= devices/<String>
<DeviceEntity> ::=
<DeviceIDList> |
(query:<QueryDevice>)|(query <QueryDevice>)
<DeviceType> ::= android|chrome_os|google_sync|linux|mac_os|windows
<DeviceUserID> ::= devices/<String>/deviceUsers/<String>
<DeviceUserEntity> ::=
<DeviceUserIDList> |
(query:<QueryDevice>)|(query <QueryDevice>)
<DeviceFieldName> ::=
androidspecificattributes|
assettag|
basebandversion|
bootloaderversion|
brand|
buildnumber|
compromisedstate|
createtime|
devicetype|
enableddeveloperoptions|
enabledusbdebugging|
endpointverificationspecificattributes|
encryptionstate|
imei|
kernelversion|
lastsynctime|
managementstate|
manufacturer|
meid|
model|
name|
networkoperator|
osversion|
otheraccounts|
ownertype|
releaseversion|
securitypatchtime|
serialnumber|
wifimacaddresses
<DeviceFieldNameList> ::= "<DeviceFieldName>(,<DeviceFieldName>)*"
<DeviceAction> ::=
cancelwipe|
wipe
<DeviceUserFieldName> ::=
compromisedstate|
createtime|
firstsynctime|
languagecode|
lastsynctime|
managementstate|
name|
passwordstate|
useragent|
useremail
<DeviceUserFieldNameList> ::= "<DeviceUserFieldName>(,<DeviceUserFieldName>)*"
<DeviceOrderbyFieldName> ::=
createtime|devicetype|lastsynctime|model|osversion|serialnumber
<DeviceUserAction> ::=
approve|
block|
cancelwipe|
wipe
```
## Create a company device
Adds a new device to the Google company-owned inventory. Once a user is assigned and enrolled on the device the device will be considered company-owned for management purposes.
The device will also register as company-owned with Google services like [Context-Aware Access (CAA)](https://support.google.com/a/answer/9275380).
```
gam create device serialnumber <String> devicetype <DeviceType> [assettag <String>]
```
Arguments `serialnumber <String>` and `devicetype <DeviceType>` are required; you can optionally specify `assettag <String>`.
## Delete devices
Delete a device from appearing in the Admin console, stop syncing for the device user.
No user data should be removed.
```
gam delete device <DeviceEntity> [doit]
```
If `<DeviceEntity>` uses a query, the `doit` option must be used to enable execution.
## Wipe devices
Wiping a device performs a factory reset, all device data is removed.
```
gam cancelwipe device <DeviceEntity> [doit]
gam wipe device <DeviceEntity> [removeresetlock] [doit]
```
If `<DeviceEntity>` uses a query, the `doit` option must be used to enable execution.
Specifying `removeresetlock` will remove the account lock on the Android or iOS device.
This lock is enabled by default and requires the existing device user to log in after the wipe in order to unlock the device.
* See: https://support.google.com/android/answer/9459346
## Perform device actions
This is an alternative form of the above commands
```
gam update device <DeviceEntity> action <DeviceAction> [removeresetlock] [doit]
```
If `<DeviceEntity>` uses a query, the `doit` option must be used to enable execution.
Specifying `removeresetlock` when `<DeviceAction>` is `wipe` will remove the account lock on the Android or iOS device.
This lock is enabled by default and requires the existing device user to log in after the wipe in order to unlock the device.
* See: https://support.google.com/android/answer/9459346
## Synchronize devices
This command generates a list of your current company devices, either a complete list
or a subset based on a query. A CSV file is read to generate another list of devices.
At a minimum, two values are required for devices in the CSV file list; a device type and a serial number.
For the device type, you can either specify a static device type or specify the column in the CSV file that contains a device type.
* `static_devicetype <DeviceType>` - A fixed device type
* `devicetype_column <String>` - The name of the column containing device types; if not specified, `deviceType` is used
For the serial number, you must specify the column in the CSV file that contains a serial number.
* `serialnumber_column <String>` - The name of the column containing serial numbers; if not specified, `serialNumber` is used
You can optionally specify the column in the CSV file that contains an asset tag.
* `assettag_column <String>` - The name of the column containing asset tags; the typical value is `assetTag`
These two/three columns are used to match current company devices against the CSV file devices.
* Devices in the CSV device list will be created if they are not the the current company device list.
* Devices in the current company device list that are not in the CSV device list will have an optional operation performed on them.
* `unassigned_missing_action delete|wipe|none` - Perform this operation if the company device has never been assigned; default action is `delete`
* `assigned_missing_action delete|wipe|none` - Perform this operation if the company device has been assigned; default action is `none`
If `preview` is specified, the operations that would be performed are previewed but are not performed; use this to test.
```
gam sync devices
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
csvfile <FileName>
(devicetype_column <String>)|(static_devicetype <DeviceType>)
(serialnumber_column <String>)
[assettag_column <String>]
[unassigned_missing_action delete|wipe|none]
[assigned_missing_action delete|wipe|none]
[preview]
```
## Display devices
```
gam info device <DeviceEntity>
<DeviceFieldName>* [fields <DeviceFieldNameList>] [userfields <DeviceUserFieldNameList>]
[nodeviceusers]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
## Print devices
```
gam print devices [todrive <ToDriveAttribute>*]
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
<DeviceFieldName>* [fields <DeviceFieldNameList>] [userfields <DeviceUserFieldNameList>]
[orderby <DeviceOrderByFieldName> [ascending|descending]]
[all|company|personal|nocompanydevices|nopersonaldevices]
[nodeviceusers]
[formatjson [quotechar <Character>]]
```
By default, all devices are displayed; use the query options to limit the display.
To AND query terms, put all of your terms in one query:
```
gam print devices query "manufacturer:Meizu os:Android 7.0.0"
```
To OR query terms, put the terms im multiple queries:
```
gam print devices queries "'model:iPhone 6','model:samsung'"
```
Select the view of devices to display:
* `all` - Company and personal devices; this is the default
* `company|nopersonaldevices` - Company devices
* `personal|nocompanydevices` - Personal devices
By default, Gam makes additional API calls to display the device users for the devices;
use `nodeviceuser` to suppress making the additional calls.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Approve or block device users
Approve or block user profiles on a device.
```
gam approve deviceuser <DeviceUserEntity> [doit]
gam block deviceuser <DeviceUserEntity> [doit]
```
If `<DeviceUserEntity>` uses a query, the `doit` option must be used to enable execution.
## Delete device users
Delete a device user from appearing in the Admin console, stop syncing for the device user.
No user data should be removed.
```
gam delete deviceuser <DeviceUserEntity> [doit]
```
If `<DeviceUserEntity>` uses a query, the `doit` option must be used to enable execution.
## Wipe device users
Wipe a device user profile from a device.
In the case of Android for Work, the work profile will be removed but the personal profile left alone.
```
gam wipe deviceuser <DeviceUserEntity> [doit]
gam cancelwipe deviceuser <DeviceUserEntity> [doit]
```
If `<DeviceUserEntity>` uses a query, the `doit` option must be used to enable execution.
## Perform device user actions
This is an alternative form of the above commands.
```
gam update deviceuser <DeviceUserEntity> action <DeviceUserAction> [doit]
```
If `<DeviceUserEntity>` uses a query, the `doit` option must be used to enable execution.
## Display device users
```
gam info deviceuser <DeviceUserEntity>
<DeviceUserFieldName>* [fields <DeviceUserFieldNameList>]
[formatjson]
```
## Print device users
```
gam print deviceusers [todrive <ToDriveAttribute>*]
[select <DeviceID>]
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
<DeviceUserFieldName>* [fields <DeviceUserFieldNameList>]
[orderby <DeviceOrderByFieldName> [ascending|descending]]
[formatjson [quotechar <Character>]]
```
By default, Gam displays device users for all devices;
* `select <DeviceID>` - Display users for a specific device
* `(query <QueryDevice>)|(queries <QueryDeviceList>)` - Display users that match queries.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display device user client state
```
gam info deviceuserstate <DeviceUserEntity> [clientid <String>]
```
## Update device user client state
The API that supports this command is in beta mode. In particular, setting `assettags` and `customvalues`
works if you set the values once; each additional time you set values they are added to the existing values
and they is no way at the moment to clear values.
```
gam update deviceuserstate <DeviceUserEntity> [clientid <String>]
[customid <String>] [assettags clear|<AssetTagList>]
[compliantstate|compliancestate compliant|noncompliant] [managedstate clear|managed|unmanaged]
[healthscore very_poor|poor|neutral|good|very_good] [scorereason clear|<String>]
(customvalue (bool|boolean <Boolean>)|(number <Integer>)|(string <String>))*
```

View File

@ -0,0 +1,480 @@
# Cloud Identity Groups - Membership
- [API documentation](#api-documentation)
- [Query documentation](#query-documentation)
- [Cloud Identity Group Documentation](#cloud-identity-group-documentation)
- [Security Group Documentation](#security-group-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [Notes](#Notes)
- [Collections of Users](#collections-of-users)
- [Add members to a group](#add-members-to-a-group)
- [Delete members from a group](#delete-members-from-a-group)
- [Synchronize members in a group](#synchronize-members-in-a-group)
- [Delete members from a group by role](#delete-members-from-a-group-by-role)
- [Update member roles and expiration time](#update-member-roles-and-expiration-time)
- [Bulk membership changes](#bulk-membership-changes)
- [Display user group member options](#display-user-group-member-options)
- [Display group membership in CSV format](#display-group-membership-in-csv-format)
- [Display group membership in hierarchical format](#display-group-membership-in-hierarchical-format)
## API documentation
* https://cloud.google.com/identity/docs/groups
* https://cloud.google.com/identity/docs/reference/rest/v1/groups
* https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships
## Query documentation
* https://cloud.google.com/identity/docs/reference/rest/v1/groups#dynamicgroupquery
## Cloud Identity Group Documentation
* https://gsuiteupdates.googleblog.com/2020/08/new-api-cloud-identity-groups-google.html
## Security Group Documentation
* https://gsuiteupdates.googleblog.com/2020/09/security-groups-beta.html
## Notes
In the Admin Directory API a group has the following characteristics:
* `id` - The unique ID of a group
* `email` - The group's email address
* `name` - The group's display name
In the Cloud Indentity Groups API a group has the following characteristics:
* `name` - The unique ID of a group
* `groupKey.id` - The group's email address
* `displayName` - The group's display name
The Admin Directory API group characteristic names will be used.
Dynamic Groups require Cloud Identity Premium accounts.
* https://cloud.google.com/identity/docs/how-to/create-dynamic-groups
The `cimember <UserItem>` option of `gam print|show cigroup-members` requires a Google Workspace Enterprise Standard, Enterprise Plus, and Enterprise for Education;
and Cloud Identity Premium accounts. Unfortunately, even if you have the required account, the API call that supports the query doesn't work.
* https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/searchTransitiveGroups
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<UniqueID> ::= id:<String>
<GroupItem> ::= <EmailAddress>|<UniqueID>|groups/<String>
<GroupList> ::= "<GroupItem>(,<GroupItem>)*"
<GroupEntity> ::= <GroupList>|<FileSelector>|<CSVkmdSelector>|<CSVDataSelector>
<GroupRole> ::= owner|manager|member
<GroupRoleList> ::= "<GroupRole>(,<GroupRole>)*"
<CIGroupType> ::= customer|group|other|serviceaccount|user
<CIGroupTypeList> ::= "<CIGroupType>(,<CIGroupType>)*"
<CIGroupMembersFieldName> ::=
createtime
expiretime|
memberkey|
name|
preferredmemberkey|
role|
type|
updatetime|
useremail
<CIGroupMembersFieldNameList> ::= "<CIGroupMembersFieldName>(,<CIGroupMembersFieldName>)*"
```
## Collections of Users
Group membership commands involve specifying collections of users;
for `<UserTypeEntity>`, see: [Collections of Users](Collections-of-Users)
## Add members to a group
```
gam update cigroups <GroupEntity> create|add [<GroupRole>]
[usersonly|groupsonly]
[notsuspended|suspended] [notarchived|archived]
[expire|expires <Time>] [preview] [actioncsv]
<UserTypeEntity>
```
When `<UserTypeEntity>` specifies a group or groups:
* `usersonly` - Only the user members from the specified groups are added
* `groupsonly` - Only the group members from the specified groups are added
By default, when adding members from organization units, all users, whether suspended or not, are included.
* `notsuspended` - Do not include suspended users, this is common
* `suspended` - Only include suspended users, this is not common but allows creating groups that allow easy identification of suspended users
By default, when adding members from groups, all users, whether suspended/archived or not, are included.
* `notsuspended` - Do not include suspended users, this is common
* `suspended` - Only include suspended users, this is not common but allows creating groups that allow easy identification of suspended users
* `notarchived` - Do not include archived users
* `archived` - Only include archived users, this is not common but allows creating groups that allow easy identification of archived users
* `notsuspended notarchived` - Do not include suspended and archived users
* `suspended archived` - Include only suspended or archived users
* `notsuspended archived` - Only include archived users, this is not common but allows creating groups that allow easy identification of archived users
* `suspended notarchived` - Only include suspended users, this is not common but allows creating groups that allow easy identification of suspended users
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `group,email,role,action,message` is generated
that shows the actions performed when updating the group.
### `actioncsv` Example
Using `actioncsv` produces a CSV file showing the actions taken.
```
$ gam redirect csv AddUpdates.csv update cigroup testgroup add members actioncsv users testuser2,testuser3
Group: testgroup@domain.com, Add 2 Members
Group: testgroup@domain.com, Member: testuser2@domain.com, Added: Role: MEMBER (1/2)
Group: testgroup@domain.com, Member: testuser3@domain.com, Add Failed: Member already exists. (2/2)
$ more AddUpdates.csv
group,email,role,action,message
testgroup@domain.com,testuser2@domain.com,MEMBER,Added,Success
testgroup@domain.com,testuser3@domain.com,MEMBER,Add Failed,Member already exists.
```
## Delete members from a group
```
gam update cigroups <GroupEntity> delete|remove [<GroupRole>]
[usersonly|groupsonly]
[notsuspended|suspended] [notarchived|archived]
[preview] [actioncsv]
<UserTypeEntity>
```
`<GroupRole>` is ignored, deletions take place regardless of role.
When `<UserTypeEntity>` specifies a group or groups:
* `usersonly` - Only the user members from the specified groups are deleted
* `groupsonly` - Only the group members from the specified groups are deleted
By default, when deleting members from organization units, all users, whether suspended or not, are included.
* `notsuspended` - Do not include suspended users, this is common
* `suspended` - Only include suspended users, this is not common but allows creating groups that allow easy identification of suspended users
By default, when deleting members from groups, all users, whether suspended/archived or not, are included.
* `notsuspended` - Do not include suspended users, this is common
* `suspended` - Only include suspended users, this is not common but allows creating groups that allow easy identification of suspended users
* `notarchived` - Do not include archived users
* `archived` - Only include archived users, this is not common but allows creating groups that allow easy identification of archived users
* `notsuspended notarchived` - Do not include suspended and archived users
* `suspended archived` - Include only suspended or archived users
* `notsuspended archived` - Only include archived users, this is not common but allows creating groups that allow easy identification of archived users
* `suspended notarchived` - Only include suspended users, this is not common but allows creating groups that allow easy identification of suspended users
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `group,email,role,action,message` is generated
that shows the actions performed when updating the group.
### `actioncsv` Example
Using `actioncsv` produces a CSV file showing the actions taken.
```
$ gam redirect csv DeleteUpdates.csv update cigroup testgroup delete members actioncsv users testuser2,testuser4
Group: testgroup@domain.com, Remove 2 Members
Group: testgroup@domain.com, Member: testuser2@domain.com, Removed: Role: MEMBER (1/2)
Group: testgroup@domain.com, Member: testuser4@domain.com, Remove Failed: Does not exist (2/2)
$ more DeleteUpdates.csv
group,email,role,action,message
testgroup@domain.com,testuser2@domain.com,MEMBER,Removed,Success
testgroup@domain.com,testuser4@domain.com,MEMBER,Remove Failed,Does not exist
```
## Synchronize members in a group
A synchronize operation gets the current membership for a group and does adds and deletes as necessary to make it match `<UserTypeEntity>`.
```
gam update cigroups <GroupEntity> sync [<GroupRole>]
[usersonly|groupsonly] [addonly|removeonly]
[notsuspended|suspended] [notarchived|archived]
[expire|expires <Time>] [preview] [actioncsv]
<UserTypeEntity>
```
If `<GroupRole>` is not specified, `member` is assumed.
When `<UserTypeEntity>` specifies a group or groups:
* `usersonly` - Only the user members from the specified groups are added/deleted
* `groupsonly` - Only the group members from the specified groups are added/deleted
By default, when synchronizing members from organization units, all users, whether suspended or not, are included.
* `notsuspended` - Do not include suspended users, this is common
* `suspended` - Only include suspended users, this is not common but allows creating groups that allow easy identification of suspended users
By default, when synchronizing members from groups, all users, whether suspended/archived or not, are included.
* `notsuspended` - Do not include suspended users, this is common
* `suspended` - Only include suspended users, this is not common but allows creating groups that allow easy identification of suspended users
* `notarchived` - Do not include archived users
* `archived` - Only include archived users, this is not common but allows creating groups that allow easy identification of archived users
* `notsuspended notarchived` - Do not include suspended and archived users
* `suspended archived` - Include only suspended or archived users
* `notsuspended archived` - Only include archived users, this is not common but allows creating groups that allow easy identification of archived users
* `suspended notarchived` - Only include suspended users, this is not common but allows creating groups that allow easy identification of suspended users
Default:
* members in `<UserTypeEntity>` that are not in the current membership will be added
* members in the current membership that are not in `<UserTypeEntity>` will deleted
When the `addonly` option is specified:
* members in `<UserTypeEntity>` that are not in the current membership will be added
* members in the current membership that are not in `<UserTypeEntity>` will not be deleted
When the `removeonly` option is specified:
* members in `<UserTypeEntity>` that are not in the current membership will not be added
* members in the current membership that are not in `<UserTypeEntity>` will be deleted
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `group,email,role,action,message` is generated
that shows the actions performed when updating the group.
### Examples using CSV file and Google sheets:
* https://github.com/taers232c/GAMADV-XTD3/wiki/Collections-of-Users#examples-using-csv-files-and-google-sheets-to-update-the-membership-of-a-group
### Example
Assume that at your school there is a group for each grade level and the members come from an OU; here is a sample CSV file GradeOU.csv
```
Grade,OU
seniors@domain.org,/Students/ClassOf2018
juniors@domain.org,/Students/ClassOf2019
...
```
This allows you to do: `gam csv GradeOU.csv gam update cigroup ~Grade sync members ou ~OU`
But suppose that at each grade level there are additional group members that are groups of faculty/staff; e.g., senioradvisors@domain.org.
In this scenario, you can't do the `update cigroup sync` command as the members that are groups will be deleted; the `usersonly` option allows
the `update cigroup sync` command to work: `gam csv GradeOU.csv gam update cigroup ~Grade sync members usersonly ou ~OU`
The users from the OU are matched against the user members of the group and adds/deletes are done as necessary to synchronize them;
the group members of the group are unaffected.
### `actioncsv` Example
Using `actioncsv` produces a CSV file showing the actions taken.
```
$ gam redirect csv SyncUpdates.csv update cigroup testgroup sync members actioncsv users testuser1,testuser3,testuser4
Getting all Members for testgroup@domain.com, may take some time on a large Group...
Got 3 Members for testgroup@domain.com...
Group: testgroup@domain.com, Remove 1 Member
Group: testgroup@domain.com, Member: testuser2@domain.com, Removed: Role: MEMBER
Group: testgroup@domain.com, Add 1 Member
Group: testgroup@domain.com, Member: testuser4@domain.com, Added: Role: MEMBER
$ more SyncUpdates.csv
group,email,role,action,message
testgroup@domain.com,testuser2@domain.com,MEMBER,Removed,Success
testgroup@domain.com,testuser4@domain.com,MEMBER,Added,Success
```
## Delete members from a group by role
```
gam update cigroups <GroupEntity> clear [member] [manager] [owner]
[usersonly|groupsonly]
[emailclearpattern|emailretainpattern <RegularExpression>]
[preview] [actioncsv]
```
If none of `member`, `manager`, or `owner` are specified, `member` is assumed.
By default, when clearing members from a group, all members, whether users or groups, are included.
* `usersonly` - Clear only the user members
* `groupsonly` - Clear only the group members
Members that have met the above qualifications to be cleared can be further qualifed by their email address.
* `emailclearpattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be cleared; others will be retained
* `emailretainpattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be retained; others will be cleared
If `preview` is specified, the deletes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `group,email,role,action,message` is generated
that shows the actions performed when updating the group.
## Update member roles and expiration time
```
gam update cigroups <GroupEntity> update [<GroupRole>]
[usersonly|groupsonly]
[notsuspended|suspended] [notarchived|archived]
[expire|expires <Time>] [preview] [actioncsv]
<UserTypeEntity>
```
There are two items that can be updated: role and expiration time. If neither option is specified,
the users are updated to members; this is the behavior from previous versions. Otherwise,
only the specified items are updated.
When `<UserTypeEntity>` specifies a group or groups:
* `usersonly` - Only the user members from the specified groups are added
* `groupsonly` - Only the group members from the specified groups are added
By default, when updating members from organization units, all users, whether suspended or not, are included.
* `notsuspended` - Do not include suspended users
* `suspended` - Only include suspended users
By default, when updating members from groups, all users, whether suspended/archived or not, are included.
* `notsuspended` - Do not include suspended users
* `suspended` - Only include suspended users
* `notarchived` - Do not include archived users
* `archived` - Only include archived users
* `notsuspended notarchived` - Do not include suspended and archived users
* `suspended archived` - Include only suspended or archived users
* `notsuspended archived` - Only include archived users
* `suspended notarchived` - Only include suspended users
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `group,email,role,action,message` is generated
that shows the actions performed when updating the group.
## Bulk membership changes
Suppose you have a CSV file (GroupMembers.csv) with headers: group,role,email
Each row contains a group email address, member role (OWNER, MEMBER, MANAGER) and a member email address.
The following command will synchronize the membership for all groups and roles.
```
gam redirect stdout ./MemberUpdates.txt redirect stderr stdout update cigroup csvkmd GroupMembers.csv keyfield group subkeyfield role datafield email sync csvdata email
```
You can also do `create|add`, `delete` and `update` in this manner.
If you want to update a specific role, you can do one of the following.
```
gam redirect stdout ./MemberUpdates.txt redirect stderr stdout update cigroup csvkmd ./GroupMembers.csv keyfield group matchfield role MEMBER datafield email sync member csvdata email
gam redirect stdout ./ManagerUpdates.txt redirect stderr stdout update cigroup csvkmd ./GroupMembers.csv keyfield group matchfield role MANAGER datafield email sync manager csvdata email
gam redirect stdout ./OwnerUpdates.txt redirect stderr stdout update cigroup csvkmd ./GroupMembers.csv keyfield group matchfield role OWNER datafield email sync owner csvdata email
```
## Display user group member options
Display user's group membership information.
```
gam <UserTypeEntity> info cimember <GroupEntity>
gam info cimember <UserTypeEntity> <GroupEntity>
```
## Display group membership in CSV format
```
gam print cigroup-members [todrive <ToDriveAttribute>*]
[(cimember|showownedby <UserItem>)|(cigroup <GroupItem>)|(select <GroupEntity>)]
[emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
[descriptionmatchpattern [not] <RegularExpression>]
[roles <GroupRoleList>] [members] [managers] [owners]
[types <CIGroupTypeList>]
<CIGroupMembersFieldName>* [fields <CIGroupMembersFieldNameList>]
[(recursive [noduplicates])||includederivedmembership] [nogroupeemail]
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
```
By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups:
* `cimember <UserItem>` - Limit display to groups that contain `<UserItem>` as a member
* `showownedby <UserItem>` - Limit display to groups owned by `<UserItem>`
* `cigroup <GroupItem>` - Limit display to the single group `<GroupItem>`
* `select <GroupEntity>` - Limit display to the groups specified in `<GroupEntity>`
These options further limit the list of groups selected above:
* `emailmatchpattern <RegularExpression>` - Limit display to groups whose email address matches `<RegularExpression>`
* `emailmatchpattern not <RegularExpression>` - Limit display to groups whose email address does not match `<RegularExpression>`
* `namematchpattern <RegularExpression>` - Limit display to groups whose name matches `<RegularExpression>`
* `namematchpattern not <RegularExpression>` - Limit display to groups whose name does not match `<RegularExpression>`
* `descriptionmatchpattern <RegularExpression>` - Limit display to groups whose description matches `<RegularExpression>`
* `descriptionmatchpattern not <RegularExpression>` - Limit display to groups whose description does not match `<RegularExpression>`
By default, all members, managers and owners in the group are displayed; these options modify that behavior:
* `roles <GroupRoleList>` - Display specified roles
* `members` - Display members
* `managers` - Display managers
* `owners` - Display owners
By default, all types of members (customer, group, serviceaccoun, user) in the group are displayed; when `recursive` is specified,
the default is to only display type user members. This option modifies those behaviors:
* `types <CIGroupTypeList>` - Display specified types
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
By default, the ID, role, email address, type, createTime, updateTime and expireTime of each member is displayed along with the group email address;
these options specify which fields to display:
* `<CIGroupMembersFieldName>*` - Individual field names
* `fields <CIGroupMembersFieldNameList>` - A comma separated list of field names
By default, the group email address is always shown, you can suppress it with the `nogroupemail` option.
By default, members that are groups are displayed as a single entry of type GROUP; this option recursively expands group members to display their user members.
* `recursive` - Recursively expand group members
The `recursive` option does not expand or display members of type CUSTOMER.
The `recursive` option adds two columns, level and subgroup, to the output:
* `level` - At what level of the expansion does the user appear; level 0 is the top level
* `subgroup` - The group that contained the user
Displaying membership of multiple groups or recursive expansion may result in multiple instances of the same user being displayed; these multiple instances can be reduced to one entry.
* `noduplicates` - Reduce multiple instances of the same user to the first instance
The `includederivedmembership` option is an alternative to `recursive`; it causes the API to expand type GROUP
members to display their constituent members. The role displayed for a user is the highest role it
has in any constituent group, it is not necessarily its role in the top group.
The options `recursive noduplicates` and `includederivedmembership types user` return the same list of users.
The `includederivedmembership` option makes less API calls but doesn't show level and subgroup information.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display group membership in hierarchical format
```
gam show cigroup-members
[(cimember|showownedby <UserItem>)|(cigroup <GroupItem>)|(select <GroupEntity>)]
[emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
[descriptionmatchpattern [not] <RegularExpression>]
[roles <GroupRoleList>] [members] [managers] [owners] [depth <Number>]
[types <CIGroupTypeList>]
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
[includederivedmembership]
[formatjson [quotechar <Character>]]
```
By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups:
* `cimember <UserItem>` - Limit display to groups that contain `<UserItem>` as a member
* `showownedby <UserItem>` - Limit display to groups owned by `<UserItem>`
* `cigroup <GroupItem>` - Limit display to the single group `<GroupItem>`
* `select <GroupEntity>` - Limit display to the groups specified in `<GroupEntity>`
These options further limit the list of groups selected above:
* `emailmatchpattern <RegularExpression>` - Limit display to groups whose email address matches `<RegularExpression>`
* `emailmatchpattern not <RegularExpression>` - Limit display to groups whose email address does not match `<RegularExpression>`
* `namematchpattern <RegularExpression>` - Limit display to groups whose name matches `<RegularExpression>`
* `namematchpattern not <RegularExpression>` - Limit display to groups whose name does not match `<RegularExpression>`
* `descriptionmatchpattern <RegularExpression>` - Limit display to groups whose description matches `<RegularExpression>`
* `descriptionmatchpattern not <RegularExpression>` - Limit display to groups whose description does not match `<RegularExpression>`
By default, all members, managers and owners in the group are displayed; these options modify that behavior:
* `roles <GroupRoleList>` - Display specified roles
* `members` - Display members
* `managers` - Display managers
* `owners` - Display owners
By default, all types of members (customer, group, serviceaccount, user) in the group are displayed; this option modifies that behavior:
* `types <CIGroupTypeList>` - Display specified types
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
By default, members of type GROUP are recursively expanded to show their constituent members. (Members of
type CUSTOMER are not expanded.) The `depth <Number>` argument controls the depth to which nested groups are displayed.
* `depth -1` - all groups in the selected group and below are displayed; this is the default.
* `depth 0` - the groups within a selected group are displayed, no descendants are displayed.
* `depth N` - the groups within the selected group and those groups N levels below the selected group are displayed.
The `includederivedmembership` option causes the API to expand type GROUP
members to display their constituent members. The role displayed for a user is the highest role it
has in any constituent group, it is not necessarily its role in the top group.
The options `types user` and `includederivedmembership types user` return the same list of users.
The `includederivedmembership` option makes less API calls but doesn't show hierarchy.
### Display group structure
To see a group's structure of nested groups use the `type group` option.
```
$ gam show cigroup-members group testgroup5 types group
Group: testgroup5@domain.com
MEMBER, GROUP, testgroup1@domain.com, ACTIVE
MEMBER, GROUP, testgroup2@domain.com, ACTIVE
MEMBER, GROUP, testgroup3@domain.com, ACTIVE
MEMBER, GROUP, testgroup2@domain.com, ACTIVE
MEMBER, GROUP, testgroup4@domain.com, ACTIVE
```
To show the structure of all groups you can do the following; it will be time consuming for a large number of groups.
```
gam redirect stdout ./groups.txt show group-members types group
```

View File

@ -0,0 +1,371 @@
# Cloud Identity Groups
- [API documentation](#api-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Query documentation](#query-documentation)
- [Cloud Identity Group Documentation](#cloud-identity-group-documentation)
- [Security Group Documentation](#security-group-documentation)
- [Notes](#Notes)
- [Definitions](#definitions)
- [Manage groups](#manage-groups)
- [Display information about individual groups](#display-information-about-individual-groups)
- [Display information about multiple groups](#display-information-about-multiple-groups)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/groups
* https://developers.google.com/admin-sdk/groups-settings/v1/reference/groups
* https://cloud.google.com/identity/docs/groups
* https://cloud.google.com/identity/docs/reference/rest/v1/groups
* https://support.google.com/a/answer/11192679
## Query documentation
* https://cloud.google.com/identity/docs/reference/rest/v1/groups#dynamicgroupquery
* https://cloud.google.com/identity/docs/reference/rest/v1/SecuritySettings#MemberRestriction
## Cloud Identity Group Documentation
* https://gsuiteupdates.googleblog.com/2020/08/new-api-cloud-identity-groups-google.html
## Security Group Documentation
* https://gsuiteupdates.googleblog.com/2020/09/security-groups-beta.html
## Notes
In the Admin Directory API a group has the following characteristics:
* `id` - The unique ID of a group
* `email` - The group's email address
* `name` - The group's display name
In the Cloud Indentity Groups API a group has the following characteristics:
* `name` - The unique ID of a group
* `groupKey.id` - The group's email address
* `displayName` - The group's display name
The Admin Directory API group characteristic names will be used.
Dynamic Groups require Cloud Identity Premium accounts.
* https://cloud.google.com/identity/docs/how-to/create-dynamic-groups
The `cimember <UserItem>` option of `gam print cigroups` requires a Google Workspace Enterprise Standard, Enterprise Plus, and Enterprise for Education;
and Cloud Identity Premium accounts. Unfortunately, even if you have the required account, the API call that supports the query doesn't work.
* https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/searchTransitiveGroups
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<UniqueID> ::= id:<String>
<GroupItem> ::= <EmailAddress>|<UniqueID>|<String>
<GroupList> ::= "<GroupItem>(,<GroupItem>)*"
<GroupEntity> ::= <GroupList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<GroupRole> ::= owner|manager|member
<GroupRoleList> ::= "<GroupRole>(,<GroupRole>)*"
<CIGroupType> ::= customer|group|other|serviceaccount|user
<CIGroupTypeList> ::= "<CIGroupType>(,<CIGroupType>)*"
<QueryDynamicGroup> ::= <String>
See: https://cloud.google.com/identity/docs/reference/rest/v1/groups#dynamicgroupquery
<QueryMemberRestrictions> ::= <String>
See: https://cloud.google.com/identity/docs/reference/rest/v1/SecuritySettings#MemberRestriction
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<GroupSettingsAttribute> ::=
(allowexternalmembers <Boolean>)|
(allowwebposting <Boolean>)|
(archiveonly <Boolean>)|
(customfootertext <String>)|
(customreplyto <EmailAddress>)|
(defaultmessagedenynotificationtext <String>)|
(description <String>)|
(enablecollaborativeinbox|collaborative <Boolean>)|
(includeinglobaladdresslist|gal <Boolean>)|
(includecustomfooter <Boolean>)|
(isarchived <Boolean>)|
(memberscanpostasthegroup <Boolean>)|
(messagemoderationlevel moderate_all_messages|moderate_non_members|moderate_new_members|moderate_none)|
(name|displayname <String>)|
(primarylanguage <Language>)|
(replyto reply_to_custom|reply_to_sender|reply_to_list|reply_to_owner|reply_to_ignore|reply_to_managers)|
(sendmessagedenynotification <Boolean>)|
(spammoderationlevel allow|moderate|silently_moderate|reject)|
(whocanadd all_members_can_add|all_managers_can_add|all_owners_can_add|none_can_add)|
(whocancontactowner anyone_can_contact|all_in_domain_can_contact|all_members_can_contact|all_managers_can_contact)|
(whocanjoin anyone_can_join|all_in_domain_can_join|invited_can_join|can_request_to_join)|
(whocanleavegroup all_members_can_leave|all_managers_can_leave|all_owners_can_leave|none_can_leave)|
(whocanpostmessage none_can_post|all_managers_can_post|all_members_can_post|all_owners_can_post|all_in_domain_can_post|anyone_can_post)|
(whocanviewgroup anyone_can_view|all_in_domain_can_view|all_members_can_view|all_managers_can_view|all_owners_can_view)|
(whocanviewmembership all_in_domain_can_view|all_members_can_view|all_managers_can_view|all_owners_can_view)
<GroupWhoCanDiscoverGroupDeprecatedAttribute> ::=
(showingroupdirectory <Boolean>)
<GroupWhoCanAssistContentDeprecatedAttribute> ::=
(whocanassigntopics all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanenterfreeformtags all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanhideabuse all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmaketopicssticky all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmarkduplicate all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmarkfavoritereplyonanytopic all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmarknoresponseneeded all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmodifytagsandcategories all_members|owners_and_managers|managers_only|owners_only|none)|
(whocantaketopics all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanunassigntopic all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanunmarkfavoritereplyonanytopic all_members|owners_and_managers|managers_only|owners_only|none)
<GroupWhoCanModerateContentDeprecatedAttribute> ::=
(whocanapprovemessages all_members|owners_and_managers|owners_only|none)|
(whocandeleteanypost all_members|owners_and_managers|owners_only|none)|
(whocandeletetopics all_members|owners_and_managers|owners_only|none)|
(whocanlocktopics all_members|owners_and_managers|owners_only|none)|
(whocanmovetopicsin all_members|owners_and_managers|owners_only|none)|
(whocanmovetopicsout all_members|owners_and_managers|owners_only|none)|
(whocanpostannouncements all_members|owners_and_managers|owners_only|none)
<GroupWhoCanModerateMembersDeprecatedAttribute> ::=
(whocanadd all_members_can_add|all_managers_can_add|none_can_add)|
(whocanapprovemembers all_members_can_approve|all_managers_can_approve|all_owners_can_approve|none_can_approve)|
(whocanbanusers all_members|owners_and_managers|owners_only|none)|
(whocaninvite all_members_can_invite|all_managers_can_invite|all_owners_can_invite|none_can_invite)|
(whocanmodifymembers all_members|owners_and_managers|owners_only|none)
<GroupDeprecatedAttribute> ::=
(allowgooglecommunication <Boolean>)|
(favoriterepliesontop <Boolean>)|
(maxmessagebytes <ByteCount>)|
(messagedisplayfont default_font|fixed_width_font)|
(whocanaddreferences all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmarkfavoritereplyonowntopic all_members|owners_and_managers|managers_only|owners_only|none)
<GroupAttribute> ::=
<JSONData>|
<GroupSettingsAttribute>|
(whocandiscovergroup allmemberscandiscover|allindomaincandiscover|anyonecandiscover)|
(whocanassistcontent all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmoderatecontent all_members|owners_and_managers|owners_only|none)|
(whocanmoderatemembers all_members|owners_and_managers|owners_only|none)|
<GroupWhoCanDiscoverGroupDeprecatedAttribute>|
<GroupWhoCanAssistContentDeprecatedAttribute>|
<GroupWhoCanModerateContentDeprecatedAttribute>|
<GroupWhoCanModerateMembersDeprecatedAttribute>|
<GroupDeprecatedAttribute>
```
```
<GroupFieldName> ::=
admincreated|
aliases|
allowexternalmembers|
allowgooglecommunication|
allowwebposting|
archiveonly|
customfootertext|
customreplyto|
customrolesenabledforsettingstobemerged|
defaultmessagedenynotificationtext|
description|
directmemberscount|
email|
enablecollaborativeinbox|collaborative|
favoriterepliesontop|
id|
includecustomfooter|
includeinglobaladdresslist|gal|
isarchived|
maxmessagebytes|
memberscanpostasthegroup|
messagedisplayfont|
messagemoderationlevel|
name|
primarylanguage|
replyto|
sendmessagedenynotification|
showingroupdirectory|
spammoderationlevel|
whocanaddreferences|
whocanadd|
whocanapprovemessages|
whocanassigntopics|
whocanassistcontent|
whocancontactowner|
whocandeleteanypost|
whocandeletetopics|
whocandiscovergroup|
whocanenterfreeformtags|
whocanhideabuse|
whocaninvite|
whocanjoin|
whocanleavegroup|
whocanlocktopics|
whocanmaketopicssticky|
whocanmarkduplicate|
whocanmarkfavoritereplyonanytopic|
whocanmarkfavoritereplyonowntopic|
whocanmarknoresponseneeded|
whocanmoderatecontent|
whocanmodifytagsandcategories|
whocanmovetopicsin|
whocanmovetopicsout|
whocanpostannouncements|
whocanpostmessage|
whocantaketopics|
whocanunassigntopic|
whocanunmarkfavoritereplyonanytopic|
whocanviewgroup|
whocanviewmembership
<GroupFieldNameList> ::= "<GroupFieldName>(,<GroupFieldName>)*"
```
```
<CIGroupFieldName> ::=
additionalgroupkeys|
createtime|
description|
displayname|
dynamicgroupmetadata|
email|
groupkey|
id|
labels|
name|
parent|
updatetime
<CIGroupFieldNameList> ::= "<CIGroupFieldName>(,<CIGroupFieldName>)*"
```
## Manage groups
These commands allow you to create, update and delete groups. They use the Admin SDK Groups Settings API
to set `<GroupAttribute>`.
```
gam create cigroup <EmailAddress> [copyfrom <GroupItem>] <GroupAttribute>
[makeowner]
[alias|aliases <EmailAddressList>] [dynamic <QueryDynamicGroup>]
gam update cigroup <GroupEntity> [copyfrom <GroupItem>] <GroupAttribute>
[makesecuritygroup|security] [makedynamicsecuritygroup|dynamicsecurity] [dynamic <QueryDynamicGroup>]
[memberrestrictions <QueryMemberRestrictions>]
gam delete cigroups <GroupEntity>
```
The `copyfrom <GroupItem>` allows copying of group attributes from one group to another.
The following attributes are not copied: name, description, email, admincreated, aliases, noneditablealiases.
Any `<GroupAttribute>` specified will override the copied attributes.
You can update a non-dynamic group to a non-dynamic security group with the `makesecuritygroup` option. To update a dynamic group to a security group, use the `makedynamicsecuritygroup` option instead.
* Warning: A Security Group cannot be changed back to a Google Group.
You can update a group to restrict its membership with the `memberrestrictions <QueryMemberRestrictions>`option.
* https://cloud.google.com/identity/docs/reference/rest/v1/SecuritySettings#MemberRestriction
The `makeowner` option makes the administrator in `oauth2.txt` the initial owner of the group.
## Display information about individual groups
This command displays information as an indented list of keys and values.
```
gam info cigroups <GroupEntity>
[nousers|membertree] [quick] [noaliases]
[nosecurity|nosecuritysettings]
[allfields|<CIGroupFieldName>*|(fields <CIGroupFieldNameList>)]
[roles <GroupRoleList>] [members] [managers] [owners]
[types <CIGroupTypeList>]
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
[formatjson]
```
By default, all direct members, managers and owners in the group are displayed; these options modify that behavior:
* `members` - Display members
* `managers` - Display managers
* `owners` - Display owners
* `nousers` or `quick` - Do not display any members, managers or owners
* `membertree` - Display all roles; expand all groups
By default, when displaying members from a group, all types of members (customer, group, serviceaccount, user) in the group are displayed; this option modifies that behavior:
* `types <CIGroupTypeList>` - Display specified types
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
By default, all group aliases are displayed, these options modify that behavior:
* `noaliases` or `quick` - Do not display group aliases
By default, GAM makes an additional API call to get the `SecuritySettings` for the group.
* `nosecuritysettings` - Do not make API and display `SecuritySettings`
* `allfields` - All Cloud Identity Group fields
* `<CIGroupFieldName>*` - Individual fields to display
* `fields <CIGroupFieldNameList>` - A comma separated list of fields to display
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the output in JSON notation
## Display information about multiple groups
This command displays information in CSV format.
```
gam print cigroups [todrive <ToDriveAttribute>*]
[(cimember|showownedby <UserItem>)|(select <GroupEntity>)|(query <String>)]
[emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
[descriptionmatchpattern [not] <RegularExpression>]
[basic|allfields|(<CIGroupFieldName>* [fields <CIGroupFieldNameList>])]
[roles <GroupRoleList>] [memberrestrictions]
[members|memberscount] [managers|managerscount] [owners|ownerscount] [totalcount] [countsonly]
[types <CIGroupTypeList>]
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
[convertcrnl] [delimiter <Character>]
[formatjson [quotechar <Character>]]
```
By default, all groups in the account are displayed, these options allow selection of subsets of groups:
* `cimember <UserItem>` - Limit display to groups that contain `<UserItem>` as a member
* `showownedby <UserItem>` - Limit display to groups owned by `<UserItem>`
* `select <GroupEntity>` - Limit display to the groups specified in `<GroupEntity>`
* `query <String>` - Limit display to the groups that match the query
These options further limit the list of groups selected above:
* `emailmatchpattern <RegularExpression>` - Limit display to groups whose email address matches `<RegularExpression>`
* `emailmatchpattern not <RegularExpression>` - Limit display to groups whose email address does not match `<RegularExpression>`
* `namematchpattern <RegularExpression>` - Limit display to groups whose name matches `<RegularExpression>`
* `namematchpattern not <RegularExpression>` - Limit display to groups whose name does not match `<RegularExpression>`
* `descriptionmatchpattern <RegularExpression>` - Limit display to groups whose description matches `<RegularExpression>`
* `descriptionmatchpattern not <RegularExpression>` - Limit display to groups whose description does not match `<RegularExpression>`
By default, GAM does not make an additional API call todisplay the member restrictions from `SecuritySettings`.
* `memberrestrictions` - Make an additional API call and display the member restrictions from `SecuritySettings`
When retrieving lists of Google Groups from API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many groups to retrieve in each API call; default is 500.
By default, only the group email address is displayed, these options specify what group fields to display:
* `basic` - Only Cloud Identity Group basic fields are displayed; no additional API calls are required
* `allfields|ciallfields` - All Cloud Identity Group fields are displayed; an additional API call per group is required
* `<GroupFieldName>*` - Individual fields to display
* `fields|cifields <CIGroupFieldNameList>` - A comma separated list of fields to display
As of 2020-12-24, a separate API call is required for each group to get the following fields:
`additionalgroupkeys,createtime,dynamicgroupmetadata,parent,updatetime`
Some text fields may contain carriage returns or line feeds, displaying fields containing these characters will make processing the CSV file with a script hard; this option converts those characters to a text form.
The default value is `csv_output_convert_cr_nl` from `gam.cfg`
* `convertcrnl` - Convert carriage return to \r and line feed to \n
When lists of items are displayed, the delimiter between items defaults to the `csv_output_column_delimiter` value in gam.cfg; you can specify a different delimiter:
* `delimiter <Character>` - Use `<Character>` as the list item delimiter, `<Character>` must be a single character after processing any escape character
By default, no members, managers or owners in the group are displayed; these options modify that behavior:
* `members` - Display list of members
* `memberscount` - Display count of members but not individual members
* `managers` - Display list of managers
* `managerscount` - Display count of managers but not individual managers
* `owners` - Display list of owners
* `ownerscount` - Display count of owners but not individual owners
* `countsonly` - Change any `members`, `managers` or `owners` options to `memberscount`, `managerscount` or `ownerscount`
* `totalcount` - Display sum of counts of members, managers, owners.
By default, when displaying members from a group, all types of members (customer, group, serviceaccount, user) in the group are displayed; this option modifies that behavior:
* `types <CIGroupTypeList>` - Display specified types
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
### Display security groups
```
gam print cigroups query "'cloudidentity.googleapis.com/groups.security' in labels"
```

57
docs/Cloud-Storage.md Normal file
View File

@ -0,0 +1,57 @@
# Cloud Storage
- [API documentation](#api-documentation)
- [Notes](#notes)
- [Definitions](#definitions)
- [Download a Cloud Storage Bucket Object](#download-a-cloud-storage-bucket-object)
## API documentation
* https://cloud.google.com/storage/docs/json_api/v1/objects
## Notes
To use these commands you must add the 'Cloud Storage API' to your project and update your client access authorization.
Enable `Cloud Storage API (Read, Vault/Takeout Download)`.
```
gam update project
gam oauth create
```
## Definitions
```
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
```
## Download a Cloud Storage Bucket Object
```
gam download storagefile <StorageBucketObjectName>
[targetfolder <FilePath>] [overwrite [<Boolean>]] [nogcspath [<Boolean>]]
```
By default, the takeout files will be downloaded to the directory specified by `drive_dir` in gam.cfg.
* `targetfolder <FilePath>` - The takeout files will be downloaded to `<FilePath>`
By default, when getting a document, an existing local file will not be overwritten; a numeric prefix is added to the filename.
* `overwrite false` - Do not overwite an existing file; add a numeric prefix and create a new file
* `overwrite | overwrite true` - Overwite an existing file
By default, when getting a document, its Google Cloud Storage path is preserved.
* `nogcspath false` - Preserve the Google Cloud Storage path
* `nogcspath | nogcspath true` - Do not preserve the Google Cloud Storage path
### Example
This example downloads a Google Cloud Storage file preserving its path
```
$ gam download storagefile gs://gam-bucket/SubFolder/SimpleText.txt
Getting File SubFolder/SimpleText.txt
Cloud Storage File: SubFolder/SimpleText.txt, Downloaded to: /Users/admin/Documents/GamWork/SubFolder/SimpleText.txt
```
This example downloads a Google Cloud Storage file removing its path
```
$ gam download storagefile gs://gam-bucket/SubFolder/SimpleText.txt nogcspath
Getting File SubFolder/SimpleText.txt
Cloud Storage File: SubFolder/SimpleText.txt, Downloaded to: /Users/admin/Documents/GamWork/SimpleText.txt
```

View File

@ -0,0 +1,460 @@
# Collections of ChromeOS Devices
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [Organization Unit Quoting](#organization-unit-quoting)
- [Query Quoting](#query-quoting)
- [Query Notes](#query-notes)
- [CrOS Type Entity](#cros-type-entity)
- [All ChromeOS devices](#all-chromeos-devices)
- [A list of ChromeOS deviceIds](#a-list-of-chromeos-deviceids)
- [A list of ChromeOS device serial numbers](#a-list-of-chromeos-device-serial-numbers)
- [ChromeOS devices directly in the Organization Unit `<OrgUnitItem>`](#chromeos-devices-directly-in-the-organization-unit-orgunititem)
- [ChromeOS devices in the Organization Unit `<OrgUnitItem>` and all of its sub Organization Units](#chromeos-devices-in-the-organization-unit-orgunititem-and-all-of-its-sub-organization-units)
- [ChromeOS devices directly in the Organization Units `<OrgUnitList>`](#chromeos-devices-directly-in-the-organization-units-orgunitlist)
- [ChromeOS devices in the Organization Units `<OrgUnitList>` and all of their sub Organization Units](#chromeos-devices-in-the-organization-units-orgunitlist-and-all-of-their-sub-organization-units)
- [ChromeOS devices directly in the Organization Unit `<OrgUnitItem>` that also match a query](#chromeos-devices-directly-in-the-organization-unit-orgunititem-that-also-match-a-query)
- [ChromeOS devices in the Organization Unit `<OrgUnitItem>` and all of its sub Organization Units that also match a query](#chromeos-devices-in-the-organization-unit-orgunititem-and-all-of-its-sub-organization-units-that-also-match-a-query)
- [ChromeOS devices directly in the Organization Units `<OrgUnitList>` that also match a query](#chromeos-devices-directly-in-the-organization-units-orgunitlist-that-also-match-a-query)
- [ChromeOS devices in the Organization Units `<OrgUnitList>` and all of their sub Organization Units that also match a query](#chromeos-devices-in-the-organization-units-orgunitlist-and-all-of-their-sub-organization-units-that-also-match-a-query)
- [ChromeOS devices directly in the Organization Unit `<OrgUnitItem>` that also match any query in a list of queries](#chromeos-devices-directly-in-the-organization-unit-orgunititem-that-also-match-any-query-in-a-list-of-queries)
- [ChromeOS devices in the Organization Unit `<OrgUnitItem>` and all of its sub Organization Units that also match any query in a list of queries](#chromeos-devices-in-the-organization-unit-orgunititem-and-all-of-its-sub-organization-units-that-also-match-any-query-in-a-list-of-queries)
- [ChromeOS devices directly in the Organization Units `<OrgUnitList>` that also match any query in a list of queries](#chromeos-devices-directly-in-the-organization-units-orgunitlist-that-also-match-any-query-in-a-list-of-queries)
- [ChromeOS devices in the Organization Units `<OrgUnitList>` and all of their sub Organization Units that also match any query in a list of queries](#chromeos-devices-in-the-organization-units-orgunitlist-and-all-of-their-sub-organization-units-that-also-match-any-query-in-a-list-of-queries)
- [ChromeOS devices that match a query](#chromeos-devices-that-match-a-query)
- [ChromeOS devices that match any query in a list of queries](#chromeos-devices-that-match-any-query-in-a-list-of-queries)
- [ChromeOS deviceIds in a flat file/Google Doc/Google Cloud Storage Object](#chromeos-deviceids-in-a-flat-filegoogle-docgoogle-cloud-storage-object)
- [ChromeOS serial numbers in a flat file/Google Doc/Google Cloud Storage Object](#chromeos-serial-numbers-in-a-flat-filegoogle-docgoogle-cloud-storage-object)
- [Selected ChromeOS deviceIds in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object](#selected-chromeos-deviceids-in-a-csv-filegoogle-sheetgoogle-docgoogle-cloud-storage-object)
- [Selected ChromeOS serial numbers in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object](#selected-chromeos-serial-numbers-in-a-csv-filegoogle-sheetgoogle-docgoogle-cloud-storage-object)
- [ChromeOS devices from OUs in a flat file/Google Doc/Google Cloud Storage Object](#chromeos-devices-from-ous-in-a-flat-filegoogle-docgoogle-cloud-storage-object)
- [ChromeOS deviceIds from OUs in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object](#chromeos-deviceids-from-ous-in-a-csv-filegoogle-sheetgoogle-docgoogle-cloud-storage-object)
- [ChromeOS devices directly in or from OUs in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object](#chromeos-devices-directly-in-or-from-ous-in-a-csv-filegoogle-sheetgoogle-docgoogle-cloud-storage-object)
- [ChromeOS deviceIds from data fields identified in a `csvkmd` argument](#chromeos-deviceids-from-data-fields-identified-in-a-csvkmd-argument)
- [Examples using CSV files](#examples-using-csv-files)
- [Examples using multiple queries or Org Units](#examples-using-multiple-queries-or-org-units)
## Definitions
* [Basic Items](Basic-Items)
* [List Items](List-Items)
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
```
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
<UserGoogleDoc> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
<UserGoogleSheet> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>) <SheetEntity>
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
```
```
<CrOSTypeEntity> ::=
(all cros)|
(cros <CrOSIDList>)|
(cros_sn <SerialNumberList>)|
(cros_ou <OrgUnitItem>)|
(cros_ou_and_children <OrgUnitItem>)|
(cros_ous <OrgUnitList>)|
(cros_ous_and_children <OrgUnitList>)|
(cros_ou_query <OrgUnitItem> <QueryCrOS>)|
(cros_ou_and_children_query <OrgUnitItem> <QueryCrOS>)|
(cros_ous_query <OrgUnitList> <QueryCrOS>)|
(cros_ous_and_children_query <OrgUnitList> <QueryCrOS>)|
(cros_ou_queries <OrgUnitItem> <QueryCrOSList>)|
(cros_ou_and_children_queries <OrgUnitItem> <QueryCrOSList>)|
(cros_ous_queries <OrgUnitList> <QueryCrOSList>)|
(cros_ous_and_children_queries <OrgUnitList> <QueryCrOSList>)|
(crosquery <QueryCrOS>)|
(crosqueries <QueryCrOSList>)|
(crosfile
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>])|
(crosfile_sn
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>])|
(croscsvfile
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])|
(croscsvfile_sn
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])|
(datafile
cros|cros_sn|cros_ous|cros_ous_and_children
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>])|
(csvdatafile
cros|cros_sn|cros_ous|cros_ous_and_children
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])|
(csvkmd
cros|cros_sn|cros_ous|cros_ous_and_children
((<FileName>|
(gsheet <UserGoogleSheet>)|
(gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[datafield <FieldName>(:<FieldName>)* [delimiter <Character>]])
(croscsvdata <FieldName>(:<FieldName>*))
```
## Organization Unit Quoting
* `<OrgUnitItem>` should be enclosed in `"` if it contains a space, comma or single quote.
* `<OrgUnitList>` may require special quoting based on whether the OUs contain spaces, commas or single quotes.
For quoting rules, see: [List Items](List-Items)
## Query Quoting
`<QueryCrOSList>` may require special quoting based on whether the queries contain spaces, commas or single quotes.
* Surround `<QueryCrOSList>` with `" "`
* Surround each query with `\" \"`, separate the queries with commas.
```
queries "\"orgUnitPath='/Path/To/OU 1'\",\"orgUnitPath='/Path/To/OU 2'\",\"orgUnitPath='/Path/To/OU 3'\""
```
## Query Notes
See https://support.google.com/chrome/a/answer/1698333
Undocumented API query terms.
```
<QueryDate> ::=
YYYY-MM-DD # Specific date
..YYYY-MM-DD # Before a date
YYYY-MM-DD.. # After a date
YYYY-MM-DD..YYYY-MM-DD # Range of dates
aue:<QueryDate>
compliance:compliant|pending_update|not_compliant
last_user_activity:<QueryDate>
policy_status:true|false
public_model_name:<String>
update_status:default_os_up_to_date|pending_update|os_image_download_not_started|os_image_download_in_progress|os_update_need_reboot
```
## CrOS Type Entity
Use these options to select Chrome OS devices for GAM commands.
## All ChromeOS devices
* `all cros`
## A list of ChromeOS deviceIds
* `cros <CrOSList>`
## A list of ChromeOS device serial numbers
* `cros_sn <SerialNumberList>`
## ChromeOS devices directly in the Organization Unit `<OrgUnitItem>`
* `cros_ou <OrgUnitItem>`
## ChromeOS devices in the Organization Unit `<OrgUnitItem>` and all of its sub Organization Units
* `cros_ou_and_children <OrgUnitItem>`
## ChromeOS devices directly in the Organization Units `<OrgUnitList>`
* `cros_ous <OrgUnitList>`
## ChromeOS devices in the Organization Units `<OrgUnitList>` and all of their sub Organization Units
* `cros_ous_and_children <OrgUnitList>`
## ChromeOS devices directly in the Organization Unit `<OrgUnitItem>` that also match a query
* `cros_ou_query <OrgUnitItem> <QueryCrOS>`
## ChromeOS devices in the Organization Unit `<OrgUnitItem>` and all of its sub Organization Units that also match a query
* `cros_ou_and_children_query <OrgUnitItem> <QueryCrOS>`
## ChromeOS devices directly in the Organization Units `<OrgUnitList>` that also match a query
* `cros_ous_query <OrgUnitList> <QueryCrOS>`
## ChromeOS devices in the Organization Units `<OrgUnitList>` and all of their sub Organization Units that also match a query
* `cros_ous_and_children_query <OrgUnitList> <QueryCrOS>`
## ChromeOS devices directly in the Organization Unit `<OrgUnitItem>` that also match any query in a list of queries
* `cros_ou_queries <OrgUnitItem> <QueryCrOSList>`
## ChromeOS devices in the Organization Unit `<OrgUnitItem>` and all of its sub Organization Units that also match any query in a list of queries
* `cros_ou_and_children_queries <OrgUnitItem> <QueryCrOSList>`
## ChromeOS devices directly in the Organization Units `<OrgUnitList>` that also match any query in a list of queries
* `cros_ous_queries <OrgUnitList> <QueryCrOSList>`
## ChromeOS devices in the Organization Units `<OrgUnitList>` and all of their sub Organization Units that also match any query in a list of queries
* `cros_ous_and_children_queries <OrgUnitList> <QueryCrOSList>`
## ChromeOS devices that match a query
* `crosquery <QueryCrOS>`
## ChromeOS devices that match any query in a list of queries
* `crosqueries <QueryCrOSList>`
## ChromeOS deviceIds in a flat file/Google Doc/Google Cloud Storage Object
```
crosfile
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>]
```
* `<FileName>` - A flat file containing a single ChromeOS deviceId per row
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gdoc <UserGoogleDoc>` - A Google Doc containing a single ChromeOS deviceId per row
* `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing a single ChromeOS deviceId per row
* `delimiter <Character>` - There are multiple deviceIds per row separated by `<Character>`; if not specified, there is single deviceId per row
## ChromeOS serial numbers in a flat file/Google Doc/Google Cloud Storage Object
```
crosfile_sn
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>]
```
* `<FileName>` - A flat file containing a single ChromeOS serial number per row
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gdoc <UserGoogleDoc>` - A Google Doc containing a single ChromeOS serial number per row
* `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing a single ChromeOS serial number per row
* `delimiter <Character>` - There are multiple serial numbers per row separated by `<Character>`; if not specified, there is single serial number per row
## Selected ChromeOS deviceIds in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
```
croscsvfile
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>]
```
* `<FileName>(:<FieldName>)+` - A CSV file and the one or more columns that contain ChromeOS deviceIds
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gsheet(:<FieldName>)+ <UserGoogleSheet>` - A Google Sheet and the one or more columns that contain ChromeOS deviceIds
* `gdoc(:<FieldName>)+ <UserGoogleDoc>` - A Google Doc and the one or more columns that contain ChromeOS deviceIds
* `gcscsv(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS deviceIds
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS deviceIds
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `delimiter <Character>` - There are multiple deviceIds per column separated by `<Character>`; if not specified, there is single deviceId per column
## Selected ChromeOS serial numbers in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
```
croscsvfile_sn
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>]
```
* `<FileName>(:<FieldName>)+` - A CSV file and the one or more columns that contain ChromeOS serial numbers
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gsheet(:<FieldName>)+ <UserGoogleSheet>` - A Google Sheet and the one or more columns that contain ChromeOS serial numbers
* `gdoc(:<FieldName>)+ <UserGoogleDoc>` - A Google Doc and the one or more columns that contain ChromeOS serial numbers
* `gcscsv(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS serial numbers
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS serial numbers
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `delimiter <Character>` - There are multiple serial numbers per column separated by `<Character>`; if not specified, there is single deviceId per column
## ChromeOS devices from OUs in a flat file/Google Doc/Google Cloud Storage Object
```
datafile
cros|cros_sn|cros_ous|cros_ous_and_children
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>]
```
* `cros|cros_sn|cros_ous|cros_ous_and_children` - The type of item in the file
* `<FileName>` - A flat file containing a single item per row
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gdoc <UserGoogleDoc>` - A Google Doc containing a single item per row
* `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing a item per row
* `delimiter <Character>` - There are multiple items per row separated by `<Character>`; if not specified, there is single item per row
## ChromeOS deviceIds from OUs in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
```
csvdatafile
cros|cros_sn|cros_sn|cros_ous|cros_ous_and_children
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>]
```
* `cros|cros_ous|cros_ous_and_children` - The type of item in the file
* `<FileName>(:<FieldName>)+` - A CSV file and the one or more columns that contain ChromeOS deviceIds
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gsheet(:<FieldName>)+ <UserGoogleSheet>` - A Google Sheet and the one or more columns that contain ChromeOS deviceIds
* `gdoc(:<FieldName>)+ <UserGoogleDoc>` - A Google Doc and the one or more columns that contain ChromeOS deviceIds
* `gcscsv(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS deviceIds
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS deviceIds
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `delimiter <Character>` - There are multiple deviceIds per column separated by `<Character>`; if not specified, there is single deviceId per column
## ChromeOS devices directly in or from OUs in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
```
csvkmd
cros|cros_sn|cros_ous|cros_ous_and_children
((<FileName>|
(gsheet <UserGoogleSheet>)|
(gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[datafield <FieldName>(:<FieldName>)* [delimiter <Character>]]
```
* `cros|cros_sn|cros_ous|cros_ous_and_children` - The type of item in the file
* `<FileName>` - A CSV file containing rows with columns of the type of item specified
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gsheet <UserGoogleSheet>` - A Google Sheet containing rows with columns of the type of item specified
* `gdoc <UserGoogleDoc>` - A Google Doc containing rows with columns of the type of item specified
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>])+`
* `keyfield <FieldName>` - The column containing key values
* `[keypattern <RegularExpression>] [keyvalue <String>]` - Allows transforming the value(s) in the `keyfield` column. If only `keyvalue <String>` is specified, all instances of `<FieldName>` in `keyvalue <String>` will be replaced by the item value. If `keypattern <RegularExpression>` is specified, the item value is matched against `<RegularExpression>` and the matched segments are substituted into `keyvalue <String>`
* `delimiter <Character>` - There are multiple values per keyfield column separated by `<Character>`; if not specified, there is single value per keyfield column
* `(subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>])*`
* `subkeyfield <FieldName>` - The column containing subkey values
* `[keypattern <RegularExpression>] [keyvalue <String>]` - Allows transforming the value(s) in the `subkeyfield` column. If only `keyvalue <String>` is specified, all instances of `<FieldName>` in `keyvalue <String>` will be replaced by the item value. If `keypattern <RegularExpression>` is specified, the item value is matched against `<RegularExpression>` and the matched segments are substituted into `keyvalue <String>`
* `delimiter <Character>` - There are multiple values per subkeyfield column separated by `<Character>`; if not specified, there is single value per subkeyfield column
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `(datafield <FieldName>(:<FieldName)* [delimiter <Character>])*`
* `datafield <FieldName>(:<FieldName)*` - The column(s) containing data values
* `delimiter <Character>` - There are multiple values per datafield column separated by `<Character>`; if not specified, there is single value per datafield column
## ChromeOS deviceIds from data fields identified in a `csvkmd` argument
* `croscsvdata <FieldName>(:<FieldName>*)` - Data fields identified in a `csvkmd` argument
## Examples using CSV files
You want to print information about ChromeOS devices at your school from Org Units based on graduation year.
Example 1
CSV File OrgUnit.csv, exactly the data you want, `keypattern` and `keyvalue` are not required.
```
OrgUnit
/Students/2020
/Students/2021
...
```
For each row, the value from the OrgUnit column is used as the Org Unit name.
```
gam csvkmd cros_ous OrgUnit.csv keyfield OrgUnit print cros
```
Example 2
CSV File GradYear.csv, you have to convert GradYear to Org Unit name `/Students/GradYear`, `keyvalue` is required.
```
GradYear
2020
2021
...
```
For each row, the value from the GradYear column replaces the keyField name in the `keyvalue` argument and that value is used as the Org Unit name.
```
gam csvkmd cros_ous GradYear.csv keyfield GradYear keyvalue "/Students/GradYear" print cros
```
Example 3
CSV File GradYear.csv, you have to convert GradYear to Org Unit name `/Students/LastTwoDigitsOfGradYear`, `keypattern` and `keyvalue` are required.
```
GradYear
2020
2021
...
```
For each row, the value from the GradYear column is matched against the `keypattern` and the matched segments are substituted into the `keyvalue` argument and that value is used as the Org Unit name.
```
gam csvkmd cros_ous GradYear.csv keyfield GradYear keypattern '20(..)' keyvalue '/Students/\1' print cros
```
## Examples using multiple queries or Org Units
Example 1
Print information about all ChromeOS devices with a serial number that starts with HY3 or 5CD.
```
gam crosqueries "id:HY3,id:5CD" print cros allfields nolists
```
Example 2
Print information about all ChromeOS devices in two Org Units that contain spaces in their names.
```
gam crosqueries "\"orgUnitPath='/Students/Middle School/2021'\",\"orgUnitPath='/Students/Middle School/2020'\"" print cros allfields nolists
```
This is equivaluent to:
```
gam cros_ous "'/Students/Middle School/2021','/Students/Middle School/2020'" print cros allfields nolists
```

View File

@ -0,0 +1,385 @@
# Collections of Items
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [ListSelector](#listselector)
- [FileSelector](#fileselector)
- [CSVFileSelector](#csvfileselector)
- [CSVkmdSelector](#csvkmdselector)
- [CSVSubkeySelector](#csvsubkeyselector)
- [CSVDataSelector](#csvdataselector)
- [Named Collections](#named-collections)
- [Examples](#examples)
## Definitions
* [Basic Items](Basic-Items)
* [List Items](List-Items)
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
```
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
<UserGoogleDoc> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
<UserGoogleSheet> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>) <SheetEntity>
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
```
## ListSelector
A list of items
```
<Item> ::= <String>
<ItemList> ::= "<Item>(,<Item>)*"
<ListSelector> ::= list <ItemList>
```
## FileSelector
A flat file containing a single Item per row.
```
<FileSelector> ::=
file ((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>]
```
* `<FileName>` - A flat file containing Items
* `gdoc <UserGoogleDoc>` - A Google Doc containing Items
* `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing Items
* `delimiter <Character>` - There are multiple Items per row separated by `<Character>`; if not specified, there is single item per row
## CSVFileSelector
A CSV file with one or more columns per row that contain Items.
```
<CSVFileSelector> ::=
csvfile ((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>]
```
* `<FileName>(:<FieldName>)+` - A CSV file and the one or more columns that contain Items
* `gsheet(:<FieldName>)+ <UserGoogleSheet>` - A Google Sheet and the one or more columns that contain Items
* `gdoc(:<FieldName>)+ <UserGoogleDoc>` - A Google Doc and the one or more columns that contain Items
* `gcscsv(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain Items
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain Items
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `delimiter <Character>` - There are multiple Items per column separated by `<Character>`; if not specified, there is single item per column
## CSVkmdSelector
A CSV file with a key column that contains an Item and optional subkey and data columns that contain data related to the key Item.
```
<CSVkmdSelector> ::=
csvkmd ((<FileName>|
(gsheet <UserGoogleSheet>)|
(gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[datafield <FieldName>(:<FieldName>)* [delimiter <Character>]]
```
* `<FileName>` - A CSV file containing rows with columns of items
* `gsheet <UserGoogleSheet>` - A Google Sheet containing rows with columns of items
* `gdoc <UserGoogleDoc>` - A Google Doc containing rows with columns of items
* `gcscsv <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing rows with columns of items
* `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing rows with columns of items
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>])+`
* `keyfield <FieldName>` - The column containing key values
* `[keypattern <RegularExpression>] [keyvalue <String>]` - Allows transforming the value(s) in the `keyfield` column. If only `keyvalue <String>` is specified, all instances of `<FieldName>` in `keyvalue <String>` will be replaced by the item value. If `keypattern <RegularExpression>` is specified, the item value is matched against `<RegularExpression>` and the matched segments are substituted into `keyvalue <String>`
* `delimiter <Character>` - There are multiple values per keyfield column separated by `<Character>`; if not specified, there is single value per keyfield column
* `(subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>])*`
* `subkeyfield <FieldName>` - The column containing subkey values
* `[keypattern <RegularExpression>] [keyvalue <String>]` - Allows transforming the value(s) in the `subkeyfield` column. If only `keyvalue <String>` is specified, all instances of `<FieldName>` in `keyvalue <String>` will be replaced by the item value. If `keypattern <RegularExpression>` is specified, the item value is matched against `<RegularExpression>` and the matched segments are substituted into `keyvalue <String>`
* `delimiter <Character>` - There are multiple values per subkeyfield column separated by `<Character>`; if not specified, there is single value per subkeyfield column
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `(datafield <FieldName>(:<FieldName)* [delimiter <Character>])*`
* `datafield <FieldName>(:<FieldName)*` - The column(s) containing data values
* `delimiter <Character>` - There are multiple values per datafield column separated by `<Character>`; if not specified, there is single value per datafield column
## CSVSubkeySelector
A subkey field identified in a `csvkmd` argument.
```
<CSVSubkeySelector> ::=
csvsubkey <FieldName>
```
## CSVDataSelector
Data fields identified in a `csvkmd` argument.
```
<CSVDataSelector> ::=
csvdata <FieldName>(:<FieldName)*
```
## Named Collections
```
<BrowserEntity> ::=
<DeviceIDList> |
(query:<QueryBrowser>)|(query:orgunitpath:<OrgUnitPath>)|(query <QueryBrowser>) |
(browserou <OrgUnitItem>) | (browserous <OrgUnitList>) |
<FileSelector> | <CSVFileSelector>
<CalendarACLScopeEntity> ::=
<CalendarACLScopeList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<CalendarEntity> ::=
<CalendarList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<ClassroomInvitationIDEntity> ::=
<ClassroomInvitationIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<ContactEntity> ::=
<ContactIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<ContactGroupEntity> ::=
<ContactGroupList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<CourseAliasEntity> ::=
<CourseAliasList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<CourseEntity> ::=
<CourseIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector>
<CourseAnnouncementIDEntity> ::=
<CourseAnnouncementIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector> | <CSVDataSelector>
<CourseSubmissionIDEntity> ::=
<CourseSubmissionIDList> | <FileSelector> | <CSVFileSelector> | <CSVDataSelector>
<CourseTopicIDEntity> ::=
<CourseTopicIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector> | <CSVDataSelector>
<CourseWorkIDEntity> ::=
<CourseWorkIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector> | <CSVDataSelector>
<CourseMaterialIDEntity> ::=
<CourseMaterialIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector> | <CSVDataSelector>
<CrOSEntity> ::=
<CrOSIDList> | (cros_sn <SerialNumberList>) |
(query:<QueryCrOS>) | (query:orgunitpath:<OrgUnitPath>) | (query <QueryCrOS>)
<DataStudioAssetIDEntity> ::=
<DataStudioAssetIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DataStudioPermissionEntity> ::=
<DataStudioPermissionList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DeviceIDEntity> ::=
<DeviceIDList> | (device_sn <SerialNumber>)
(query:<QueryDevice>) | (query <QueryDevice>)
<DeviceFileEntity> ::=
<TimeList> |
(first|last|allexceptfirst|allexceptlast <Number>) |
(before|after <Time>) | (range <Time> <Time>) |
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DomainNameEntity> ::=
<DomainNameList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DriveFileIDEntity> ::=
<DriveFileItem> |
(id <DriveFileItem>) | (id:<DriveFileItem>) |
(ids <DriveFileList>) | (ids:<DriveFileList>)
<DriveFileNameEntity> ::=
(anyname <DriveFileName>) | (anyname:<DriveFileName>) |
(anydrivefilename <DriveFileName>) | (anydrivefilename:<DriveFileName>) |
(name <DriveFileName>) | (name:<DriveFileName>) |
(drivefilename <DriveFileName>) | (drivefilename:<DriveFileName>) |
(othername <DriveFileName>) | (othername:<DriveFileName>) |
(otherdrivefilename <DriveFileName>) | (otherdrivefilename:<DriveFileName>)
<DriveFileQueryEntity> ::=
(query <QueryDriveFile>) | (query:<QueryDriveFile>) |
(fullquery <QueryDriveFile>)
<DriveFileQueryShortcut> ::=
all_files |
all_folders |
all_forms |
all_google_files |
all_non_google_files |
all_shortcuts |
all_3p_shortcuts |
all_items |
my_files |
my_folders |
my_forms |
my_google_files |
my_non_google_files |
my_shortcuts |
my_3p_shortcuts |
my_items |
my_top_files |
my_top_folders |
my_top_items |
others_files |
others_folders |
others_forms |
others_google_files |
others_non_google_files |
others_shortcuts |
others_3p_shortcuts |
others_items |
writable_files
<DriveFileEntityShortcut> ::=
alldrives |
mydrive_any |
mydrive_me |
mydrive_others |
onlyteamdrives|onlyshareddrives |
orphans |
ownedby_any |
ownedby_me |
ownedby_others |
root | mydrive |
rootwithorphans|mydrivewithorphans |
sharedwithme_all |
sharedwithme_mydrive |
sharedwithme_notmydrive
<DriveFileEntity> ::=
<DriveFileIDEntity> |
<DriveFileNameEntity> |
<DriveFileQueryEntity> |
<DriveFileQueryShortcut> |
mydrive | mydriveid |
root | rootid |
<SharedDriveIDEntity> [<SharedDriveFileQueryShortcut>] |
<SharedDriveNameEntity> [<SharedDriveFileQueryShortcut>] |
<SharedDriveFileNameEntity> |
<SharedDriveFileQueryEntity> |
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector> | <CSVDataSelector>)
<DriveFilePermissionEntity> ::=
<DriveFilePermissionList> |
<JSONData> |
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DriveFilePermissionIDEntity> ::=
<DriveFilePermissionIDList> |
<JSONData> |
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DriveFileRevisionIDEntity> ::=
(<DriveFileRevisionID>) | (id[ |:]<DriveFileRevisionID>) (ids[ |:]<DriveFileRevisionIDList>)
(first|last|allexceptfirst|allexceptlast <Number>)|
(before|after <Time>) | (range <Time> <Time>)|
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<DriveLabelNameEntity> ::=
<DriveLabelNameList> | <FileSelector> | <CSVFileSelector> | <CSVDataSelector>
<EmailAddressEntity> ::=
<EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<FilterIDEntity> ::=
<FilterIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<EventIDEntity> ::=
(id|eventid <EventId>) |
(event|events <EventIdList> |
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector> | <CSVDataSelector>)
<GroupEntity> ::=
<GroupList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<GuardianEntity> ::=
<GuardianList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<GuardianInvitationIDEntity> ::=
<GuardianInvitationIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LabelIDEntity> ::=
<LabelIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<LabelNameEntity> ::=
<LabelNameList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<MessageIDEntity> ::=
<MessageIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<MobileEntity> ::=
<ResourceIDList> |
(query:<QueryMobile>) | (query <QueryMobile>)
<NotesNameEntity> ::=
<NotesNameList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<OrgUnitEntity> ::=
<OrgUnitList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector>
<OtherContactsResourceNameEntity> ::=
<OtherContactsResourceNameNameList> | <FileSelector> | <CSVFileSelector> | <CSVDataSelector>
<PeopleResourceNameEntity> ::=
<PeopleResourceNameList> | <FileSelector> | <CSVFileSelector> | <CSVDataSelector>
<ProjectIDEntity> ::=
current | gam | <ProjectID> | (filter <String>) |
(select <ProjectIDList> | <FileSelector> | <CSVFileSelector>)
<PrinterIDEntity> ::=
<PrinterIDList> | <FileSelector> | <CSVFileSelector>
<RecipientEntity> ::=
<EmailAddressEntity> | (select <UserTypeEntity>)
<ResourceEntity> ::=
<ResourceIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector>
<SchemaEntity> ::=
<SchemaNameList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector>
<SerialNumberEntity> ::=
<SerialNumberList> | <FileSelector> | <CSVFileSelector>
<SharedDriveIDEntity> ::=
<DriveFileItem> |
(teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::=
(teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
<SharedDriveEntity> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>
<SharedDriveAdminQueryEntity> ::=
(teamdriveadminquery <QueryTeamDrive>) | (teamdriveadminquery:<QueryTeamDrive>)
<SharedDriveEntityAdmin> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>|
<SharedDriveAdminQueryEntity>
<SharedDriveFileNameEntity> ::=
(teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
<SharedDriveFileQueryEntity> ::=
(teamdrivequery <QueryDriveFile>) | (teamdrivequery:<QueryDriveFile>)
<SharedDriveFileQueryShortcut> ::=
all_files | all_folders | all_google_files | all_non_google_files | all_items
<SiteACLScopeEntity> ::=
<SiteACLScopeList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<SiteEntity> ::=
<SiteList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<TasklistIDEntity> ::=
<TasklistIDList> | <FileSelector> | <CSVFileSelector>
<TasklistIDTaskIDEntity> ::=
<TasklistIDTaskIDList> | <FileSelector> | <CSVFileSelector>
<ThreadIDEntity> ::=
<ThreadIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<UserEntity> ::=
<UserList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
```
## Examples
You want to update the membership of a collection of parent groups at your school, the data is coming from a database in a fixed format.
Example 1, CSV File GroupP1P2.csv, exactly the data you want, `keypattern` and `keyvalue` are not required.
```
Group,P1Email,P2Email
2017-parents@domain.com,g1member11@domain.com,g1member12@domain.com
2017-parents@domain.com,g1member21@domain.com,g1member22@domain.com
2018-parents@domain.com,g2member11@domain.com,g2member11@domain.com
2018-parents@domain.com,g2member21@domain.com,g2member22@domain.com
...
```
For each row, the value from the Group column is used as the group name.
`gam update groups csvkmd GroupP1P2.csv keyfield Group datafield P1Email:P2Email sync member csvdata P1Email:P2Email`
Example 2, CSV File GradYearP1P2.csv, you have to convert GradYear to group name `GradYear-parents@domain.com`, `keyvalue` is required.
```
GradYear,P1Email,P2Email
2017,g1member11@domain.com,g1member12@domain.com
2017,g1member21@domain.com,g1member22@domain.com
2018,g2member11@domain.com,g2member11@domain.com
2018,g2member21@domain.com,g2member22@domain.com
...
```
For each row, the value from the GradYear column replaces the keyField name in the `keyvalue` argument and that value is used as the group name.
`gam update groups csvkmd GradYearP1P2.csv keyfield GradYear keyvalue GradYear-parents@domain.com datafield P1Email:P2Email sync member csvdata P1Email:P2Email`
Example 3, CSV File GradYearP1P2.csv, you have to convert GradYear to group name `LastTwoDigitsOfGradYear-parents@domain.com`, `keypattern` and `keyvalue` are required.
```
GradYear,P1Email,P2Email
2017,g1member11@domain.com,g1member12@domain.com
2017,g1member21@domain.com,g1member22@domain.com
2018,g2member11@domain.com,g2member11@domain.com
2018,g2member21@domain.com,g2member22@domain.com
...
```
For each row, the value from the GradYear column is matched against the `keypattern`, the matched segments are substituted into the `keyvalue` argument and that value is used as the group name.
`gam update groups csvkmd GradYearP1P2.csv keyfield GradYear keypattern '20(..)' keyvalue '\1-parents@domain.com' datafield P1Email:P2Email sync member csvdata P1Email:P2Email`

View File

@ -0,0 +1,678 @@
# Collections of Users
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [List quoting rules](#list-quoting-rules)
- [User Type Entity](#user-type-entity)
- [All non-suspended Users](#all-non-suspended-users)
- [All suspended Users](#all-suspended-Users)
- [All non-suspended and suspended Users](#all-non-suspended-and-suspended-users)
- [A single User](#a-single-user)
- [A list of Users](#a-list-of-users)
- [The admin user referenced in oauth2.txt](#the-admin-user-referenced-in-oauth2txt)
- [Users in the domains `<DomainNameList>`](#users-in-the-domains-domainnamelist)
- [Users directly in the group `<GroupItem>`](#users-directly-in-the-group-groupitem)
- [Users directly in the groups `<GroupList>`](#users-directly-in-the-groups-grouplist)
- [Users directly and indirectly in the group `<GroupItem>`](#users-directly-and-indirectly-in-the-group-groupitem)
- [Users directly and indirectly in the groups `<GroupList>`](#users-directly-and-indirectly-in-the-groups-grouplist)
- [Selected Users from groups](#selected-users-from-groups)
- [Users directly in the Cloud Identity group `<GroupItem>`](#users-directly-in-the-cloud-identity-group-groupitem)
- [Users directly in the Cloud Identity groups `<GroupList>`](#users-directly-in-the-cloud-identity-groups-grouplist)
- [Selected Users from Cloud Identity groups](#selected-users-from-cloud-identity-groups)
- [Users directly in the Organization Unit `<OrgUnitItem>`](#users-directly-in-the-organization-unit-orgunititem)
- [Users in the Organization Unit `<OrgUnitItem>` and all of its sub Organization Units](#users-in-the-organization-unit-orgunititem-and-all-of-its-sub-organization-units)
- [Users directly in the Organization Units `<OrgUnitList>`](#users-directly-in-the-organization-units-orgunitlist)
- [Users in the Organization Units `<OrgUnitList>` and all of their sub Organization Units](#users-in-the-organization-units-orgunitlist-and-all-of-their-sub-organization-units)
- [All of the students and teachers in the courses specified in `<CourseIDList>`](#all-of-the-students-and-teachers-in-the-courses-specified-in-courseidlist)
- [All of the students in the courses specified in `<CourseIDList>`](#all-of-the-students-in-the-courses-specified-in-courseidlist)
- [All of the teachers in the courses specified in `<CourseIDList>`](#all-of-the-teachers-in-the-courses-specified-in-courseidlist)
- [All Users with any of the licenses specified in `<SKUIDList>`](#all-users-with-any-of-the-licenses-specified-in-skuidlist)
- [Users that match a query](#users-that-match-a-query)
- [Users that match any query in a list of queries](#users-that-match-any-query-in-a-list-of-queries)
- [Users in a flat file/Google Doc/Google Cloud Storage Object](#users-in-a-flat-filegoogle-docgoogle-cloud-storage-object)
- [Selected users in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object](#selected-users-in-a-csv-filegoogle-sheetgoogle-docgoogle-cloud-storage-object)
- [Users from groups/OUs/courses in a flat file/Google Doc/Google Cloud Storage Object](#users-from-groupsouscourses-in-a-flat-filegoogle-docgoogle-cloud-storage-object)
- [Users from groups/OUs/courses in a CSV file/Google Sheet/Google Doc](#users-from-groupsouscourses-in-a-csv-filegoogle-sheetgoogle-docgoogle-cloud-storage-object)
- [Users directly in or from groups/OUs/courses in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object](#users-directly-in-or-from-groupsouscourses-in-a-csv-filegoogle-sheetgoogle-docgoogle-cloud-storage-object)
- [Users from data fields identified in a `csvkmd` argument](#users-from-data-fields-identified-in-a-csvkmd-argument)
- [Examples using CSV files and Google Sheets to update the membership of a group](#examples-using-csv-files-and-google-sheets-to-update-the-membership-of-a-group)
- [Examples using CSV files to print users from groups](#examples-using-CSV-files-to-print-users-from-groups)
- [Examples using multiple queries](#examples-using-multiple-queries)
## Definitions
* [Basic Items](Basic-Items)
* [List Items](List-Items)
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
```
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
<UserGoogleDoc> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
<UserGoogleSheet> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>) <SheetEntity>
```
```
<DriveFileID> ::= <String>
<DriveFileURL> ::=
https://drive.google.com/open?id=<DriveFileID>
https://drive.google.com/drive/files/<DriveFileID>
https://drive.google.com/drive/folders/<DriveFileID>
https://drive.google.com/drive/folders/<DriveFileID>?resourcekey=<String>
https://drive.google.com/file/d/<DriveFileID>/<String>
https://docs.google.com>/document/d/<DriveFileID>/<String>
https://docs.google.com>/drawings/d/<DriveFileID>/<String>
https://docs.google.com>/forms/d/<DriveFileID>/<String>
https://docs.google.com>/presentation/d/<DriveFileID>/<String>
https://docs.google.com>/spreadsheets/d/<DriveFileID>/<String>
<DriveFileItem> ::= <DriveFileID>|<DriveFileURL>
<DriveFileList> ::= "<DriveFileItem>(,<DriveFileItem>)*"
<DriveFileName> ::= <String>
<DriveFileIDEntity> ::=
(<DriveFileItem>)|(id( |:)<DriveFileItem>)|(ids( |:)<DriveFileList>)
<DriveFileNameEntity> ::=
(drivefilename <DriveFileName>)|(drivefilename:<DriveFileName>)|
(anydrivefilename <DriveFileName>)|(anydrivefilename:<DriveFileName>)
<SharedDriveID> ::= <String>
<SharedDriveName> ::= <String>
<SharedDriveIDEntity> ::= (teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::= (teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
<SharedDriveEntity> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>
<SheetEntity> ::= <String>|id:<Number>
<UserTypeEntity> ::=
(all users|users_ns|users_susp|users_ns_susp)|
(user <UserItem>)|
(users <UserList>)|
(oauthuser)
(domains|domains_ns|domains_susp <DomainNameList>)|
(group|group_ns|group_susp|group_inde <GroupItem>)|
(groups|groups_ns|groups_susp|groups_inde <GroupList>)|
(group_inde <GroupItem>)|(groups_inde <GroupList>)|
(group_users|group_users_ns|group_users_susp <GroupList>
[members] [managers] [owners]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(group_users_select <GroupList>
[members] [managers] [owners]
[notsuspended|suspended] [notarchived|archived]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(ou|ou_ns|ou_susp <OrgUnitItem>)|
(ou_and_children|ou_and_children_ns|ou_and_children_susp <OrgUnitItem>)|
(ous|ous_ns|ous_susp <OrgUnitList>)|
(ous_and_children|ous_and_children_ns|ous_and_children_susp <OrgUnitList>)|
(courseparticipants <CourseIDList>)|
(students <CourseIDList>)|
(teachers <CourseIDList>)|
(license|licenses|licence|licences <SKUIDList>)|
(query <QueryUser>)|
(queries <QueryUserList>)|
(file
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>])|
(csvfile
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])|
(datafile
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>])|
(csvdatafile
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])|
(csvkmd
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
((<FileName>|
(gsheet <UserGoogleSheet>)|
(gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[datafield <FieldName>(:<FieldName>)* [delimiter <Character>]])
(csvdata <FieldName>(:<FieldName>*))
```
## List quoting rules
Items in a list can be separated by commas or spaces; if an item itself contains a comma, a space or a single quote, special quoting must be used.
Typically, you will enclose the entire list in double quotes and quote each item in the list as detailed below.
- Items, separated by commas, without spaces, commas or single quotes in the items themselves
* ```"item,item,item"```
- Items, separated by spaces, without spaces, commas or single quotes in the items themselves
* ```"item item item"```
- Items, separated by commas, with spaces, commas or single quotes in the items themselves
* ```"'it em','it,em',\"it'em\""```
- Items, separated by spaces, with spaces, commas or single quotes in the items themselves
* ```"'it em' 'it,em' \"it'em\""```
Typical places where these rules apply are lists of OUs and Contact Groups.
## User Type Entity
Use these options to select users for GAM commands.
## All non-suspended Users
* `all users`
* `all users_ns`
## All suspended Users
* `all users_susp`
## All non-suspended and suspended Users
* `all users_ns_susp`
## A single User
* `user <UserItem>`
## A list of Users
* `users <UserList>`
## The admin user referenced in oauth2.txt
* `oauthuser`
## Users in the domains `<DomainNameList>`
* `domains|domains_ns|domains_susp <DomainNameList>`
* `domains` - All users
* `domains_ns` - Non-suspended users
* `domains_susp` - Suspended users
## Users directly in the group `<GroupItem>`
* `group|group_ns|group_susp <GroupItem>`
* `group` - All user members
* `group_ns` - Non-suspended user members
* `group_susp` - Suspended user members
## Users directly in the groups `<GroupList>`
* `groups|groups_ns|groups_susp <GroupList>`
* `groups` - All user members
* `groups_ns` - Non-suspended user members
* `groups_susp` - Suspended user members
## Users directly and indirectly in the group `<GroupItem>`
* `group_inde` - All user members including those from all subgroups
## Users directly and indirectly in the groups `<GroupList>`
* `groups_inde` - All user members including those from all subgroups
## Selected Users from groups
* `group_users|group_users_ns|group_users_susp <GroupList> [members] [managers] [owners] [primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end`
* `group_users` - All user members
* `group_users_ns` - Non-suspended user members
* `group_users_susp` - Suspended user members
* `[members] [managers] [owners]` - The desired roles; if roles are not specified, all roles are included
* `primarydomain` - Select Users from the primary domain
* `domains <DomainNameList>` - Select Users from the list of domains
* `recursive` - Select Users from all subgroups; do not select Users from a member of type CUSTOMER (all users in a domain); GAM performs the recursion
* `includederivedmembership` - Select Users from all subgroups; do select Users from a member of type CUSTOMER (all users in a domain); the API performs the recursion but produces inconsistent results, use with caution
* `end` - Terminate the selection
* `group_users_select <GroupList> [members] [managers] [owners] [notsuspended|suspended] [notarchived|archived] [primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end`
* `[members] [managers] [owners]` - The desired roles; if roles are not specified, all roles are included
* By default, memebers of all statuses are included
* `notsuspended` - Do not include suspended users, this is common
* `suspended` - Only include suspended users, this is not common but allows creating groups that allow easy identification of suspended users
* `notarchived` - Do not include archived members
* `archived` - Only include archived members, this is not common but allows creating groups that allow easy identification of archived users
* `notsuspended notarchived` - Do not include suspended and archived members
* `suspended archived` - Include only suspended or archived members
* `notsuspended archived` - Only include archived members, this is not common but allows creating groups that allow easy identification of archived users
* `suspended notarchived` - Only include suspended users, this is not common but allows creating groups that allow easy identification of suspended users
* `primarydomain` - Select Users from the primary domain
* `domains <DomainNameList>` - Select Users from the list of domains
* `recursive` - Select Users from all subgroups; do not select Users from a member of type CUSTOMER (all users in a domain); GAM performs the recursion
* `includederivedmembership` - Select Users from all subgroups; do select Users from a member of type CUSTOMER (all users in a domain); the API performs the recursion but produces inconsistent results, use with caution
* `end` - Terminate the selection
## Users directly in the Cloud Identity group `<GroupItem>`
* `cigroup <GroupItem>`
* `cigroup` - All user members
## Users directly in the Cloud Identity groups `<GroupList>`
* `cigroups <GroupList>`
* `cigroups` - All user members
## Selected Users from Cloud Identity groups
* `cigroup_users <GroupList> [members] [managers] [owners>] [recursive] end`
* `cigroup_users` - All user members
* `[members] [managers] [owners]` - The desired roles; if roles are not specified, all roles are included
* `recursive` - Select Users from all subgroups; do not select Users from a member of type CUSTOMER (all users in a domain); GAM performs the recursion
* `end` - Terminate the selection
## Users directly in the Organization Unit `<OrgUnitItem>`
* `ou|ou_ns|ou_susp <OrgUnitItem>`
* `ou` - All users
* `ou_ns` - Non-Suspended users
* `ou_susp` - Suspended users
## Users in the Organization Unit `<OrgUnitItem>` and all of its sub Organization Units
* `ou_and_children|ou_and_children_ns|ou_and_children_susp <OrgUnitItem>`
* `ou_and_children` - All users
* `ou_and_children_ns` - Non-suspended users
* `ou_and_children_susp` - Suspended users
## Users directly in the Organization Units `<OrgUnitList>`
* `ous|ous_ns|ous_susp <OrgUnitList>` - Users directly in the Organization Units `<OrgUnitList>`
* `ous` - All users
* `ous_ns` - Non-suspended users
* `ous_susp` - Suspended users
`<OrgUnitList>` may require special quoting based on whether the OUs contain spaces, commas or single quotes.
For quoting rules, see: [List Items](List-Items)
## Users in the Organization Units `<OrgUnitList>` and all of their sub Organization Units
* `ous_and_children|ous_and_children_ns|ous_and_children_susp <OrgUnitList>` - Users in the Organization Units `<OrgUnitList>` and all of their sub Organization Units
* `ous_and_children` - All users
* `ous_and_children_ns` - Non-suspended users
* `ous_and_children_susp` - Suspended users
`<OrgUnitList>` may require special quoting based on whether the OUs contain spaces, commas or single quotes.
For quoting rules, see: [List Items](List-Items)
## All of the students and teachers in the courses specified in `<CourseIDList>`
* `courseparticipants <CourseIDList>`
## All of the students in the courses specified in `<CourseIDList>`
* `students <CourseIDList>`
## All of the teachers in the courses specified in `<CourseIDList>`
* `teachers <CourseIDList>`
## All Users with any of the licenses specified in `<SKUIDList>`
* `license|licenses|licence|licences <SKUIDList>`
## Users that match a query
* `query <QueryUser>`
See https://developers.google.com/admin-sdk/directory/v1/guides/search-users
## Users that match any query in a list of queries
* `queries <QueryUserList>`
See https://developers.google.com/admin-sdk/directory/v1/guides/search-users
`<QueryUserList>` may require special quoting based on whether the queries contain spaces, commas or single quotes.
* Surround `<QueryCrOSList>` with `" "`
* Surround each query with `\" \"`, separate the queries with commas.
```
queries "\"orgUnitPath='/Path/To/OU 1' isSuspended=False\",\"orgUnitPath='/Path/To/OU 2' isSuspended=False\",\"orgUnitPath='/Path/To/OU 3' isSuspended=False\""
```
Note that the results are all users who match one or more of the queries. In other words this is "OR" logic, and you get the union of all matching results.
For quoting rules, see: [List Items](List-Items)
## Users in a flat file/Google Doc/Google Cloud Storage Object
```
file
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>]
```
* `<FileName>` - A flat file containing a single User per row
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gdoc <UserGoogleDoc>` - A Google Doc containing a single User per row
* `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing a single User per row
* `delimiter <Character>` - There are multiple Users per row separated by `<Character>`; if not specified, there is single user per row
## Selected users in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
```
csvfile
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>]
```
* `<FileName>(:<FieldName>)+` - A CSV file and the one or more columns that contain Users
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gsheet(:<FieldName>)+ <UserGoogleSheet>` - A Google Sheet and the one or more columns that contain Users
* `gdoc(:<FieldName>)+ <UserGoogleDoc>` - A Google Doc and the one or more columns that contain Users
* `gcscsv(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain Users
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain Users
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `delimiter <Character>` - There are multiple Users per column separated by `<Character>`; if not specified, there is single user per column
## Users from groups/OUs/courses in a flat file/Google Doc/Google Cloud Storage Object
```
datafile
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>]
```
* `users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|ous_and_children|ous_and_children_ns|ous_and_children_susp|courseparticipants|students|teachers` - The type of item in the file
* `<FileName>` - A flat file containing rows of the type of item specified
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gdoc <UserGoogleDoc>` - A Google Doc containing rows of the type of item specified
* `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing rows of the type of item specified
* `delimiter <Character>` - There are multiple items per row separated by `<Character>`; if not specified, there is single item per row
## Users from groups/OUs/courses in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
```
csvdatafile
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>]
```
* `users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|ous_and_children|ous_and_children_ns|ous_and_children_susp|courseparticipants|students|teachers` - The type of item in the file
* `<FileName>(:<FieldName>)+` - A CSV file and the one or more columns contain the type of item specified
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gsheet(:<FieldName>)+ <UserGoogleSheet>` - A Google Sheet and the one or more columns contain the type of item specified
* `gdoc(:<FieldName>)+ <UserGoogleDoc>` - A Google Doc and the one or more columns contain the type of item specified
* `gcscsv(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns contain the type of item specified
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns contain the type of item specified
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `delimiter <Character>` - There are multiple Users per column separated by `<Character>`; if not specified, there is single user per column
## Users directly in or from groups/OUs/courses in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
```
csvkmd
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
((<FileName>|
(gsheet <UserGoogleSheet>)|
(gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[datafield <FieldName>(:<FieldName>)* [delimiter <Character>]]
```
* `users|groups|groups_ns_|groups_susp|groups_inde|ous|ous_ns|ous_susp|ous_and_children|ous_and_children_ns|ous_and_children_susp|courseparticipants|students|teachers` - The type of item in the file
* `<FileName>` - A CSV file containing rows with columns of the type of item specified
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gsheet <UserGoogleSheet>` - A Google Sheet containing rows with columns of the type of item specified
* `gdoc <UserGoogleDoc>` - A Google Doc containing rows with columns of the type of item specified
* `gcscsv <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object with columns of the type of item specified
* `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object with columns of the type of item specified
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>])+`
* `keyfield <FieldName>` - The column containing key values
* `[keypattern <RegularExpression>] [keyvalue <String>]` - Allows transforming the value(s) in the `keyfield` column. If only `keyvalue <String>` is specified, all instances of `<FieldName>` in `keyvalue <String>` will be replaced by the item value. If `keypattern <RegularExpression>` is specified, the item value is matched against `<RegularExpression>` and the matched segments are substituted into `keyvalue <String>`
* `delimiter <Character>` - There are multiple values per keyfield column separated by `<Character>`; if not specified, there is single value per keyfield column
* `(subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>])*`
* `subkeyfield <FieldName>` - The column containing subkey values
* `[keypattern <RegularExpression>] [keyvalue <String>]` - Allows transforming the value(s) in the `subkeyfield` column. If only `keyvalue <String>` is specified, all instances of `<FieldName>` in `keyvalue <String>` will be replaced by the item value. If `keypattern <RegularExpression>` is specified, the item value is matched against `<RegularExpression>` and the matched segments are substituted into `keyvalue <String>`
* `delimiter <Character>` - There are multiple values per subkeyfield column separated by `<Character>`; if not specified, there is single value per subkeyfield column
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `(datafield <FieldName>(:<FieldName)* [delimiter <Character>])*`
* `datafield <FieldName>(:<FieldName)*` - The column(s) containing data values
* `delimiter <Character>` - There are multiple values per datafield column separated by `<Character>`; if not specified, there is single value per datafield column
## Users from data fields identified in a `csvkmd` argument
* `csvdata <FieldName>(:<FieldName>*)`
## Examples using CSV files and Google Sheets to update the membership of a group
### Example 1
The file Users.csv has a single column of email addresses, there is no header row.
```
user1@domain.com
user2@domain.com
...
gam update group group@domain.com sync members file Users.csv
```
The Google Sheet `user@domain.com <DriveFileID> <SheetEntity>` has a single column of email addresses, there is no header row.
Define an implicit header with the `fields Email` option.
```
user1@domain.com
user2@domain.com
...
gam update group group@domain.com sync members csvfile gsheet:Email user@domain.com <DriveFileID> <SheetEntity> fields Email
```
The Google Doc `user@domain.com <DriveFileID>` has a single column of email addresses, there is no header row.
```
user1@domain.com
user2@domain.com
...
gam update group group@domain.com sync members file gdoc user@domain.com <DriveFileID>
```
### Example 2
The CSV file Users.csv has one column of email addresses labelled Email.
```
Email
user1@domain.com
user2@domain.com
...
gam update group group@domain.com sync members csvfile Users.csv:Email
```
The Google Sheet `user@domain.com <DriveFileID> <SheetEntity>` has one column of email addresses labelled Email.
```
Email
user1@domain.com
user2@domain.com
...
gam update group group@domain.com sync members csvfile gsheet:Email user@domain.com <DriveFileID> <SheetEntity>
```
### Example 3
The CSV file Users.csv has two columns of email addresses labelled Email1 and Email2.
```
Email1,Email2
user1@domain.com,user2@domain.com
user3@domain.com,user4@domain.com
...
gam update group group@domain.com sync members csvfile Users.csv:Email1:Email2
```
The Google Sheet `user@domain.com <DriveFileID> <SheetEntity>` has two columns of email addresses labelled Email1 and Email2.
```
Email1,Email2
user1@domain.com,user2@domain.com
user3@domain.com,user4@domain.com
...
gam update group group@domain.com sync members csvfile gsheet:Email1:Email2 user@domain.com <DriveFileID> <SheetEntity>
```
### Example 4
The file Groups.txt has a single column of group email addresses, there is no header row.
You want to sync with the members of those groups.
```
group1@domain.com
group2@domain.com
...
gam update group group@domain.com sync members datafile groups Groups.txt
```
The Google Doc `user@domain.com <DriveFileID>` has a single column of group email addresses, there is no header row.
You want to sync with the members of those groups.
```
group1@domain.com
group2@domain.com
...
gam update group group@domain.com sync members datafile groups gdoc user@domain.com <DriveFileID>
```
### Example 5
The CSV file Groups.csv has a single column of group email addresses labelled Group.
You want to sync with the members of those groups.
```
Group
group1@domain.com
group2@domain.com
...
gam update group group@domain.com sync members csvdatafile groups Groups.csv:Group
```
The Google Sheet `user@domain.com <DriveFileID> <SheetEntity>` has a single column of group email addresses labelled Group.
You want to sync with the members of those groups.
```
Group
group1@domain.com
group2@domain.com
...
gam update group group@domain.com sync members csvdatafile groups gsheet:Group user@domain.com <DriveFileID> <SheetEntity>
```
### Example 6
The CSV file GroupMembers.csv has headers: group,role,email
Each row contains a group email address, member role (OWNER, MEMBER, MANAGER) and a member email address.
The following command will synchronize the membership for all groups and roles.
```
gam redirect stdout ./MemberUpdates.txt redirect stderr stdout update group csvkmd GroupMembers.csv keyfield group subkeyfield role datafield email sync csvdata email
```
The Google Sheet `user@domain.com <DriveFileID> <SheetEntity>` has headers: group,role,email
Each row contains a group email address, member role (OWNER, MEMBER, MANAGER) and a member email address.
The following command will synchronize the membership for all groups and roles.
```
gam redirect stdout ./MemberUpdates.txt redirect stderr stdout update group csvkmd gsheet user@domain.com <DriveFileID> <SheetEntity> keyfield group subkeyfield role datafield email sync csvdata email
```
## Examples using CSV files to print users from groups
You want to print the membership of a collection of parent groups at your school based on graduation year.
### Example 1
The CSV File Group.csv has exactly the data you want, `keypattern` and `keyvalue` are not required.
```
Group
2020-parents@domain.com
2021-parents@domain.com
...
```
For each row, the value from the Group column is used as the group name.
```
gam csvkmd groups Group.csv keyfield Group print users
```
### Example 2
The CSV File GradYear.csv has graduation years; you have to convert GradYear to group name `GradYear-parents@domain.com`, `keyvalue` is required.
```
GradYear
2020
2021
...
```
For each row, the value from the GradYear column replaces the keyField name in the `keyvalue` argument and that value is used as the group name.
```
gam csvkmd group GradYear.csv keyfield GradYear keyvalue GradYear-parents@domain.com print users
```
### Example 3
The CSV File GradYear.csv has graduation years; you have to convert GradYear to group name `LastTwoDigitsOfGradYear-parents@domain.com`, `keypattern` and `keyvalue` are required.
```
GradYear
2020
2021
...
```
For each row, the value from the GradYear column is matched against the `keypattern` and the matched segments are substituted into the `keyvalue` argument and that value is used as the group name.
```
gam csvkmd group GradYear.csv keyfield GradYear keypattern '20(..)' keyvalue '\1-parents@domain.com' print users
```
## Examples using multiple queries
### Example 1
Print users who are specialists or technicians:
```
gam queries "orgTitle=Specialist,orgTitle=Technician" print users allfields
```
### Example 2
Print users who are have the title Manager in the sales org or anyone in the marketing org:
```
gam queries "\"orgName='Sales Org' orgTitle=Manager\",\"orgName='Marketing Org'\"" print users allfields
````
### Example 3
Print users in either of two Org Units that contain spaces in their names.
```
gam queries "\"orgUnitPath='/Students/Middle School/2021'\",\"orgUnitPath='/Students/Middle School/2020'\"" print users allfields
```
This is equivaluent to:
```
gam ous "'/Students/Middle School/2021','/Students/Middle School/2020'" print users allfields
```

View File

@ -0,0 +1,109 @@
# Command data from Google Docs, Sheets and Cloud Storage
- [Introduction](#introduction)
- [Definitions](#definitions)
- [Read data from a Google Doc or Drive File](#read-data-from-a-google-doc-or-drive-file)
- [Plain Text](#plain-text)
- [HTML](#html)
- [Read data from a Google Sheet](#read-data-from-a-google-sheet)
- [Read data from a Google Cloud Storage File](#read-data-from-a-google-cloud-storage-file)
- [Plain Text](#plain-text)
- [CSV](#csv)
- [HTML](#html)
## Introduction
Google Sheets can be used in `gam csv ...` commands.
* [Bulk Processing](Bulk-Processing)
Google Docs and Sheets can be used to specify collections of data.
* [Collections of ChromeOS Devices](Collections-of-ChromeOS-Devices)
* [Collections of Items](Collections-of-Items)
* [Collections of Users](Collections-of-Users)
Google Docs and Drive Files can be used to specify notes, messages and signatures.
* [Domain Shared Contacts - Global Address List](Contacts-GAL)
* [Send Email](Send-Email)
* [Users](Users)
* [Users - Contacts](Users-Contacts)
* [Users - Gmail - Messages/Threads](Users-Gmail-Messages-Threads)
* [Users - Gmail - SendAs/Signature/Vacation](Users-Gmail-Send-As-Signature-Vacation)
## Definitions
* [Drive Items](Drive-Items)
## Read data from a Google Doc or Drive File
```
<UserGoogleDoc> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
```
* `<EmailAddress>` - The email address of a user with at least read access to the document
Use one of the following to specify the file:
* `<DriveFileIDEntity>` - The ID of the file on a Drive or Shared Drive
* `<DriveFileNameEntity>` - The name of the file
* `<SharedDriveEntity> <SharedDriveFileNameEntity>` - A Shared Drive and the name of the file on that drive
## Plain Text
Interpret a Google Doc as plain text or read a Drive file with MIME type text/plain.
```
gdoc <UserGoogleDoc>
```
## HTML
Read a Drive file with MIME type text/html.
```
ghtml <UserGoogleDoc>
```
## Read data from a Google Sheet
```
<SheetEntity> ::= <String>|id:<Number>
<UserGoogleSheet> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>) <SheetEntity>
```
* `<EmailAddress>` - The email address of a user with at least read access to the document
Use one of the following to specify the file:
* `<DriveFileIDEntity>` - The ID of the file on a Drive or Shared Drive
* `<DriveFileNameEntity>` - The name of the file
* `<SharedDriveEntity> <SharedDriveFileNameEntity>` - A Shared Drive and the name of the file on that drive
If a file name is specified, it must resolve to a single file ID; otherwise an error is generated.
If a Shared Drive name is specified, it must resolve to a single Shared Drive ID; otherwise an error is generated.
Select a sheet/tab from the Google Sheet with its ID or name; it is verified to exist within the Google Sheet.
Example:
```
gam csv gsheet you@exmaple.com <DriveFileIDEntity> "Sheet 1" gam create user firstname "~FirstName" lastname "~lastName" email "~email"
```
## Read data from a Google Cloud Storage File
```
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
```
## CSV
Read a Google Cloud Storage file with contentType text/csv.
```
gcscsv <StorageBucketObjectName>
```
## Plain Text
Read a Google Cloud Storage file with contentType text/plain.
```
gcsdoc <StorageBucketObjectName>
```
## HTML
Read a Google Cloud Storage file with contentType text/html.
```
gcshtml <StorageBucketObjectName>
```

View File

@ -0,0 +1,58 @@
# Command Line Parsing
- [Linux and MacOS](#linux-and-macos)
- [Windows Command Prompt](#windows-command-prompt)
- [Windows PowerShell](#windows-powershell)
- [List quoting rules](#list-quoting-rules)
## Linux and MacOS
When entering `gam csv` commands, you should enclose references to CSV file headers in `"`; e.g., `name "~name"`.
In bash, if an argument contains a `~`, `|`, `>`, or `<`, you must enclose the argument in `"`; e.g., `name "Test|Group"`.
In zsh, if an argument contains a `~`, `|`, `!`, `>`, or `<`, you must enclose the argument in `'`; e.g., `name 'Test|Group'`.
To embed a `'` in a string enclosed in `"`, enter `'`; `name "Test'Group"`.
To embed a `"` in a string enclosed in `'`, enter `"`; `name 'Test"Group'`.
Linux and MacOS do not recognize smart or curly quotes, `“` and `”`, they can not be used to enclose arguments.
## Windows Command Prompt
Command Prompt does not recognize smart or curly quotes, `“` and `”`, they can not be used to enclose arguments.
Command Prompt does not recognize single quotes, `'`, they can not be used to enclose arguments.
To embed a `'` in a string enclosed in `"`, enter `'`; `name "Test'Group"`.
To embed a `"` in a string enclosed in `"`, enter `\"`; `name "Test\"Group"`.
## Windows PowerShell
In PowerShell, if you want an empty string argument, you must enter: ``` `"`" ```
PowerShell does not recognize smart or curly quotes, `` and ``, they can not be used to enclose arguments.
To embed a `'` in a string enclosed in `"`, enter `'`; `name "Test'Group"`.
To embed a `"` in a string enclosed in `"`, enter ``` `" ```; ```name "Test`"Group"```.
To embed a `'` in a string enclosed in `'`, enter `''`; `name 'Test''Group'`.
To embed a `"` in a string enclosed in `'`, enter `\"`; `name 'Test\"Group'`.
## List quoting rules
Items in a list can be separated by commas or spaces; if an item itself contains a comma, a space or a single quote, special quoting must be used.
Typically, you will enclose the entire list in double quotes and quote each item in the list as detailed below.
- Items, separated by commas, without spaces, commas or single quotes in the items themselves
* ```"item,item,item"```
- Items, separated by spaces, without spaces, commas or single quotes in the items themselves
* ```"item item item"```
- Items, separated by commas, with spaces, commas or single quotes in the items themselves
* ```"'it em','it,em',\"it'em\""```
- Items, separated by spaces, with spaces, commas or single quotes in the items themselves
* ```"'it em' 'it,em' \"it'em\""```
Typical places where these rules apply are lists of OUs and Contact Groups.

View File

@ -0,0 +1,88 @@
# Command Logging and Progress
- [Introduction](#introduction)
- [GAM Configuration](gam.cfg)
- [Command Logging](#command-logging)
- [Command Progress](#command-progress)
## Introduction
Starting with version 6.07.00, GAM can log its commands to a file.
Display of `gam batch|tbatch|csv|loop` progress messages has been improved.
## Command Logging
The following keywords in `gam.cfg` control logging of GAM commands.
```
cmdlog
Path to GAM Log file; there is no logging if cmdlog is empty
Default: ''
cmdlog_max_backups
Maximum number of backup log files
Default: 5
Range: 1 - 10
cmdlog_max_kilo_bytes
Maximum kilobytes per log file
Default: 1000
Range: 100 - 10000
```
If `cmdlog` specifies a relative file path, it is appended to `config_dir` in the current section if defined or `config_dir` in `[DEFAULT]`.
This makes it easy to have distinct log files when you have multiple clients/tenants defined in `gam.cfg`
You use the `cmdlog_max_kilo_bytes` and `cmdlog_max_backups` values to cause the log file to rollover at a predetermined size.
When the log file is nearly `cmdlog_max_kilo_bytes` in length, it is closed and a new log file is silently opened for output.
The system will save old log files by appending `.N`, to the filename. For example, with a `cmdlog_max_backups` of 5 and a base log file name of `gam.log`, you would get `gam.log`, `gam.log.1`, `gam.log.2`, up to `gam.log.5`.
The log file being written to is always `gam.log`. When this log file is filled, it is closed and renamed to `gam.log.1`, and if files `gam.log.1`, `gam.log.2`, etc. exist, then they are renamed to `gam.log.2`, `gam.log.3` etc. respectively.
Commands are logged at completion with a timestamp, return code and the command line
```
2021-08-01T19:350:30.777-07:00,0,/Users/admin/bin/gamadv-xtd3/gam info domain
```
Commands that generate sub-commands, `gam batch|tbatch|csv|loop`, log the initial command with a return code of `*`,
the sub-command lines and the initial command with a numeric return code.
```
$ gam redirect stdout usernames.csv multiprocess redirect stderr stdout csv users.csv gam info user "~primaryEmail" quick name
2021-08-01T19:50:38.151-07:00,0/6,Using 6 processes...
$ more ~/.gam/gam.log
2021-08-01T19:50:38.120-07:00,*,/Users/admin/bin/gamadv-xtd3/gam redirect stdout usernames.csv multiprocess redirect stderr stdout csv users.csv showcmds false gam info user ~primaryEmail quick name
2021-08-01T19:50:39.144-07:00,0,gam info user testuser2 quick name
2021-08-01T19:50:39.358-07:00,0,gam info user testuser3 quick name
2021-08-01T19:50:39.358-07:00,0,gam info user testuser1 quick name
2021-08-01T19:50:39.401-07:00,0,gam info user testuser5 quick name
2021-08-01T19:50:39.459-07:00,56,gam info user testuserx quick name
2021-08-01T19:50:39.470-07:00,0,gam info user testuser4 quick name
2021-08-01T19:50:39.483-07:00,0,/Users/admin/bin/gamadv-xtd3/gam redirect stdout usernames.csv multiprocess redirect stderr stdout csv users.csv showcmds false gam info user ~primaryEmail quick name
```
## Command Progress
Added the following keyword to `gam.cfg` to display sub-commands to stderr when executing `gam batch|tbatch|csv|loop`.
The commands are displayed when initiated/completed so you can monitor GAM's progress.
```
show_commands
Display commands to stderr when executing `gam batch|tbatch|csv|loop`.
Default: False
```
This value will be used when not overridden by the `showcmds [<Boolean>]` command line option; see [Bulk Processing](Bulk-Processing).
Sub-commands are displayed at initiation with a timestamp, index/total, Start, 0 and the sub-command line.
Sub-commands are displayed at completion with a timestamp, index/total, End, return code and the sub-command line.
```
$ gam redirect stdout usernames.csv multiprocess redirect stderr stdout csv users.csv showcmds true gam info user "~primaryEmail" quick name
2021-08-01T19:46:07.845-07:00,0/6,Using 6 processes...
2021-08-01T19:46:07.846-07:00,1/6,Start,0,gam info user testuser1 quick name
2021-08-01T19:46:07.846-07:00,2/6,Start,0,gam info user testuser2 quick name
2021-08-01T19:46:07.846-07:00,3/6,Start,0,gam info user testuser3 quick name
2021-08-01T19:46:07.846-07:00,4/6,Start,0,gam info user testuser4 quick name
2021-08-01T19:46:07.846-07:00,5/6,Start,0,gam info user testuser5 quick name
2021-08-01T19:46:07.846-07:00,6/6,Start,0,gam info user testuserx quick name
2021-08-01T19:46:08.827-07:00,3/6,End,0,gam info user testuser3 quick name
2021-08-01T19:46:08.983-07:00,2/6,End,0,gam info user testuser2 quick name
2021-08-01T19:46:08.983-07:00,1/6,End,0,gam info user testuser1 quick name
2021-08-01T19:46:09.049-07:00,6/6,End,56,gam info user testuserx quick name
2021-08-01T19:46:09.059-07:00,5/6,End,0,gam info user testuser5 quick name
2021-08-01T19:46:09.079-07:00,4/6,End,0,gam info user testuser4 quick name
2021-08-01T19:46:09.083-07:00,0/6,Complete
```

View File

@ -0,0 +1,454 @@
# Context-Aware Access Levels
- [Notes](#Notes)
- [Context-Aware Access documentation](https://support.google.com/a/answer/9275380)
- [API documentation](#api-documentation)
- [Grant Service Account Rights to Manage CAA](#grant-service-account-rights-to-manage-caa)
- [Definitions](#definitions)
- [Parameters for Basic Levels](#parameters-for-basic-levels)
- [Create an Access Level](#create-an-access-level)
- [Update an Access Level](#update-an-access-level)
- [Delete an Access Level](#delete-an-access-level)
- [Display all Access Levels](#display-all-access-levels)
- [CAA Region Codes](#caa-region-codes)
## Notes
This Wiki page was built directly from Jay Lee's Wiki page; my sincere thanks for his efforts.
GAM 6.20.00 and newer can create and manage access levels which can be assigned to Workspace services for your users.
To use these features you must update your project.
```
gam update project
```
## API documentation
* https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies/list
## Grant Service Account Rights to Manage CAA
In order for GAM to manage CAA access levels, you need to grant your service account a special role for your GCP organization.
1. Run a GAM command like `gam print caalevels`. This will show you the service account email and role you need to grant it. Copy the service account email.
2. You can also get the value from oauth2service.json: `"client_email": "gam-project-abc-123-xyz@gam-project-abc-123-xyz.iam.gserviceaccount.com"`
3. As an organization admin (Workspace Super Admin should work) go to [https://console.cloud.google.com/iam-admin/iam](https://console.cloud.google.com/iam-admin/iam).
4. In the top blue bar, to the right of `Google Cloud Platform` click the desired `<Project Name>`.
5. If the page shows `Permissions for organization <Primary Domain>`", skip the next step.
6. If the page shows `Permissions for project <Project Name>`", click the building icon immediately to the left of your `<Primary Domain>` in the Inheritance column.
7. Near the top click `Add`.
8. Enter the service account email address you recorded earlier into the `New principals*` box.
9. In the `Select a role*` box, select Access Context Manager > Access Context Manager Editor.
10. Click `Save`. It may take 15 minutes or more for the role permissions to propagate.
11. Confirm the role is in place by re-running `gam print caalevels`
## Definitions
```
<QueryCEL> ::= <String>
See: https://cloud.google.com/access-context-manager/docs/custom-access-level-spec
<CAALevelName> ::= <String>
<CAAAllowedEncryptionStatus> ::=
encryption_unsupported |
encrypted |
unencrypted
<CAAAllowedEncryptionStatusList> ::= "<CAAAllowedEncryptionStatus>(,<CAAAllowedEncryptionStatus>)"
<CAAAllowedDeviceManagementLevel> ::=
basic |
advanced|complete |
none
<CAAAllowedDeviceManagementLevelList> ::= "<CAAAllowedDeviceManagementLevel>(,<CAAAllowedDeviceManagementLevel>)"
<CAACombiningFunction> ::=
and |
or
<CAAIPSubNetwork> ::=
<CIDRnetmask>
<CAAIPSubNetworkList> ::= "<CAAIPSubNetwork>(,<CAAIPSubNetwork>)"
<CAAMember> ::=
user:<EmailAddress> |
serviceAccount:<EmailAddress>
<CAAMemberList> ::= "<CAAMember>(,<CAAMember>)"
<CAAOsType> ::=
DESKTOP_MAC |
DESKTOP_WINDOWS |
DESKTOP_LINUX |
DESKTOP_CHROME_OS |
VERIFIED_DESKTOP_CHROME_OS |
ANDROID |
IOS
<CAAOsConstraint> ::=
<CAAOsType> |
<CAAOsType>:<String>.<String>.<String>
<CAAOsConstraintList> ::= "<CAAOsConstraint>(,<CAAOsConstraint>)"
<CAARegion> ::=
<Character><Character>
<CAARegionList> ::= "<CAARegion>(,<CAARegion>)"
<CAADevicePolicyAttribute> ::=
(requirescreenlock <Boolean>) |
(allowedencryptionstatuses <CAAAllowedEncryptionStatusList>) |
(osconstraints <CAAOsConstraintList>) |
(alloweddevicemanagementlevels <CAAAllowedDeviceManagementLevelList>) |
(requireadminapproval <Boolean>) |
(requirecorpowned <Boolean>) # See: https://www.iso.org/obp/ui/#search
<CAAConditionAttribute> ::=
(ipsubnetworks <CAAIPSubNetworkList>) |
(devicepolicy <CAADevicePolicyAttribute> enddevicepolicy) |
(requiredaccesslevels <StringList>) |
(negate <Boolean>) |
(members <CAAMemberList>) |
(regions <CAARegionList>)
<CAABasicAttribute> ::+
(combiningfunction <CAACombiningFunction>) |
(condition <CAAConditionAttribute>+ endcondition)
```
# Parameters for Basic Levels
```
basic
combiningfunction and|or
condition
negate true|false
ipsubnetworks ip4range,ip6range,...
regions <country code>,country code>,...
devicepolicy
requirescreenlock true|false
allowedencryptionstatuses ENCRYPTION_UNSUPPORTED,ENCRYPTED,UNENCRYPTED
alloweddevicemanagementlevels NONE,BASIC,COMPLETE
requireadminapproval true|false
requirecorpowned true|false
osconstraints DESKTOP_MAC:version,DESKTOP_WINDOWS:version,DESKTOP_LINUX:version,
DESKTOP_CHROME_OS:version,VERIFIED_DESKTOP_CHROME_OS:version,
ANDROID:version,IOS:version
enddevicepolicy
endcondition
condition
...
endcondition
```
* The combiningfunction argument specifies if a user must pass all 2+ conditions (AND) or only one (OR).
* The negate argument specifies whether a user that matches the condition passes it or fails.
* The ipsubnetworks argument specifies a comma-separated list of IPv4 or IPv6 networks the user must be coming from to match.
* The regions argument specifies a comma-separated list of country/regions the user must be coming from to match.
* The device policy argument specifies characteristics of the user's device that must be present to match.
## Create an Access Level
Create a new access level. CAA supports basic and custom conditions.
```
gam create caalevel <String> [description <String>] (basic <CAABasicAttribute>+)|(custom <QueryCEL>)
```
## Example
This example defines a custom access level that requires the user to use a Cloud-managed Chrome browser (CBCM) or be logged into a Cloud-managed Chrome profile.
```
gam create caalevel custom "device.chrome.management_state == ChromeManagementState.CHROME_MANAGEMENT_STATE_BROWSER_MANAGED | ChromeManagementState.CHROME_MANAGEMENT_STATE_PROFILE_MANAGED"
```
This example creates a basic access level that requires the user to come from the US or Canada regions
```
gam create caalevel CORP_COUNTRIES basic condition regions US,CA endcondition
```
This example creates a basic access level that requires the user come from one of the given IP ranges
```
gam create caalevel CORP_IPS basic condition ipsubnetworks 1.2.3.0/24,4.5.6.0/24 endcondition
```
----
## Update an Access Level
Updates an existing access level. CAA supports basic and custom conditions.
```
gam update caalevel <CAALevelName> [description <String>] (basic <CAABasicAttribute>+)|(custom <QueryCEL>)
```
## Examples
This example adds UK to the allowed regions for CORP_COUNTRIES
```
gam update caalevel CORP_COUNTRIES basic condition regions US,CA,UK endcondition
```
## Delete an Access Level
Deletes the specified access level.
```
gam delete caalevel <CAALevelName>
```
# Display all access levels
```
gam show caalevels
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values:
* `formatjson` - Display the fields in JSON format.
```
gam print caalevels [todrive <ToDriveAttribute>*]
[formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format:
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## CAA Region Codes
```
AD: Andorra
AE: United Arab Emirates
AF: Afghanistan
AG: Antigua and Barbuda
AI: Anguilla
AL: Albania
AM: Armenia
AO: Angola
AQ: Antarctica
AR: Argentina
AS: American Samoa
AT: Austria
AU: Australia
AW: Aruba
AX: Åland Islands
AZ: Azerbaijan
BA: Bosnia and Herzegovina
BB: Barbados
BD: Bangladesh
BE: Belgium
BF: Burkina Faso
BG: Bulgaria
BH: Bahrain
BI: Burundi
BJ: Benin
BL: Saint Barthélemy
BM: Bermuda
BN: Brunei Darussalam
BO: Bolivia Plurinational State of
BQ: Bonaire Sint Eustatius and Saba
BR: Brazil
BS: Bahamas
BT: Bhutan
BV: Bouvet Island
BW: Botswana
BY: Belarus
BZ: Belize
CA: Canada
CC: Cocos (Keeling) Islands
CD: Congo The Democratic Republic of the
CF: Central African Republic
CG: Congo
CH: Switzerland
CI: Côte d'Ivoire
CK: Cook Islands
CL: Chile
CM: Cameroon
CN: China
CO: Colombia
CR: Costa Rica
CU: Cuba
CV: Cabo Verde
CW: Curaçao
CX: Christmas Island
CY: Cyprus
CZ: Czechia
DE: Germany
DJ: Djibouti
DK: Denmark
DM: Dominica
DO: Dominican Republic
DZ: Algeria
EC: Ecuador
EE: Estonia
EG: Egypt
EH: Western Sahara
ER: Eritrea
ES: Spain
ET: Ethiopia
FI: Finland
FJ: Fiji
FK: Falkland Islands (Malvinas)
FM: Micronesia Federated States of
FO: Faroe Islands
FR: France
GA: Gabon
GB: United Kingdom
GD: Grenada
GE: Georgia
GF: French Guiana
GG: Guernsey
GH: Ghana
GI: Gibraltar
GL: Greenland
GM: Gambia
GN: Guinea
GP: Guadeloupe
GQ: Equatorial Guinea
GR: Greece
GS: South Georgia and the South Sandwich Islands
GT: Guatemala
GU: Guam
GW: Guinea-Bissau
GY: Guyana
HK: Hong Kong
HM: Heard Island and McDonald Islands
HN: Honduras
HR: Croatia
HT: Haiti
HU: Hungary
ID: Indonesia
IE: Ireland
IL: Israel
IM: Isle of Man
IN: India
IO: British Indian Ocean Territory
IQ: Iraq
IR: Iran Islamic Republic of
IS: Iceland
IT: Italy
JE: Jersey
JM: Jamaica
JO: Jordan
JP: Japan
KE: Kenya
KG: Kyrgyzstan
KH: Cambodia
KI: Kiribati
KM: Comoros
KN: Saint Kitts and Nevis
KP: Korea Democratic People's Republic of
KR: Korea Republic of
KW: Kuwait
KY: Cayman Islands
KZ: Kazakhstan
LA: Lao People's Democratic Republic
LB: Lebanon
LC: Saint Lucia
LI: Liechtenstein
LK: Sri Lanka
LR: Liberia
LS: Lesotho
LT: Lithuania
LU: Luxembourg
LV: Latvia
LY: Libya
MA: Morocco
MC: Monaco
MD: Moldova Republic of
ME: Montenegro
MF: Saint Martin (French part)
MG: Madagascar
MH: Marshall Islands
MK: North Macedonia
ML: Mali
MM: Myanmar
MN: Mongolia
MO: Macao
MP: Northern Mariana Islands
MQ: Martinique
MR: Mauritania
MS: Montserrat
MT: Malta
MU: Mauritius
MV: Maldives
MW: Malawi
MX: Mexico
MY: Malaysia
MZ: Mozambique
NA: Namibia
NC: New Caledonia
NE: Niger
NF: Norfolk Island
NG: Nigeria
NI: Nicaragua
NL: Netherlands
NO: Norway
NP: Nepal
NR: Nauru
NU: Niue
NZ: New Zealand
OM: Oman
PA: Panama
PE: Peru
PF: French Polynesia
PG: Papua New Guinea
PH: Philippines
PK: Pakistan
PL: Poland
PM: Saint Pierre and Miquelon
PN: Pitcairn
PR: Puerto Rico
PS: Palestine State of
PT: Portugal
PW: Palau
PY: Paraguay
QA: Qatar
RE: Réunion
RO: Romania
RS: Serbia
RU: Russian Federation
RW: Rwanda
SA: Saudi Arabia
SB: Solomon Islands
SC: Seychelles
SD: Sudan
SE: Sweden
SG: Singapore
SH: Saint Helena Ascension and Tristan da Cunha
SI: Slovenia
SJ: Svalbard and Jan Mayen
SK: Slovakia
SL: Sierra Leone
SM: San Marino
SN: Senegal
SO: Somalia
SR: Suriname
SS: South Sudan
ST: Sao Tome and Principe
SV: El Salvador
SX: Sint Maarten (Dutch part)
SY: Syrian Arab Republic
SZ: Eswatini
TC: Turks and Caicos Islands
TD: Chad
TF: French Southern Territories
TG: Togo
TH: Thailand
TJ: Tajikistan
TK: Tokelau
TL: Timor-Leste
TM: Turkmenistan
TN: Tunisia
TO: Tonga
TR: Turkey
TT: Trinidad and Tobago
TV: Tuvalu
TW: Taiwan Province of China
TZ: Tanzania United Republic of
UA: Ukraine
UG: Uganda
UM: United States Minor Outlying Islands
US: United States
UY: Uruguay
UZ: Uzbekistan
VA: Holy See (Vatican City State)
VC: Saint Vincent and the Grenadines
VE: Venezuela Bolivarian Republic of
VG: Virgin Islands British
VI: Virgin Islands U.S.
VN: Viet Nam
VU: Vanuatu
WF: Wallis and Futuna
WS: Samoa
YE: Yemen
YT: Mayotte
ZA: South Africa
ZM: Zambia
ZW: Zimbabwe
```

47
docs/Customer.md Normal file
View File

@ -0,0 +1,47 @@
# Customer
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Update customer](#update-customer)
- [Display customer](#display-customer)
- [Display instance](#display-instance)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/customers
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<CustomerAttribute> ::=
(primary <DomainName>)|
(adminsecondaryemail|alternateemail <EmailAddress>)|
(contact|contactname <String>)|
(language <LanguageCode>)|
(phone|phonenumber <String>)|
(name|organizationname <String>)|
(address|address1|addressline1 <String>)|
(address2|addressline2 <String>)|
(address3|addressline3 <String>)|
(city|locality <String>)|
(state|region <String>)|
(zipcode|postal|postalcode <String>)|
(country|countrycode <String>)
```
## Update customer
```
gam update customer <CustomerAttribute>*
```
## Display customer
```
gam info customer [formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
## Display instance
```
gam info instance [formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.

View File

@ -0,0 +1,187 @@
# Domain People - Contacts & Profiles
- [API documentation](#api-documentation)
- [Collections of Users](Collections-of-Users)
- [Notes](#notes)
- [Definitions](#definitions)
- [Display Domain Contacts](#display-domain-contacts)
- [Display Domain Profiles](#display-domain-profiles)
## API documentation
* https://developers.google.com/contacts/v3/announcement
* https://developers.google.com/people/contacts-api-migration
* https://developers.google.com/people
* https://developers.google.com/people/api/rest/v1/people/listDirectoryPeople
* https://developers.google.com/people/api/rest/v1/people/searchDirectoryPeople
## Notes
To use these features you must add the `People API` to your project and authorize the appropriate scopes:
* `Client Access` - `People Directory API - read only`
* `Service Account Access`
* `People Directory API - read only`: https://www.googleapis.com/auth/directory.readonly
* `OAuth2 API`: https://www.googleapis.com/auth/userinfo.profile
```
gam update project
gam oauth create
gam user user@domain.com check serviceaccount
```
## Definitions
```
<PeopleResourceName> ::= people/<String>
<PeopleResourceNameList> ::= "<PeopleResourceName>(,<PeopleResourceName>)*"
<PeopleResourceNameEntity> ::=
<PeopleResourceNameNameList> | <FileSelector> | <CSVFileSelector> | <CSVDataSelector>
<PeopleSourceName> ::=
contact|contacts|
profile|profiles
<PeopleMergeSourceName> ::=
contact|contacts
<PeopleFieldName> ::=
addresses|
ageranges|
biographies|
birthdays|
calendarurls|
clientdata|
coverphotos|
emailaddresses|
events|
externalids|
genders|
imclients|
interests|
locales|
locations|
memberships|
metadata|
misckeywords|
names|
nicknames|
occupations|
organizations|
phonenumbers|
photos|
relations|
sipaddresses|
skills|
urls|
userdefined
<PeopleFieldNameList> ::= "<PeopleFieldName>(,<PeopleFieldName>)*"
```
## Display Domain Contacts
### Display as an indented list of keys and values.
```
gam info domaincontacts <PeopleResourceNameEntity>
[allfields|(fields <PeopleFieldNameList>)]
[formatjson]
```
By default, Gam displays the fields `names,emailaddresses`.
* `allfields|(fields <PeopleFieldNameList>)` - Select fields to display
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam show domaincontacts
[query <String>]
[mergesources <PeopleMergeSourceName>]
[allfields|(fields <PeopleFieldNameList>)]
[formatjson]
```
By default, Gam displays all domain contacts.
* `query <String>` - Display contacts based on the data in their fields.
Google's explanation of `mergesources`: Additional data to merge into the directory sources
if they are connected through verified join keys such as email addresses or phone numbers.
By default, Gam displays the fields `names,emailaddresses`.
* `allfields|(fields <PeopleFieldNameList>)` - Select fields to display
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Display as a CSV file.
```
gam print domaincontacts [todrive <ToDriveAttribute>*]
[query <String>]
[mergesources <PeopleMergeSourceName>]
[allfields|(fields <PeopleFieldNameList>)]
[formatjson [quotechar <Character>]]
```
By default, Gam displays all domain contacts.
* `query <String>` - Display contacts based on the data in their fields.
Google's explanation of `mergesources`: Additional data to merge into the directory sources
if they are connected through verified join keys such as email addresses or phone numbers.
By default, Gam displays the fields `names,emailaddresses`.
* `allfields|(fields <PeopleFieldNameList>)` - Select fields to display
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Domain Profiles
### Display as an indented list of keys and values.
```
gam info people|domainprofiles <PeopleResourceNameEntity>
[allfields|(fields <PeopleFieldNameList>)]
[formatjson]
```
By default, Gam displays the fields `names,emailaddresses`.
* `allfields|(fields <PeopleFieldNameList>)` - Select fields to display
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam show people|domainprofiles
[query <String>]
[mergesources <PeopleMergeSourceName>]
[allfields|(fields <PeopleFieldNameList>)]
[formatjson]
```
By default, Gam displays all domain profiles.
* `query <String>` - Display profiles based on the data in their fields.
Google's explanation of `mergesources`: Additional data to merge into the directory sources
if they are connected through verified join keys such as email addresses or phone numbers.
By default, Gam displays the fields `names,emailaddresses`.
* `allfields|(fields <PeopleFieldNameList>)` - Select fields to display
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Display as a CSV file.
```
gam print people|domainprofiles [todrive <ToDriveAttribute>*]
[query <String>]
[mergesources <PeopleMergeSourceName>]
[allfields|(fields <PeopleFieldNameList>)]
[formatjson [quotechar <Character>]]
```
By default, Gam displays all domain profiles.
* `query <String>` - Display profiles based on the data in their fields.
Google's explanation of `mergesources`: Additional data to merge into the directory sources
if they are connected through verified join keys such as email addresses or phone numbers.
By default, Gam displays the fields `names,emailaddresses`.
* `allfields|(fields <PeopleFieldNameList>)` - Select fields to display
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,315 @@
# Domain Shared Contacts - Global Address List
- [API documentation](#api-documentation)
- [Query documentation](#query-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [Create domain shared contacts](#create-domain-shared-contacts)
- [Select domain shared contacts](#select-domain-shared-contacts)
- [Update domain shared contacts](#update-domain-shared-contacts)
- [Delete domain shared contacts](#delete-domain-shared-contacts)
- [Clear old email addresses from contacts](#clear-old-email-addresses-from-contacts)
- [Delete duplicate email addresses from contacts](#delete-duplicate-email-addresses-from-contacts)
- [Manage domain contact photos](#manage-domain-contact-photos)
- [Display domain shared contacts](#display-domain-shared-contacts)
- [Display global address list](#display-global-address-list)
## API documentation
* https://developers.google.com/admin-sdk/domain-shared-contacts/
## Query documentation
* https://developers.google.com/google-apps/contacts/v3/reference#contacts-query-parameters-reference
## Definitions
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
```
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
<UserGoogleDoc> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
<NoteContent> ::=
((<String>)|
(file <FileName> [charset <CharSet>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
<Date> ::=
<Year>-<Month>-<Day> |
(+|-)<Number>(d|w|y) |
never|
today
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<QueryContact> ::= <String>
https://developers.google.com/google-apps/contacts/v3/reference#contacts-query-parameters-reference
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<ContactID> ::= <String>
<ContactIDList> ::= "<ContactID>(,<ContactID>)*"
<ContactEntity> ::=
<ContactIDList>|<FileSelector>|<CSVkmdSelector>|<CSVDataSelector>
<ContactSelection> ::=
[query <QueryContact>]
[emailmatchpattern <RegularExpression> [emailmatchtype work|home|other|<String>]]
[updated_min <Date>]
```
```
<ContactBasicAttribute> ::=
(additionalname|middlename <String>)|
(billinginfo <String>)|
(birthday <Date>)|
(directoryserver <String>)|
(familyname|lastname <String>)|
(gender female|male)|
(givenname|firstname <String>)|
(initials <String>)|
(language <Language>)|
(location <String>)|
(maidenname <String>)|
(mileage <String>)|
(name <String>)|
(nickname <String>)|
(note <NoteContent>)|
(occupation <String>)|
(prefix <String>)|
(priority low|normal|high)
(sensitivity confidential|normal|personal|private)
(shortname <String>)|
(subject <String>)|
(suffix <String>)
```
```
<ContactMultiAttribute> ::=
(address work|home|other|<String>
(formatted|unstructured <String>)|(streetaddress <String>)|
(pobox <String>)|(neighborhood <String>)|(locality <String>)|
(region <String>)|(postalcode <String>)|(country <String>)*
notprimary|primary)|
(calendar work|home|free-busy|<String> <URL>
notprimary|primary)|
(email work|home|other|<String> <EmailAddress>
notprimary|primary)|
(event anniversary|other|<String> <Date>)|
(externalid account|customer|network|organization|<String> <String>)|
(hobby <String>)|
(im work|home|other|<String>
aim|gtalk|icq|jabber|msn|net_meeting|qq|skype|yahoo <String>
notprimary|primary)|
(jot work|home|other|keywords|user> <String>)|
(organization work|other|<String> <String>
(location <String>)|(department <String>)|(title <String>)|
(jobdescription <String>)|(symbol <String>)*
notprimary|primary)|
(phone work|home|other|fax|work_fax|home_fax|other_fax|main|company_main|
assistant|mobile|work_mobile|pager|work_pager|car|radio|callback|
isdn|telex|tty_tdd|<String> <String>
notprimary|primary)|
(relation spouse|child|mother|father|parent|brother|sister|friend|relative|
domestic_partner|manager|assistant|referred_by|partner|<String> <String>)|
(userdefinedfield <String> <String>)|
(website home_page|blog|profile|work|home|other|ftp|reservations|
app_install_page|<String> <URL> notprimary|primary)
<ContactClearAttribute> ::=
(address clear)|
(calendar clear)|
(email clear)|
(event clear)|
(externalid clear)|
(hobby clear)|
(im clear)|
(jot clear)|
(organization clear)|
(phone clear)|
(relation clear)|
(userdefinedfield clear)|
(website clear)
```
```
<ContactAttribute> ::=
<JSONData>|
<ContactBasicAttribute>|
<ContactMultiAttribute>|
<ContactClearAttribute>
```
```
<ContactFieldName> ::=
additionalname|middlename|
address|
billinginfo|
birthday|
calendar|
directoryserver|
email|
event|
externalid|
familyname|lastname|
gender|
givenname|firstname|
hobby|
im|
initials|
jot|
language|
location|
maidenname|
mileage|
name|
nickname|
note|
occupation|
organization|
phone|
prefix|
priority|
relation|
sensitivity|
shortname|
subject|
suffix|
updated|
userdefinedfield|
website
<ContactFieldNameList> ::= "<ContactFieldName>(,<ContactFieldName>)*"
<ContactOrderByFieldName> ::=
lastmodified
```
## Create domain shared contacts
```
gam create contact <ContactAttribute>+
```
## Select domain shared contacts
You specify contacts by ID or by selection qualifiers.
```
<ContactID> ::= <String>
<ContactIDList> ::= "<ContactID>(,<ContactID>)*"
<ContactEntity> ::=
<ContactIDList>|<FileSelector>|<CSVkmdSelector>|<CSVDataSelector>
<ContactSelection> ::=
[query <QueryContact>]
[emailmatchpattern <RegularExpression> [emailmatchtype work|home|other|<String>]]
[updated_min <Date>]
```
Selection qualifiers may be combined.
* `query <QueryContact>` - Fulltext query on contacts data fields. See: https://developers.google.com/contacts/v3/reference#contacts-query-parameters-reference
* `emailmatchpattern <RegularExpression>` - Select contacts that have an email address matching `<RegularExpression>`
* `emailmatchpattern <RegularExpression> emailmatchtype work|home|other|<String>` - Select contacts that have an email address matching `<RegularExpression>` and a specific type
* `emailmatchpattern ".*" emailmatchtype work|home|other|<String>` - Select contacts that have any email address with a specific type
* `updated_min <Date>` - Select contacts updated since `<Date>`
## Update domain shared contacts
```
gam update contacts <ContactEntity>|<ContactSelection> <ContactAttribute>+
```
## Delete domain shared contacts
```
gam delete contacts <ContactEntity>|<ContactSelection>
```
## Clear old email addresses from contacts
```
gam clear contacts <ContactEntity>|<ContactSelection>
[emailclearpattern <RegularExpression> [emailcleartype work|home|other|<String>]]
[delete_cleared_contacts_with_no_emails]
```
Typically, you would select contacts by `emailmatchpattern <RegularExpression>` (and optionally `emailmatchtype work|home|other|<String>`),
then the matching email addresses will be cleared from the domiain contact's email list. The contact itself is updated, not deleted.
Email addresses that don't match will be unaffected. If you want to clear all email addresses of a particular type,
use `emailmatchpattern ".*" emailmatchtype work|home|other|<String>`.
You can specify `emailclearpattern <RegularExpression>` (and optionally `emailcleartype work|home|other|<String>`) if you want to
clear email addresses other than the ones used to match the contacts or if you specify `<ContactEntity>`.
A contact may contain no email addresses after matching email addresses are cleared. If you do not want to keep contacts with no
email addresses after clearing, use the `delete_cleared_contacts_with_no_emails` option and they will be deleted.
Contacts with no email addresses before clearing will not be affected.
## Delete duplicate email addresses from contacts
If the same email address appears multiple times within a contact, all but the first will be deleted.
```
gam dedup contacts [<ContactEntity>|<ContactSelection>] [matchType [<Boolean>]]
```
If neither `<ContactEntity>` or `<ContactSelection>` is specified, all contacts are checked for duplicates.
By default, the email type `work|home|other|<String>` is ignored, all duplicates, regardless of type,
will be deleted. If `matchtype` is true, only duplicate email addresses with the same type will be deleted.
## Manage domain contact photos
```
gam update contactphotos <ContactEntity>|<ContactSelection>
[drivedir|(sourcefolder <FilePath>)] [filename <FileNamePattern>]
gam get contactphotos <ContactEntity>|<ContactSelection>
[drivedir|(targetfolder <FilePath>)] [filename <FileNamePattern>]
gam delete contactphotos <ContactEntity>|<ContactSelection>
```
The default directory is the current working directory, `drivedir` specifies the value of drive_dir from gam.cfg and
`sourcefolder/targetfolder <FilePath>` specifies a user-chosen path.
`<FileNamePattern>` can contain the strings `#email#` and `#contactid#` which will be replaced by the the contact's primary emailaddress or the contact ID.
If not specified, `<FileNamePattern>` defaults to `#contactid#.jpg`.
## Display domain shared contacts
```
gam info contacts <ContactEntity>
[basic|full]
[fields <ContactFieldNameList>] [formatjson]
gam show contacts [<ContactSelection>]
[basic|full|countsonly] [showdeleted]
[orderby <ContactOrderByFieldName> [ascending|descending]]
[fields <ContactFieldNameList>] [formatjson]
```
If `<ContactSelection>` is not specified, all contacts are displayed.
If `countsonly` is specified, no contact fields are displayed, just the number of contacts.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print contacts [todrive <ToDriveAttribute>*] [<ContactSelection>]
[basic|full|countsonly] [showdeleted]
[orderby <ContactOrderByFieldName> [ascending|descending]]
[fields <ContactFieldNameList>] [formatjson [quotechar <Character>]]
```
If `<ContactSelection>` is not specified, all contacts are displayed.
If `countsonly` is specified, no contact fields are displayed, just the number of contacts.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display global address list
```
gam info gal <ContactEntity>
[basic|full]
[fields <ContactFieldNameList>] [formatjson]
gam show gal <ContactSelection>
[basic|full] [orderby <ContactOrderByFieldName> [ascending|descending]]
[fields <ContactFieldNameList>] [formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print gal [todrive <ToDriveAttribute>*] <ContactSelection>
[basic|full] [orderby <ContactOrderByFieldName> [ascending|descending]]
[fields <ContactFieldNameList>] [formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields.
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,31 @@
# Domains - Verification
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Introduction](#introduction)
- [Create site verification tokens](#create-site-verification-tokens)
- [Test site verification token](#test-site-verification-token)
- [Display site verification information](#display-site-verification-information)
## API documentation
* https://developers.google.com/site-verification/v1/getting_started
* https://developers.google.com/site-verification/v1/
## Definitions
```
<DomainName> ::= <String>(.<String>)+
```
## Introduction
To use Google Apps Gmail and other Web services, your account's site ownership must be verified.
## Create site verification tokens
```
gam create verify|verification <DomainName>
```
## Test site verification token
```
gam update verify|verification <DomainName> cname|txt|text|site|file
```
## Display site verification information
```
gam info verify|verification
```

75
docs/Domains.md Normal file
View File

@ -0,0 +1,75 @@
# Domains
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Create a domain](#create-a-domain)
- [Promote a domain to be primary](#promote-a-domain-to-be-primary)
- [Delete a domain](#delete-a-domain)
- [Display domains](#display-domains)
- [Create and delete domain aliases](#create-and-delete-domain-aliases)
- [Display domain aliases](#display-domain-aliases)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/domains
## Definitions
```
<DomainAlias> ::= <String>
<DomainName> ::= <String>(.<String>)+
```
## Create a domain
```
gam create domain <DomainName>
```
## Promote a domain to be primary
```
gam update domain <DomainName> primary
```
## Delete a domain
```
gam delete domain <DomainName>
```
## Display domains
```
gam info domain [<DomainName>] [formatjson]
gam show domains [formatjson]
```
For `info`, if `<DomainName>` is omitted, information about the primary domain will be displayed.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print domains [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields.
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Create and delete domain aliases
```
gam create domainalias|aliasdomain <DomainAlias> <DomainName>
gam delete domainalias|aliasdomain <DomainAlias>
```
## Display domain aliases
```
gam info domainalias|aliasdomain <DomainAlias> [formatjson]
gam show domainaliases|aliasdomains [formatjson] [formatjson [quotechar <Character>]]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print domainaliases|aliasdomains [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields.
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

74
docs/Downloads.md Normal file
View File

@ -0,0 +1,74 @@
# Downloads
You can download the current GAMADV-XTD3 release from the [GitHub Releases](https://github.com/taers232c/GAMADV-XTD3/releases) page. Choose one of the following:
* Executable Archive, Automatic, Linux/Mac OS/Google Cloud Shell/Raspberry Pi/ChromeOS
- Start a terminal session and execute one of the following commands:
- New install, default path `$HOME/bin`
- `bash <(curl -s -S -L https://raw.githubusercontent.com/taers232c/GAMADV-XTD3/master/src/gam-install.sh)`
- New install, specify a path
- `bash <(curl -s -S -L https://raw.githubusercontent.com/taers232c/GAMADV-XTD3/master/src/gam-install.sh) -d <Path>`
- Update to latest version, do not create project or authorizations, default path `$HOME/bin`
- `bash <(curl -s -S -L https://raw.githubusercontent.com/taers232c/GAMADV-XTD3/master/src/gam-install.sh) -l`
- Update to latest version, do not create project or authorizations, specify a path
- `bash <(curl -s -S -L https://raw.githubusercontent.com/taers232c/GAMADV-XTD3/master/src/gam-install.sh) -l -d <Path>`
By default, a folder, `gamadv-xtd3`, is created in the default or specified path and the files are downloaded into that folder.
Add the `-s` option to the end of the above commands to suppress creating the `gamadv-xtd3` folder; the files are downloaded directly into the default or specified path.
* Executable Archive, Manual, Linux/Google Cloud Shell
- `gamadv-xtd3-6.wx.yz-linux-x86_64-glibc2.35.tar.xz`
- `gamadv-xtd3-6.wx.yz-linux-x86_64-glibc2.31.tar.xz`
- `gamadv-xtd3-6.wx.yz-linux-x86_64-glibc2.27.tar.xz`
- `gamadv-xtd3-6.wx.yz-linux-x86_64-glibc2.23.tar.xz`
- `gamadv-xtd3-6.wx.yz-linux-x86_64-glibc2.19.tar.xz`
- `gamadv-xtd3-6.wx.yz-linux-x86_64-legacy.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session and cd to the install directory.
* Executable Archive, Manual, Raspberry Pi/ChromeOS ARM devices
- `gamadv-xtd3-6.wx.yz-linux-arm64-glibc2.31.tar.xz`
- `gamadv-xtd3-6.wx.yz-linux-arm64-glibc2.27.tar.xz`
- `gamadv-xtd3-6.wx.yz-linux-arm64-glibc2.23.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session and cd to the install directory.
* Executable Archive, Manual, Mac OS versions Big Sur, Monterey, Ventura - M1/M2
- `gamadv-xtd3-6.wx.yz-macos-arm64.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session and cd to the install directory.
* Executable Archive, Manual, Mac OS, versions Big Sur, Monterey, Ventura - Intel
- `gamadv-xtd3-6.wx.yz-macos-x86_64.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session and cd to the install directory.
* Executable Archive, Manual, Mac OS, versions prior to Big Sur
- `gamadv-xtd3-6.wx.yz-macos-x86_64-legacy.tar`
- Download the archive, extract the contents into some directory.
- Start a terminal session and cd to the install directory.
* Executable Archive, Manual, Windows 64 bit
- `gamadv-xtd3-6.wx.yz-windows-x86_64.zip`
- Download the archive, extract the contents into some directory.
- Start a terminal session and cd to the install directory.
* Executable Installer, Manual, Windows 64 bit
- `gamadv-xtd3-6.wx.yz-windows-x86_64.msi`
- Download the installer and run it.
- Start a Command Prompt/PowerShell session and cd to the install directory.
* Executable Archive, Manual, Windows 32 bit
- `gamadv-xtd3-6.wx.yz-windows-x86.zip`
- Download the archive, extract the contents into some directory.
- Start a terminal session and cd to the install directory.
* Executable Installer, Manual, Windows 32 bit
- `gamadv-xtd3-6.wx.yz-windows-x86.msi`
- Download the installer and run it.
- Start a Command Prompt/PowerShell session and cd to the install directory.
* Source, all platforms
- `Source code(zip)`
- `Source code(tar.gz)`
- Download the archive, extract the contents into some directory.
- Start a terminal/Command Prompt/PowerShell session and cd to the install directory.

View File

@ -0,0 +1,388 @@
# Drive File Selection
- [Definitions](#definitions)
- [Introduction](#introduction)
- [Select file by ID](#select-file-by-id)
- [Select files by their characteristics](#select-files-by-their-characteristics)
- [Select with Drive File API query](#select-with-drive-file-api-query)
- [Select file by name](#select-file-by-name)
- [Select file ownership](#select-file-ownership)
- [Select MIME type](#select-MIME-type)
- [Select file ownership and MIME type](#select-file-ownership-and-mime-type)
- [Select based on file size](#select-based-on-file-size)
- [Select based on file name](#select-based-on-file-name)
- [Select based on permission matching](#select-based-on-permission-matching)
- [Select root folder](#select-root-folder)
- [Select a list of file IDs](#select-a-list-of-file-ids)
- [Select Shared Drive file by ID](#select-shared-drive-file-by-id)
- [Select Shared Drive file by name](#select-shared-drive-file-by-name)
- [Select Shared Drive file by query](#select-shared-drive-file-by-query)
- [Select root folder of a Shared Drive by ID](#select-root-folder-of-a-shared-drive-by-id)
- [Select root folder of a Shared Drive by name](#select-root-folder-of-a-shared-drive-by-name)
## Definitions
```
<DriveFileID> ::= <String>
https://drive.google.com/open?id=<DriveFileID>
https://drive.google.com/drive/files/<DriveFileID>
https://drive.google.com/drive/folders/<DriveFileID>
https://drive.google.com/drive/folders/<DriveFileID>?resourcekey=<String>
https://drive.google.com/file/d/<DriveFileID>/<String>
https://docs.google.com>/document/d/<DriveFileID>/<String>
https://docs.google.com>/drawings/d/<DriveFileID>/<String>
https://docs.google.com>/forms/d/<DriveFileID>/<String>
https://docs.google.com>/presentation/d/<DriveFileID>/<String>
https://docs.google.com>/spreadsheets/d/<DriveFileID>/<String>
<DriveFileItem> ::= <DriveFileID>|<DriveFileURL>
<DriveFileList> ::= "<DriveFileItem>(,<DriveFileItem>)*"
<DriveFileIDEntity> ::=
(<DriveFileItem>)|(id( |:)<DriveFileItem>)|(ids( |:)<DriveFileList>)
<DriveFileName> ::= <String>
<DriveFileNameEntity> ::=
(drivefilename <DriveFileName>)|(drivefilename:<DriveFileName>)|
(anydrivefilename <DriveFileName>)|(anydrivefilename:<DriveFileName>)
<DriveFolderID> ::= <String>
<DriveFolderIDList> ::= "<DriveFolderID>(,<DriveFolderID>)*"
<DriveFolderName> ::= <String>
<QueryDriveFile> :: = <String> See: https://developers.google.com/drive/api/v3/search-files
<DriveFileQueryEntity> ::=
(query <QueryDriveFile>) | (query:<QueryDriveFile>)
<DriveFileQueryShortcut> ::=
all_files |
all_folders |
all_forms |
all_google_files |
all_non_google_files |
all_shortcuts |
all_3p_shortcuts |
all_items |
my_files |
my_folders |
my_forms |
my_google_files |
my_non_google_files |
my_shortcuts |
my_3p_shortcuts |
my_items |
my_top_files |
my_top_folders |
my_top_items |
others_files |
others_folders |
others_forms |
others_google_files |
others_non_google_files |
others_shortcuts |
others_3p_shortcuts |
others_items |
writable_files
<SharedDriveID> ::= <String>
<SharedDriveName> ::= <String>
<SharedDriveIDEntity> ::= (teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::= (teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
<SharedDriveEntity> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>
<SharedDriveAdminQueryEntity> ::=
(teamdriveadminquery <QueryTeamDrive>) | (teamdriveadminquery:<QueryTeamDrive>)
<SharedDriveFileQueryEntity> ::=
(query <QueryDriveFile>) | (query:<QueryDriveFile>)
<SharedDriveFileQueryShortcut> ::=
all_files | all_folders | all_google_files | all_non_google_files | all_items
<SharedDriveEntityAdmin> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>|
<SharedDriveAdminQueryEntity>
<DriveFileEntity> ::=
<DriveFileIDEntity> |
<DriveFileNameEntity> |
<DriveFileQueryEntity> |
<DriveFileQueryShortcut> |
mydrive | mydriveid |
root | rootid |
<SharedDriveIDEntity> [<SharedDriveFileQueryShortcut>] |
<SharedDriveNameEntity> [<SharedDriveFileQueryShortcut>] |
<SharedDriveFileNameEntity> |
<SharedDriveFileQueryEntity> |
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector>) | <CSVDataSelector>)
```
## Introduction
Many Gam commands operate on Google Drive files, there are multiple ways to specify the file on which to operate.
The Google Drive REST API can only manipulate files by ID; you either specify an ID or an option that will produce an ID.
## Select file by ID
Select a file by giving its unique ID.
There are multiple formats for backwards compatibility with old Gam commands that used different formats to specify the same data.
```
<DriveFileIDEntity> ::=
<DriveFileItem> |
(id <DriveFileItem>) | (id:<DriveFileItem>) |
(ids <DriveFileList>) | (ids:<DriveFileList>)
```
### Examples
```
gam user testuser show fileinfo 1234ABCD
gam user testuser show fileinfo id 1234ABCD
gam user testuser show fileinfo id:1234ABCD
gam user testuser show fileinfo https://drive.google.com/a/domain.com/file/d/1234ABCD
gam user testuser show fileinfo ids "1234ABCD,5678EFGH"
gam user testuser show fileinfo ids:"1234ABCD,5678EFGH"
```
## Select files by their characteristics
The `print|show filetree|filelist` have variety of options for choosing the files to display.
## Select with Drive File API query
The Google Drive API has a query option that you can use to select files.
* https://developers.google.com/drive/api/v3/search-files
* https://developers.google.com/drive/api/v3/ref-search-terms
```
<DriveFileQueryEntity> ::=
(query <QueryDriveFile>) | (query:<QueryDriveFile>)
```
The default query for selecting files is `'me' in owners`; all files and folders in `My Drive` that the user owns.
You can specify multiple `query <QueryDriveFile>` and `query:<QueryDriveFile>` options.
Each one is appended to the default/existing query with `and (<QueryDriveFile>)`.
The are several options manipulate the query.
## Select file by name
If you have a file name, a search must be performed to find the ID that matches the name.
Remember, searching for a file by name may return several file IDs if you have multiple files with the same name.
There are multiple formats for backwards compatibility with old Gam commands that used different formats to specify the same data.
If a drive file name contains spaces or commas, it must be enclosed in quotes.
```
<DriveFileNameEntity> ::=
(anyname <DriveFileName>) | (anyname:<DriveFileName>) | (anydrivefilename <DriveFileName>) | (anydrivefilename:<DriveFileName>) |
(name <DriveFileName>) | (name:<DriveFileName>) | (drivefilename <DriveFileName>) | (drivefilename:<DriveFileName>) |
(othername <DriveFileName>) | (othername:<DriveFileName>) | (otherdrivefilename <DriveFileName>) | (otherdrivefilename:<DriveFileName>)
```
* `anyname <DriveFileName>` - `(name = '<DriveFileName>')`
* `anyname:<DriveFileName>` - `(name = '<DriveFileName>')`
* `anydrivefilename <DriveFileName>` - `(name = '<DriveFileName>')`
* `anydrivefilename:<DriveFileName>` - `(name = '<DriveFileName>')`
* `name <DriveFileName>` - `('me' in owners and name = '<DriveFileName>')`
* `name:<DriveFileName>` - `('me' in owners and name = '<DriveFileName>')`
* `drivefilename <DriveFileName>` - `('me' in owners and name = '<DriveFileName>')`
* `drivefilename:<DriveFileName>` - `('me' in owners and name = '<DriveFileName>')`
* `othername <DriveFileName>` - `(not 'me' in owners and name = '<DriveFileName>')`
* `othername:<DriveFileName>` - `(not 'me' in owners and name = '<DriveFileName>')`
* `otherdrivefilename <DriveFileName>` - `(not 'me' in owners and name = '<DriveFileName>')`
* `otherdrivefilename:<DriveFileName>` - `(not 'me' in owners and name = '<DriveFileName>')`
### Examples
```
gam user testuser show fileinfo drivefilename "Test File"
gam user testuser show fileinfo drivefilename:"Test File"
gam user testuser show fileinfo anydrivefilename "Test File"
gam user testuser show fileinfo anydrivefilename:"Test File"
```
## Select file ownership
By default, files the user owns are sisplayed; you can select the ownership characteristic.
```
anyowner|(showownedby any|me|others)
```
* `showownedby any` or `anyowner` - Removes `'me' in owners` and `not 'me' in owners` from the query
* `showownedby me` - Adds `'me' in owners` to the query
* `showownedby others` - Adds `not 'me' in owners` to the query
## Select MIME type
By default, all types of files and folders are displayed; you can specify a list of MIME types to display or a list of MIME types to suppress.
```
<MimeTypeShortcut> ::=
gdoc|gdocument|
gdrawing|
gfile|
gfolder|gdirectory|
gform|
gfusion|
gmap|
gpresentation|
gscript|
gshortcut|
g3pshortcut|
gsheet|gspreadsheet|
gsite
<MimeTypeName> ::= application|audio|font|image|message|model|multipart|text|video
<MimeType> ::= <MimeTypeShortcut>|(<MimeTypeName>/<String>)
<MimeTypeList> ::= "<MimeType>(,<MimeType>)*"
```
This is the mapping from `<MimeTypeShortcut>` to MIME type.
* `gdoc|gdocument` - 'application/vnd.google-apps.document
* `gdrawing` - application/vnd.google-apps.drawing
* `gfile` - application/vnd.google-apps.file
* `gfolder|gdirectory` - application/vnd.google-apps.folder
* `gform` - application/vnd.google-apps.form
* `gfusion|gfusiontable` - application/vnd.google-apps.fusiontable
* `gmap` - application/vnd.google-apps.map
* `gpresentation` - application/vnd.google-apps.presentation
* `gscript` - application/vnd.google-apps.script
* `gshortcut` - application/vnd.google-apps.shortcut
* `g3pshortcut` - application/vnd.google-apps.drive-sdk
* `gsite` - application/vnd.google-apps.site
* `gsheet|gspreadsheet` - application/vnd.google-apps.spreadsheet
Display files and folders with specified MIME types
```
showmimetype <MimeTypeList>
```
Adds `(mimeType = '<MimeType>' or mimeType = '<MimeType>' ...)` to the query,
Display files and folders with MIME types other than those specified
```
showmimetype not <MimeTypeList>
```
Adds `(mimeType != '<MimeType>' and mimeType != '<MimeType>' ...)` to the query.
## Select file ownership and MIME type
The options combine ownership and broad MIME type selections.
```
<DriveFileQueryShortcut> ::=
all_files | all_folders | all_google_files | all_non_google_files | all_items |
my_files | my_folders | my_google_files | my_non_google_files | my_items |
my_top_files | my_top_folders | my_top_items |
others_files | others_folders | others_google_files | others_non_google_files | others_items |
writable_files
```
* all_files - "mimeType != application/vnd.google-apps.folder"
* all_folders - "mimeType = application/vnd.google-apps.folder"
* all_google_files - "mimeType != application/vnd.google-apps.folder and mimeType contains 'vnd.google'"
* all_non_google_files - "not mimeType contains 'vnd.google'"
* all_items - "" (An empty query specifies all files and folders)
* my_files - "'me' in owners and mimeType != application/vnd.google-apps.folder"
* my_folders - "'me' in owners and mimeType = application/vnd.google-apps.folder"
* my_google_files - "'me' in owners and mimeType != application/vnd.google-apps.folder and mimeType contains 'vnd.google'"
* my_non_google_files - "'me' in owners and not mimeType contains 'vnd.google'"
* my_items - "'me' in owners"
* my_top_files - "'me' in owners and mimeType != application/vnd.google-apps.folder and 'root' in parents"
* my_top_folders - "'me' in owners and mimeType = application/vnd.google-apps.folder and 'root' in parents"
* my_top_items - "'me' in owners and 'root' in parents"
* others_files - "not 'me' in owners and mimeType != application/vnd.google-apps.folder"
* others_folders - "not 'me' in owners and mimeType = application/vnd.google-apps.folder"
* others_google_files - "not 'me' in owners and mimeType != application/vnd.google-apps.folder and mimeType contains 'vnd.google'"
* others_non_google_files - "not 'me' in owners and not mimeType contains 'vnd.google'"
* others_items - "not 'me' in owners"
* writable_files - "'me' in writers and mimeType != application/vnd.google-apps.folder"
## Select based on file size
For these filters, GAM processes then after the list of files is downloaded. You can combine these
options `query <QueryDriveFile>` to minimize the number of files downloaded but they also work with other
file selection options.
Limit the display to files with binary content of size greater than or equal to a number of bytes.
```
minimumfilesize <Integer>`
```
## Select based on file name
The Google Drive API has limited name matching in the query; Limit the display to files whose name matches `<RegularExpression>`.
```
filenamematchpattern <RegularExpression>`
```
## Select based on permission matching
Use [Permission matches](#permission-matches) to limit the display to files with matching permissions.
### Examples
```
gam user testuser show fileinfo query "name='Test File'"
gam user testuser show fileinfo query:"name='Test Folder' and mimeType=application/vnd.google-apps.folder"
gam user testuser print filelist my_non_google_files
```
## Select root folder
```
root|mydrive
```
Examples
```
gam user testuser show fileinfo root
```
## Select a list of file IDs
You can select a list of file IDs by referencing files that contain file IDs.
```
<DriveFileEntity> ::=
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector>) | <CSVDataSelector>)
```
* [Collections of Items](Collections-of-Items)
## Select Shared Drive file by ID
Select a Shared Drive file by giving its unique ID.
```
<SharedDriveIDEntity> ::=
<DriveFileItem> |
(teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
```
### Examples
```
gam user testuser show fileinfo 1234ABCD
gam user testuser show fileinfo id 1234ABCD
gam user testuser show fileinfo teamdriveid 1234ABCD
```
## Select Shared Drive file by name
If you have the name, a search must be performed to find the ID that matches the name.
You must specify the Shared Drive, either by ID or name, and the name of the file.
Remember, searching for a file by name may return several file IDs if you have multiple files with the same name.
```
<SharedDriveIDEntity> ::=
(teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::=
(teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::=
(teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
```
### Examples
```
gam user testuser show fileinfo teamdriveid 1234ABCD teamdrivefilename "Test File"
gam user testuser show fileinfo teamdrive "Shared Drive 1" teamdrivefilename "Test File"
```
## Select Shared Drive file by query
You can use a query to find a file ID. You perform the query on all Shared Drives or a specific Shared Drive.
See: [Drive Query](https://developers.google.com/drive/api/v3/search-files)
```
<SharedDriveFileQueryEntity> ::=
(teamdrivequery <QueryDriveFile>) | (teamdrivequery:<QueryDriveFile>)
<SharedDriveFileQueryShortcut> ::=
all_files | all_folders | all_google_files | all_non_google_files | all_items
```
Keyword to query mappings for `<DriveFileQueryShortcut>`:
* all_files - "mimeType != application/vnd.google-apps.folder"
* all_folders - "mimeType = application/vnd.google-apps.folder"
* all_google_files - "mimeType != application/vnd.google-apps.folder and mimeType contains 'vnd.google'"
* all_non_google_files - "not mimeType contains 'vnd.google'"
* all_items - "" (An empty query specifies all files and folders)
### Examples
```
gam user testuser show fileinfo teamdrivequery "name='Test File'"
gam user testuser show fileinfo teamdriveid 1234ABCD teamdrivequery "name='Test File'"
gam user testuser show fileinfo teamdrive teamdrive "Shared Drive 1" teamdrivequery "name='Test File'"
gam user testuser show fileinfo teamdriveid 1234ABCD all_non_google_files
```
## Select root folder of a Shared Drive by ID
The root folder of a Shared Drive is a folder, you select it by giving its unique ID.
```
<SharedDriveIDEntity> ::=
<DriveFileItem> |
(teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
```
### Examples
```
gam user testuser show fileinfo 1234ABCD
gam user testuser show fileinfo teamdriveid 1234ABCD
```
## Select root folder of a Shared Drive by name
If you have a Shared Drive name, a search must be performed to find the ID that matches the name.
```
<SharedDriveNameEntity> ::=
(teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
```
### Examples
```
gam user testuser show fileinfo teamdrive "Shared Drive 1"
```

39
docs/Drive-Items.md Normal file
View File

@ -0,0 +1,39 @@
# Drive Items
- [Basic Items](Basic-Items)
- [List Items](List-Items)
```
<DriveFileID> ::= <String>
<DriveFileURL> ::=
https://drive.google.com/open?id=<DriveFileID>
https://drive.google.com/drive/files/<DriveFileID>
https://drive.google.com/drive/folders/<DriveFileID>
https://drive.google.com/drive/folders/<DriveFileID>?resourcekey=<String>
https://drive.google.com/file/d/<DriveFileID>/<String>
https://docs.google.com>/document/d/<DriveFileID>/<String>
https://docs.google.com>/drawings/d/<DriveFileID>/<String>
https://docs.google.com>/forms/d/<DriveFileID>/<String>
https://docs.google.com>/presentation/d/<DriveFileID>/<String>
https://docs.google.com>/spreadsheets/d/<DriveFileID>/<String>
<DriveFileItem> ::= <DriveFileID>|<DriveFileURL>
<DriveFileName> ::= <String>
<DriveFileIDEntity> ::=
<DriveFileItem> |
(id <DriveFileItem>) | (id:<DriveFileItem>) |
(ids <DriveFileList>) | (ids:<DriveFileList>)
<DriveFileNameEntity> ::=
(name <DriveFileName>) | (name:<DriveFileName>) |
(drivefilename <DriveFileName>) | (drivefilename:<DriveFileName>) |
(anyname <DriveFileName>) | (anyname:<DriveFileName>) |
(anydrivefilename <DriveFileName>) | (anydrivefilename:<DriveFileName>)
<SharedDriveIDEntity> ::=
<DriveFileItem> |
(teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>)
<SharedDriveName> ::= <String>
<SharedDriveNameEntity> ::=
(teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
<SharedDriveEntity> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>
<SharedDriveFileNameEntity> ::=
(teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
```

93
docs/Drive-REST-API-v3.md Normal file
View File

@ -0,0 +1,93 @@
All Google Drive API calls have been converted from v2 to v3, see: https://developers.google.com/drive/v3/web/migration
Many of the changes are internal to Gam and have no visible effect. Google has modified/renamed many field names and these will affect scripts that parse the output from `gam print/show drivesettings/drivefileacls/fileinfo/filelist/filerevisions`. Additionally, Google has dropped some fields and their values are no longer available. On input, Gam accepts both the old and new field names.
A variable, `drive_v3_native_names` (default value is True), has been added to `gam.cfg` to control the field names on output: when True, the v3 native field names are used; when False, the v3 native field names are mapped to the v2 field names.
If you have scripts that process the output from these print commands, you may have to make modifications to your scripts.
Run your print/show commands with a version of Standard Gam and save the output.
With drive_v3_native_names = False, run your print/show commands with this version of Gam and compare the output to that saved in the previous run;
modify your scripts that process the output as appropriate.
There is a cost to mapping the v3 field names back to the v2 field names; you can avoid this cost by setting drive_v3_native_names = True,
running your print/show commands, comparing the output and making the appropriate script modifications.
```
print/show drivesettings
Dropped fields:
DRIVE
GMAIL
PHOTOS
domainSharingPolicy
lauguageCode
Renamed fields (Old->New):
name->displayName,
quotaBytesTotal->limit
quotaBytesUsed->usageInDrive
quotaBytesUsedAggregate->usage
quotaBytesUsedInTrash->usageInDriveTrash
print/show drivefileacls
Dropped fields:
authKey
Renamed fields (Old->New):
name->displayName
withLink->allowFileDiscovery
print/show fileinfo/filelist
Dropped fields:
defaultOpenWithLink
embedLink
exportLinks
labels(hidden)
markedViewedByMeDate
openWithLinks
selfLink
parents(isRoot)
parents(parentLink)
parents(selfLink)
permissions(selfLink)
selfLink
userPermission(selfLink)
Renamed fields (Old->New):
alternateLink->webViewLink
capabilities(canChangeRestrictedDownload)->capabilities(canChangeViewersCanCopyContent)
createdDate->createdTime
expirationDate->expirationTime
fileSize->size
lastViewedByMeDate->viewedByMeTime
modified->modifiedByMe
modifiedByMeDate->modifiedByMeTime
modifiedDate->modifiedTime
restricted->viewersCanCopyContent
sharedWithMeDate->sharedWithMeTime
title->name
trashedDate->trashedTime
viewed->viewedByMe
withLink->allowFileDiscovery
print/show filerevisions
Dropped fields:
exportLinks
publishedLink
selfLink
Renamed fields (Old->New):
fileSize->size
isAuthenticatedUser->me
modifiedDate->modifiedTie
picture.url->photoLink
pinned->keepForever
```
The parents field of a file has undergone the most change. In Drive v2 it was a list of compound items with three sub-fields per item: id, isRoot, parentLink.
In Drive v3 the parents field is a list of simple items, the parent ids. The following examples show how the parents field is output in a CSV file for a file with two parents.
```
Previous versions of Gam:
Owner,title,parents,parents.0.isRoot,parents.0.id,parents.0.parentLink,parents.1.isRoot,parents.1.id,parents.1.parentLink
testuser@domain.com,TestFile,2,True,PPPP1111,https://www.googleapis.com/drive/v2/files/PPPP1111,False,PPPP2222,https://www.googleapis.com/drive/v2/files/PPPP2222
Current version of Gam with drive_v3_name_names = false
Owner,title,parents,parents.0.id,parents.1.id
testuser@domain.com,TestFile,2,PPPP1111,PPPP2222
Current version of Gam with drive_v3_name_names = true
Owner,name,parents
testuser@domain.com,TestFile,PPPP1111 PPPP2222
```

View File

@ -0,0 +1,42 @@
# Email Audit Monitor
- [API documentation](#api-documentation)
- [Notes](#notes)
- [Definitions](#definitions)
- [Create Email Audit Monitor](#create-email-audit-monitor)
- [Delete Email Audit Monitor](#delete-email-audit-monitor)
- [Display Email Audit Monitors](#display-email-audit-monitors)
## API documentation
* https://developers.google.com/admin-sdk/email-audit
## Notes
To use these features you must add the `Email Audit API` to your project and authorize the appropriate scopes:
* `Client Access` - `Email Audit API`
```
gam update project
gam oauth create
```
## Definitions
```
<DateTime> ::=
<Year>-<Month>-<Day>(<Space>|T)<Hour>:<Minute> |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
```
## Create Email Audit Monitor
```
gam audit monitor create <EmailAddress> <DestEmailAddress> [begin <DateTime>] [end <DateTime>]
[incoming_headers] [outgoing_headers] [nochats] [nodrafts] [chat_headers] [draft_headers]
```
## Delete Email Audit Monitor
```
gam audit monitor delete <EmailAddress> <DestEmailAddress>
```
## Display Email Audit Monitors
```
gam audit monitor list <EmailAddress>
```

57
docs/Find-File-Owner.md Normal file
View File

@ -0,0 +1,57 @@
# Find File Owner
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Display File Ownership](#display-file-ownership)
- [Display File Ownership for Old files](#display-file-ownership-for-old-files)
## API documentation
* https://developers.google.com/admin-sdk/reports/v1/reference/activities
## Definitions
```
<DriveFileID> ::= <String>
<DriveFileName> ::= <String>
```
## Display File Ownership
These commands use the Reports API audit activity and may not find the owner if the file has not been accessed in 180 days.
If you specify a `<DriveFileID>`, there will be at most one line of output. If you specify a `<DriveFileName>`, there will be
one line of output for each distinct file with that name.
The Reports API calls are:
* `ownership <DriveFileID>` - `gam report drive filter "doc_id==<DriveFileID>"`
* `ownership drivefilename <DriveFileName>` - `gam report drive filter "doc_title==<DriveFileName>"`
```
gam show ownership <DriveFileID>|(drivefilename <DriveFileName>)
[formatjson]
```
By default, Gam displays the information as a list of keys and values.
* `formatjson` - Display the output in JSON notation
```
gam print ownership <DriveFileID>|(drivefilename <DriveFileName>) [todrive <ToDriveAttribute>*]
(addcsvdata <FieldName> <String>)*
[formatjson [quotechar <Character>]]
```
* `addcsvdata <FieldName> <String>` - Add additional columns of data from the command line to the output
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format.
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display File Ownership for Old files
If the above commands fail, you can try to loop through all accounts, however this might take a long time if you are on a large Google Workspace Account.
```
gam config auto_batch_min 1 redirect csv - multiprocess redirect stderr null multiprocess all users print filelist select id <DriveFileID> fields id,name,owners.emailaddress norecursion showownedby any
```
Starting with version 6.07.26, this can be made more efficient by terminating processing after the owner is identified.
```
gam config auto_batch_min 1 multiprocessexit rc=0 redirect csv - multiprocess redirect stderr null multiprocess all users print filelist select id <DriveFileID> fields id,name,owners.emailaddress norecursion showownedby any
```

64
docs/GAM-Return-Codes.md Normal file
View File

@ -0,0 +1,64 @@
# GAM Return Codes
These are the return codes used by GAMADV-XTD3.
```
SUCCESS_RC = 0
UNKNOWN_ERROR_RC = 1
USAGE_ERROR_RC = 2
SOCKET_ERROR_RC = 3
GOOGLE_API_ERROR_RC = 4
NETWORK_ERROR_RC = 5
FILE_ERROR_RC = 6
MEMORY_ERROR_RC = 7
KEYBOARD_INTERRUPT_RC = 8
HTTP_ERROR_RC = 9
SCOPES_NOT_AUTHORIZED_RC = 10
DATA_ERROR_RC = 11
API_ACCESS_DENIED_RC = 12
CONFIG_ERROR_RC = 13
SYSTEM_ERROR_RC = 14
NO_SCOPES_FOR_API_RC = 15
CLIENT_SECRETS_JSON_REQUIRED_RC = 16
OAUTH2SERVICE_JSON_REQUIRED_RC = 16
OAUTH2_TXT_REQUIRED_RC = 16
INVALID_JSON_RC = 17
JSON_ALREADY_EXISTS_RC = 17
AUTHENTICATION_TOKEN_REFRESH_ERROR_RC = 18
HARD_ERROR_RC = 19
# Information
ENTITY_IS_A_USER_RC = 20
ENTITY_IS_A_USER_ALIAS_RC = 21
ENTITY_IS_A_GROUP_RC = 22
ENTITY_IS_A_GROUP_ALIAS_RC = 23
ENTITY_IS_AN_UNMANAGED_ACCOUNT_RC = 24
CHECK_USER_GROUPS_ERROR_RC = 29
ORPHANS_COLLECTED_RC = 30
# Warnings/Errors
ACTION_FAILED_RC = 50
ACTION_NOT_PERFORMED_RC = 51
INVALID_ENTITY_RC = 52
BAD_REQUEST_RC = 53
ENTITY_IS_NOT_UNIQUE_RC = 54
DATA_NOT_AVALIABLE_RC = 55
ENTITY_DOES_NOT_EXIST_RC = 56
ENTITY_DUPLICATE_RC = 57
ENTITY_IS_NOT_AN_ALIAS_RC = 58
ENTITY_IS_UKNOWN_RC = 59
NO_ENTITIES_FOUND_RC = 60
INVALID_DOMAIN_RC = 61
INVALID_DOMAIN_VALUE_RC = 62
INVALID_TOKEN_RC = 63
JSON_LOADS_ERROR_RC = 64
MULTIPLE_DELETED_USERS_FOUND_RC = 65
MULTIPLE_PROJECT_FOLDERS_FOUND_RC = 65
STDOUT_STDERR_ERROR_RC = 66
INSUFFICIENT_PERMISSIONS_RC = 67
REQUEST_COMPLETED_NO_RESULTS_RC = 71
REQUEST_NOT_COMPLETED_RC = 72
SERVICE_NOT_APPLICABLE_RC = 73
TARGET_DRIVE_SPACE_ERROR_RC = 74
USER_REQUIRED_TO_CHANGE_PASSWORD_ERROR_RC = 75
USER_SUSPENDED_ERROR_RC = 76
NO_CSV_DATA_TO_UPLOAD_RC = 77
```

View File

@ -0,0 +1,41 @@
# GAM setup with minimal GCP permissions.
- GCP Admin can create a project for the Workspace / GAM admin.
- GAM admin needs following permissions on the created project resource:
```
clientauthconfig.brands.create
clientauthconfig.brands.update
clientauthconfig.clients.create
clientauthconfig.clients.createSecret
clientauthconfig.clients.delete
clientauthconfig.clients.get
clientauthconfig.clients.getWithSecret
clientauthconfig.clients.list
clientauthconfig.clients.listWithSecrets
clientauthconfig.clients.update
iam.serviceAccountKeys.create
iam.serviceAccounts.create
iam.serviceAccounts.list
iam.serviceAccounts.setIamPolicy
oauthconfig.testusers.get
oauthconfig.verification.get
resourcemanager.projects.get
serviceusage.services.enable
serviceusage.services.get
serviceusage.services.list
```
Reasons for permission by service:
| Service(s) | Reason |
|---------|--------|
| clientauthconfig and oauthconfig | Manage the [OAuth Consent Page](https://developers.google.com/workspace/guides/configure-oauth-consent) |
| iam | Manage service accounts and their keys |
| serviceusage | Enable Google API services |
| resourcemanager | Read basic project info |
- Once GAM admin has rights to the new project they can complete setup with:
```
gam use project
```
admin will be prompted for the project ID.

View File

@ -0,0 +1,16 @@
# GAMADV-XTD3 on Android Devices
GAMADV-XTD3 now runs on 64-bit Android devices such as Google's Pixel phones. The installation requires an app that adds the Linux environment to Android such as [UserLAnd](https://play.google.com/store/apps/details?id=tech.ula&hl=en_US).
_Note: Chromebooks / Chrome OS devices should install GAMADV-XTD3 using [these instructions](GAMADV-XTD3-on-Chrome-OS-Devices)._
1. Install the [UserLAnd](https://play.google.com/store/apps/details?id=tech.ula&hl=en_US) app.
2. Click Debian to install a Debian environment.
3. Set a username and password.
4. Choose SSH for connection type.
5. Once setup, login with the password to get to a Linux shell.
6. Run the following commands to install prerequisites:
```
sudo apt update
sudo apt install curl python3
```
7. [How to Install Advanced GAM](How-to-Install-Advanced-GAM)

View File

@ -0,0 +1,14 @@
# GAMADV-XTD3 on Chrome OS Devices
Chrome OS devices that [support Linux apps](https://support.google.com/chromebook/answer/9145439?hl=en) can run GAMADV-XTD3. This includes Intel/AMD x86_64 Chromebooks as well as ARM-based Chromebooks with Mediatek or Rockchip 64-bit CPUs.
1. [Set up Linux on your Chromebook](https://support.google.com/chromebook/answer/9145439?hl=en).
1. From the Terminal app, run the following commands:
```
sudo apt update
sudo apt install xz-utils
```
3. [How to Install Advanced GAM](How-to-Install-Advanced-GAM)
# Google cloud shell
Note that from a Chrome OS device, it might be just as easy to use [Google Cloud Shell](https://cloud.google.com/shell). Especially if you are concerned about network connectivity and/or bandwidth, using a shell instance within Google's server infrastructure is always going to be less resource intensive than sending data back and forth between a Google API and your local machine on your local network.

3592
docs/GamUpdates.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
# Google Data Transfers
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Display transfer apps](#display-transfer-apps)
- [Create transfers](#create-transfers)
- [Display transfers](#display-transfers)
## API documentation
* https://developers.google.com/admin-sdk/data-transfer/v1/reference/transfers
* https://support.google.com/a/answer/1247799
* Explains how background drive transfers work, including orphaned files, trashed file behaviour (not transfered), etc.
## Definitions
```
<DataTransferService> ::=
calendar|
currents|
datastudio|"google data studio"|
drive|gdrive|googledrive|"drive and docs"
<DataTransferServiceList> ::= "<DataTransferService>(,<DataTransferService>)*"
<UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
<OldOwnerID> ::= <UserItem>
<NewOwnerID> ::= <UserItem>
<TransferID> ::= <String>
```
## Display transfer apps
```
gam print|show transferapps
```
## Create transfers
```
gam create|add datatransfer|transfer <OldOwnerID> <DataTransferServiceList> <NewOwnerID>
[private|shared|all] [privacy_level private|shared|private,shared]
[releaseresources [<Boolean>]]
(<ParameterKey> <ParameterValue>)*
```
For`datastudio` and `drive`, there are options to control the privacy level of the files to be transferred.
* `private` or `privacy_level private` - Transfer files that are not shared with anyone
* `shared` or `privacy_level shared` - Transfer files shared with at least one other user; this is the **default**
* `all` or `privacy_level private,shared` - Transfer all files
For calendars, there is an option to indicate whether to release resources for future events.
* `releaseresources false` - Do not release resources for future events; this is the default.
* `releaseresources` or `releaseresources true` - Release resources for future events
A `<TransferID>` is returned which can be used to monitor the progress of the transfer.
NOTE: For calendars, the behaviour is not sufficiently defined in the API documentation.
As of 2020-06-10, background transfers only transfer future non-private events with at least one guest/resource.
The option `<ParameterKey> <ParameterValue>` is for future expansion.
## Display transfers
```
gam info datatransfer|transfer <TransferID>
gam show datatransfers|transfers
[olduser|oldowner <UserItem>] [newuser|newowner <UserItem>]
[status completed|failed|inprogress|<String>] [delimiter <Character>]
gam print datatransfers|transfers [todrive <ToDriveAttribute>*]
[olduser|oldowner <UserItem>] [newuser|newowner <UserItem>]
[status completed|failed|inprogress|<String>] [delimiter <Character>]
```
By default, all data transfer operations are printed, use these options to select specific transfers.
* `olduser|oldowner <UserItem>`
* `newuser|newowner <UserItem>`
* `status completed|failed|inprogress`
By default, the entries in lists of items are separated by the `csv_output_field_delimiter` from `gam.cfg`.
* `delimiter <Character>` - Separate list items with `<Character>`

View File

@ -0,0 +1,58 @@
# Google Network Addresses
All GAM calls are made on port 443 (HTTPS) to the following addresses:
```
https://dns.google
https://accounts.google.com
https://accesscontextmanager.googleapis.com
https://admin.googleapis.com
https://alertcenter.googleapis.com
https://audit.googleapis.com
https://calendar.googleapis.com
https://chat.googleapis.com
https://chromemanagement.googleapis.com
https://chromepolicy.googleapis.com
https://classroom.googleapis.com
https://cloudidentity.googleapis.com
https://cloudresourcemanager.googleapis.com
https://contacts.googleapis.com
https://datastudio.googleapis.com
https://docs.googleapis.com
https://drive.googleapis.com
https://driveactivity.googleapis.com
https://drivelabels.googleapis.com
https://forms.googleapis.com
https://gmail.googleapis.com
https://groupsmigration.googleapis.com
https://groupssettings.googleapis.com
https://keep.googleapis.com
https://iam.googleapis.com
https://iap.googleapis.com
https://licensing.googleapis.com
https://oauth2.googleapis.com
https://people.googleapis.com
https://pubsub.googleapis.com
https://reseller.googleapis.com
https://sheets.googleapis.com
https://siteverification.googleapis.com
https://storage.googleapis.com
https://tasks.googleapis.com
https://vault.googleapis.com
https://versionhistory.googleapis.com
https://www.googleapis.com
```
Other addresses used to support GAM but not directly accessed by GAM.
```
https://admin.google.com
https://console.cloud.google.com
https://www.google.com
https://api.github.com
https://raw.githubusercontent.com
```
The following command introduced in 6.25.15 can be used to verify the Google connections.
```
gam checkconnection
```

783
docs/Groups-Membership.md Normal file
View File

@ -0,0 +1,783 @@
# Groups - Membership
- [API documentation](#api-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [Collections of Users](#collections-of-users)
- [Select users based on suspension state](#select-users-based-on-suspension-state)
- [Select users based on archived state](#select-users-based-on-archived-state)
- [Add members to a group](#add-members-to-a-group)
- [Delete members from a group](#delete-members-from-a-group)
- [Synchronize members in a group](#synchronize-members-in-a-group)
- [Delete members from a group by role or status](#delete-members-from-a-group-by-role-or-status)
- [Update member roles and delivery options](#update-member-roles-and-delivery-options)
- [Bulk membership changes](#bulk-membership-changes)
- [Display user group member options](#display-user-group-member-options)
- [Display group membership in CSV format](#display-group-membership-in-csv-format)
- [Display group membership in hierarchical format](#display-group-membership-in-hierarchical-format)
## API documentation
* https://developers.google.com/admin-sdk/directory/v1/reference/members
## Definitions
```
<DeliverySetting> ::=
allmail|
abridged|daily|
digest|
disabled|
none|nomail
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<EmailItem> ::= <EmailAddress>|<UniqueID>|<String>
<UniqueID> ::= id:<String>
<GroupItem> ::= <EmailAddress>|<UniqueID>|<String>
<GroupList> ::= "<GroupItem>(,<GroupItem>)*"
<GroupEntity> ::= <GroupList>|<FileSelector>|<CSVkmdSelector>|<CSVDataSelector>
<GroupRole> ::= owner|manager|member
<GroupRoleList> ::= "<GroupRole>(,<GroupRole>)*"
<GroupType> ::= customer|group|user
<GroupTypeList> ::= "<GroupType>(,<GroupType>)*"
<QueryGroup> ::= <String>
See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
<MembersFieldName> ::=
delivery|deliverysettings|
email|useremail|
group|groupemail|
id|
name|
role|
status|
type
<MembersFieldNameList> ::= "<MembersFieldName>(,<MembersFieldName>)*"
```
## Collections of Users
Group membership commands involve specifying collections of users;
for `<UserTypeEntity>`, see: [Collections of Users](Collections-of-Users)
### Select users based on suspension state
When adding, deleting or synchronizing group members, to select only suspended or non-suspended users, use the following`<UserTypeEntity>`:
```
(all users_ns|users_susp)|
(domains_ns|domains_susp <DomainNameList>)|
(group_ns|group_susp <GroupItem>)|
(groups_ns|groups_susp <GroupList>)|
(group_users_ns|group_users_susp <GroupList>
[members] [managers] [owners]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(ou_ns|ou_susp <OrgUnitItem>)|
(ou_and_children_ns|ou_and_children_susp <OrgUnitItem>)|
(ous_ns|ous_susp <OrgUnitList>)|
(ous_and_children_ns|ous_and_children_susp <OrgUnitList>)
```
When adding, deleting or synchronizing group members, the `notsuspended|suspended` option can be used to select
users in a particular suspension state. This option can be used with the following `<UserTypeEntity>`:
```
(all users)|
(domains <DomainNameList>)|
(group <GroupItem>)|
(groups <GroupList>)|
(group_users <GroupList>
[members] [managers] [owners]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(ou <OrgUnitItem>)|
(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|
(ous_and_children <OrgUnitList>)
```
### Select users based on archived state
When adding, deleting or synchronizing group members, the `notarchived|archived` option can be used to select
users in a particular archived state. This option can be used with the following `<UserTypeEntity>`:
```
(all users|users_ns|users_susp|users_ns_susp)|
(domains|domains_ns|domains_susp <DomainNameList>)|
(group|group_ns|group_susp <GroupItem>)|
(groups|groups_ns|groups_susp <GroupList>)|
(group_users|group_users_ns|group_users_susp <GroupList>
[members] [managers] [owners]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(ou|ou_ns|ou_susp <OrgUnitItem>)|
(ou_and_children|ou_and_children_ns|ou_and_children_susp <OrgUnitItem>)|
(ous|ous_ns|ous_susp <OrgUnitList>)|
(ous_and_children|ous_and_children_ns|ous_and_children_susp <OrgUnitList>)|
(query <QueryUser>)|
(queries <QueryUserList>)
```
Prior to bersion `6.20.05`, the `notarchived|archived` option could only be used with the following `<UserTypeEntity>`:
```
(group|group_ns|group_susp <GroupItem>)|
(groups|groups_ns|groups_susp <GroupList>)|
(group_users|group_users_ns|group_users_susp <GroupList>
[members] [managers] [owners]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)
```
## Add members to a group
```
gam update group|groups <GroupEntity> create|add [<GroupRole>]
[usersonly|groupsonly]
[notsuspended|suspended] [notarchived|archived]
[[delivery] <DeliverySetting>]
[preview] [actioncsv]
<UserItem>|<UserTypeEntity>
```
When `<UserTypeEntity>` specifies a group or groups:
* `usersonly` - Only the user members from the specified groups are added
* `groupsonly` - Only the group members from the specified groups are added
For `notsuspended|suspended`, see: [Select users based on suspension state](#select-users-based-on-suspension-state)
For `notarchived|archived`, see: [Select users based on archived state](#select-users-based-on-archived-state)
You can set the `delivery` option for the new members:
* `allmail` - All messages, delivered as soon as they arrive
* `abridged|daily` - No more than one message a day
* `digest` - Up to 25 messages bundled into a single message
* `none|nomail` - No messages
* `disabled` - Remove subscription; this is what the documentation says, it's not clear what it means
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `group,email,role,action,message` is generated
that shows the actions performed when updating the group.
Gam adds the members in batches and pauses between batches in order to avoid exceeding Google's quota limits. The size of the batch
is set in `gam.cfg/batch_size` and the pause in `gam.cfg/inter_watch_wait`. For add, values of 20 and 1 seem to give reasonable results.
For each batch, if the quota rate limit is exceeded, Gam increases inter_batch_wait by .25 seconds.
For example,
```
gam config batch_size 20 inter_batch_wait 1 update group testgroup@domain.com add members file users.lst
```
### `actioncsv` Example
Using `actioncsv` produces a CSV file showing the actions taken.
```
$ gam redirect csv AddUpdates.csv update group testgroup add members actioncsv users testuser2,testuser3
Group: testgroup@domain.com, Add 2 Members
Group: testgroup@domain.com, Member: testuser2@domain.com, Added: Role: MEMBER (1/2)
Group: testgroup@domain.com, Member: testuser3@domain.com, Add Failed: Member already exists. (2/2)
$ more AddUpdates.csv
group,email,role,action,message
testgroup@domain.com,testuser2@domain.com,MEMBER,Added,Success
testgroup@domain.com,testuser3@domain.com,MEMBER,Add Failed,Member already exists.
```
## Delete members from a group
```
gam update group|groups <GroupEntity> delete|remove [<GroupRole>]
[usersonly|groupsonly]
[notsuspended|suspended] [notarchived|archived]
[preview] [actioncsv]
<UserItem>|<UserTypeEntity>
```
`<GroupRole>` is ignored, deletions take place regardless of role.
When `<UserTypeEntity>` specifies a group or groups:
* `usersonly` - Only the user members from the specified groups are deleted
* `groupsonly` - Only the group members from the specified groups are deleted
For `notsuspended|suspended`, see: [Select users based on suspension state](#select-users-based-on-suspension-state)
For `notarchived|archived`, see: [Select users based on archived state](#select-users-based-on-archived-state)
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `group,email,role,action,message` is generated
that shows the actions performed when updating the group.
Gam deletes the members in batches and pauses between batches in order to avoid exceeding Google's quota limits. The size of the batch
is set in `gam.cfg/batch_size` and the pause in `gam.cfg/inter_watch_wait`. For delete, values of 20 and 2 seem to give reasonable results.
For each batch, if the quota rate limit is exceeded, Gam increases inter_batch_wait by .25 seconds.
For example,
```
gam config batch_size 20 inter_batch_wait 2 update group testgroup@domain.com delete members file users.lst
```
### `actioncsv` Example
Using `actioncsv` produces a CSV file showing the actions taken.
```
$ gam redirect csv DeleteUpdates.csv update group testgroup delete members actioncsv users testuser2,testuser4
Group: testgroup@domain.com, Remove 2 Members
Group: testgroup@domain.com, Member: testuser2@domain.com, Removed: Role: MEMBER (1/2)
Group: testgroup@domain.com, Member: testuser4@domain.com, Remove Failed: Does not exist (2/2)
$ more DeleteUpdates.csv
group,email,role,action,message
testgroup@domain.com,testuser2@domain.com,MEMBER,Removed,Success
testgroup@domain.com,testuser4@domain.com,MEMBER,Remove Failed,Does not exist
```
## Synchronize members in a group
A synchronize operation gets the current membership for a group and does adds and deletes as necessary to make it match `<UserTypeEntity>`.
```
gam update group|groups <GroupEntity> sync [<GroupRole>]
[usersonly|groupsonly] [addonly|removeonly]
[notsuspended|suspended] [notarchived|archived]
[remove_domain_nostatus_members]
[[delivery] <DeliverySetting>]
[preview] [actioncsv]
(additionalmembers [<GroupRole>] <EmailAddressEntity>)*
<UserItem>|<UserTypeEntity>
```
If `<GroupRole>` is not specified, `member` is assumed.
When `<UserTypeEntity>` specifies a group or groups:
* `usersonly` - Only the user members from the specified groups are added/deleted
* `groupsonly` - Only the group members from the specified groups are added/deleted
For `notsuspended|suspended`, see: [Select users based on suspension state](#select-users-based-on-suspension-state)
For `notarchived|archived`, see: [Select users based on archived state](#select-users-based-on-archived-state)
The `notsuspended|suspended` and `notarchived|archived` not only control what users are selected from `<UserTypeEntity>`
but they also control what users are selected from `<GroupEntity>`.
The `remove_domain_nostatus_members` option is used to remove members from the group that are in your domain but have no status.
These members were added to the group before the user or group that they represent was created.
Your domain is defined as the value from `domain` in `gam.cfg` if it is defined, or, if not, the domain of your Google Workspace Admin in oauth2.txt.
You can set the `delivery` option for the new members:
* `allmail` - All messages, delivered as soon as they arrive
* `abridged|daily` - No more than one message a day
* `digest` - Up to 25 messages bundled into a single message
* `none|nomail` - No messages
* `disabled` - Remove subscription; this is what the documentation says, it's not clear what it means
Default:
* members in `<UserTypeEntity>` that are not in the current membership will be added
* members in the current membership that are not in `<UserTypeEntity>` will deleted
When the `addonly` option is specified:
* members in `<UserTypeEntity>` that are not in the current membership will be added
* members in the current membership that are not in `<UserTypeEntity>` will not be deleted
When the `removeonly` option is specified:
* members in `<UserTypeEntity>` that are not in the current membership will not be added
* members in the current membership that are not in `<UserTypeEntity>` will be deleted
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `group,email,role,action,message` is generated
that shows the actions performed when updating the group.
The option `additionalmembers [<GroupRole>] <EmailAddressEntity>` can be used to specify members in addition to those specified with `<UserTypeEntity>`.
For example,
```
gam update group teachers@domain.com sync member additionalmembers counselor@domain.com ou /Teachers
```
Gam adds/deletes the members in batches and pauses between batches in order to avoid exceeding Google's quota limits. The size of the batch
is set in `gam.cfg/batch_size` and the pause in `gam.cfg/inter_watch_wait`. For sync, values of 20 and 1 seem to give reasonable results for
the adds but the inter_batch_wait is probably too low for the deletes; for each batch, if the quota rate limit is exceeded, Gam increases inter_batch_wait by .25 seconds.
For example,
```
gam config batch_size 20 inter_batch_wait 1 update group testgroup@domain.com sync members file users.lst
```
### Examples using CSV file and Google sheets:
* https://github.com/taers232c/GAMADV-XTD3/wiki/Collections-of-Users#examples-using-csv-files-and-google-sheets-to-update-the-membership-of-a-group
### Example
Assume that at your school there is a group for each grade level and the members come from an OU; here is a sample CSV file GradeOU.csv
```
Grade,OU
seniors@domain.org,/Students/ClassOf2023
juniors@domain.org,/Students/ClassOf2024
...
```
This allows you to do: `gam csv GradeOU.csv gam update group ~Grade sync members ou ~OU`
But suppose that at each grade level there are additional group members that are groups of faculty/staff; e.g., senioradvisors@domain.org.
In this scenario, you can't do the `update group sync` command as the members that are groups will be deleted; the `usersonly` option allows
the `update group sync` command to work: `gam csv GradeOU.csv gam update group ~Grade sync members usersonly ou ~OU`
The users from the OU are matched against the user members of the group and adds/deletes are done as necessary to synchronize them;
the group members of the group are unaffected.
### `actioncsv` Example
Using `actioncsv` produces a CSV file showing the actions taken.
```
$ gam redirect csv SyncUpdates.csv update group testgroup sync members actioncsv users testuser1,testuser3,testuser4
Getting all Members for testgroup@domain.com, may take some time on a large Group...
Got 3 Members for testgroup@domain.com...
Group: testgroup@domain.com, Remove 1 Member
Group: testgroup@domain.com, Member: testuser2@domain.com, Removed: Role: MEMBER
Group: testgroup@domain.com, Add 1 Member
Group: testgroup@domain.com, Member: testuser4@domain.com, Added: Role: MEMBER
$ more SyncUpdates.csv
group,email,role,action,message
testgroup@domain.com,testuser2@domain.com,MEMBER,Removed,Success
testgroup@domain.com,testuser4@domain.com,MEMBER,Added,Success
```
## Delete members from a group by role or status
```
gam update group|groups <GroupEntity> clear [member] [manager] [owner]
[usersonly|groupsonly]
[notsuspended|suspended] [notarchived|archived]
[emailclearpattern|emailretainpattern <RegularExpression>]
[remove_domain_nostatus_members]
[preview] [actioncsv]
```
If none of `member`, `manager`, or `owner` are specified, `member` is assumed.
By default, when clearing members from a group, all members, whether users or groups, are included.
* `usersonly` - Clear only the user members
* `groupsonly` - Clear only the group members
By default, when clearing members from a group, all members, whether suspended/archived or not, are included.
* `notsuspended` - Clear only non-suspended members
* `suspended` - Clear only suspended members
* `notarchived` - Clear only non-archived members
* `archived` - Clear only archived users
* `notsuspended notarchived` - Do not clear suspended and archived members
* `suspended archived` - Clear suspended and archived members
* `notsuspended archived` - Do not clear archived members
* `suspended notarchived` - Do not clear suspended members
Members that have met the above qualifications to be cleared can be further qualifed by their email address.
* `emailclearpattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be cleared; others will be retained
* `emailretainpattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be retained; others will be cleared
The `remove_domain_nostatus_members` option is used to clear members from the group that are in your domain but have no status.
These members were added to the group before the user or group that they represent was created.
Your domain is defined as the value from `domain` in `gam.cfg` if it is defined, or, if not, the domain of your Google Workspace Admin in oauth2.txt.
If `preview` is specified, the deletes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `group,email,role,action,message` is generated
that shows the actions performed when updating the group.
Gam deletes the members in batches and pauses between batches in order to avoid exceeding Google's quota limits. The size of the batch
is set in `gam.cfg/batch_size` and the pause in `gam.cfg/inter_watch_wait`. For delete, values of 20 and 2 seem to give reasonable results.
For each batch, if the quota rate limit is exceeded, Gam increases inter_batch_wait by .25 seconds.
For example,
```
gam config batch_size 20 inter_batch_wait 2 update group testgroup@domain.com clear members
```
## Update member roles and delivery options
```
gam update group|groups <GroupEntity> update [<GroupRole>]
[usersonly|groupsonly]
[notsuspended|suspended] [notarchived|archived]
[[delivery] <DeliverySetting>]
[createifnotfound]
[preview] [actioncsv]
<UserItem>|<UserTypeEntity>
```
There are two items that can be updated: role and delivery. If neither option is specified,
the users are updated to members; this is the behavior from previous versions. Otherwise,
only the specified items are updated.
When `<UserTypeEntity>` specifies a group or groups:
* `usersonly` - Only the user members from the specified groups are added
* `groupsonly` - Only the group members from the specified groups are added
By default, when updating members from organization units, all users, whether suspended or not, are included.
* `notsuspended` - Do not include suspended users
* `suspended` - Only include suspended users
By default, when updating members from groups, all users, whether suspended/archived or not, are included.
* `notsuspended` - Do not include suspended users
* `suspended` - Only include suspended users
* `notarchived` - Do not include archived users
* `archived` - Only include archived users
* `notsuspended notarchived` - Do not include suspended and archived users
* `suspended archived` - Include only suspended or archived users
* `notsuspended archived` - Only include archived users
* `suspended notarchived` - Only include suspended users
You can set the `delivery` option for the updated members:
* `allmail` - All messages, delivered as soon as they arrive
* `abridged|daily` - No more than one message a day
* `digest` - Up to 25 messages bundled into a single message
* `none|nomail` - No messages
* `disabled` - Remove subscription; this is what the documentation says, it's not clear what it means
If, when attempting to update the role of a group member, the group member is not found, the `createifnotfound` option causes Gam to add the member with the specified role.
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `group,email,role,action,message` is generated
that shows the actions performed when updating the group.
## Bulk membership changes
### Example 1
The file Users.csv has a single column of email addresses, there is no header row.
```
user1@domain.com
user2@domain.com
...
gam update group group@domain.com sync members file Users.csv
```
The Google Sheet `user@domain.com <DriveFileID> <SheetEntity>` has a single column of email addresses, there is no header row.
Define an implicit header with the `fields Email` option.
```
user1@domain.com
user2@domain.com
...
gam update group group@domain.com sync members csvfile gsheet:Email user@domain.com <DriveFileID> <SheetEntity> fields Email
```
The Google Doc `user@domain.com <DriveFileID>` has a single column of email addresses, there is no header row.
```
user1@domain.com
user2@domain.com
...
gam update group group@domain.com sync members file gdoc user@domain.com <DriveFileID>
```
### Example 2
The CSV file Users.csv has one column of email addresses labelled Email.
```
Email
user1@domain.com
user2@domain.com
...
gam update group group@domain.com sync members csvfile Users.csv:Email
```
The Google Sheet `user@domain.com <DriveFileID> <SheetEntity>` has one column of email addresses labelled Email.
```
Email
user1@domain.com
user2@domain.com
...
gam update group group@domain.com sync members csvfile gsheet:Email user@domain.com <DriveFileID> <SheetEntity>
```
### Example 3
The CSV file Users.csv has two columns of email addresses labelled Email1 and Email2.
```
Email1,Email2
user1@domain.com,user2@domain.com
user3@domain.com,user4@domain.com
...
gam update group group@domain.com sync members csvfile Users.csv:Email1:Email2
```
The Google Sheet `user@domain.com <DriveFileID> <SheetEntity>` has two columns of email addresses labelled Email1 and Email2.
```
Email1,Email2
user1@domain.com,user2@domain.com
user3@domain.com,user4@domain.com
...
gam update group group@domain.com sync members csvfile gsheet:Email1:Email2 user@domain.com <DriveFileID> <SheetEntity>
```
### Example 4
The file Groups.txt has a single column of group email addresses, there is no header row.
You want to sync with the members of those groups.
```
group1@domain.com
group2@domain.com
...
gam update group group@domain.com sync members datafile groups Groups.txt
```
The Google Doc `user@domain.com <DriveFileID>` has a single column of group email addresses, there is no header row.
You want to sync with the members of those groups.
```
group1@domain.com
group2@domain.com
...
gam update group group@domain.com sync members datafile groups gdoc user@domain.com <DriveFileID>
```
### Example 5
The CSV file Groups.csv has a single column of group email addresses labelled Group.
You want to sync with the members of those groups.
```
Group
group1@domain.com
group2@domain.com
...
gam update group group@domain.com sync members csvdatafile groups Groups.csv:Group
```
The Google Sheet `user@domain.com <DriveFileID> <SheetEntity>` has a single column of group email addresses labelled Group.
You want to sync with the members of those groups.
```
Group
group1@domain.com
group2@domain.com
...
gam update group group@domain.com sync members csvdatafile groups gsheet:Group user@domain.com <DriveFileID> <SheetEntity>
```
### Example 6
The CSV file GroupMembers.csv has headers: group,role,email
Each row contains a group email address, member role (OWNER, MEMBER, MANAGER) and a member email address.
The following command will synchronize the membership for all groups and roles.
```
gam redirect stdout ./MemberUpdates.txt redirect stderr stdout update group csvkmd GroupMembers.csv keyfield group subkeyfield role datafield email sync csvdata email
```
The Google Sheet `user@domain.com <DriveFileID> <SheetEntity>` has headers: group,role,email
Each row contains a group email address, member role (OWNER, MEMBER, MANAGER) and a member email address.
The following command will synchronize the membership for all groups and roles.
```
gam redirect stdout ./MemberUpdates.txt redirect stderr stdout update group csvkmd gsheet user@domain.com <DriveFileID> <SheetEntity> keyfield group subkeyfield role datafield email sync csvdata email
```
You can also do `create|add`, `delete` and `update` in this manner.
If you want to update a specific role, you can do one of the following.
```
gam redirect stdout ./MemberUpdates.txt redirect stderr stdout update group csvkmd ./GroupMembers.csv keyfield group matchfield role MEMBER datafield email sync member csvdata email
gam redirect stdout ./ManagerUpdates.txt redirect stderr stdout update group csvkmd ./GroupMembers.csv keyfield group matchfield role MANAGER datafield email sync manager csvdata email
gam redirect stdout ./OwnerUpdates.txt redirect stderr stdout update group csvkmd ./GroupMembers.csv keyfield group matchfield role OWNER datafield email sync owner csvdata email
```
## Display user group member options
Display user's group membership information. Delivery information is displayed; an additional API call per user is required.
```
gam <UserTypeEntity> info member|group-members <GroupEntity>
gam info member|group-members <UserItem>|<UserTypeEntity> <GroupEntity>
```
## Display group membership in CSV format
By default, delivery information is not displayed.
```
gam print group-members [todrive <ToDriveAttribute>*]
[([domain <DomainName>] ([member|showownedby <EmailItem>]|[query <QueryGroup>]))|
(group|group_ns|group_susp <GroupItem>)|
(select <GroupEntity>)]
[emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
[descriptionmatchpattern [not] <RegularExpression>]
[admincreatedmatch <Boolean>]
[roles <GroupRoleList>] [members] [managers] [owners]
[membernames] [showdeliverysettings]
<MembersFieldName>* [fields <MembersFieldNameList>]
[notsuspended|suspended] [notarchived|archived]
[types <GroupTypeList>]
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
[userfields <UserFieldNameList>]
[(recursive [noduplicates])|includederivedmembership] [nogroupemail]
[peoplelookup|(peoplelookupuser <EmailAddress>)]
[formatjson [quotechar <Character>]]
```
By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups:
* `domain <DomainName>` - Limit display to groups in the domain `<DomainName>`
* `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>`
* `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>`
* `query <QueryGroup>` - Limit display to groups that match `<QueryGroup>`, matching is done at Google; mutually exclusive with `member <UserItem>`
* `group <GroupItem>` - Limit display to the single group `<GroupItem>`
* `group_ns <GroupItem>` - Limit display to the single group `<GroupItem>`, display non-suspended members
* `group_susp <GroupItem>` - Limit display to the single group `<GroupItem>`, display suspended members
* `select <GroupEntity>` - Limit display to the groups specified in `<GroupEntity>`
* `showownedby <UserItem>` - Limit display to groups owned by `<UserItem>`
When using `query <QueryGroup>` with the `name:{PREFIX}*` query, `PREFIX` must contain at least three characters.
You can identify groups with the `All users in the organization` member with:
* `query "memberKey=<CustomerID>"` - All versions
* `member id:<CustomerID>` - Version 6.10.06 or later
These options further limit the list of groups selected above:
* `emailmatchpattern <RegularExpression>` - Limit display to groups whose email address matches `<RegularExpression>`
* `emailmatchpattern not <RegularExpression>` - Limit display to groups whose email address does not match `<RegularExpression>`
* `namematchpattern <RegularExpression>` - Limit display to groups whose name matches `<RegularExpression>`
* `namematchpattern not <RegularExpression>` - Limit display to groups whose name does not match `<RegularExpression>`
* `descriptionmatchpattern <RegularExpression>` - Limit display to groups whose description matches `<RegularExpression>`
* `descriptionmatchpattern not <RegularExpression>` - Limit display to groups whose description does not match `<RegularExpression>`
* `admincreatedmatch True` - Limit display to groups created by administrators
* `admincreatedmatch False` - Limit display to groups created by users
By default, all members, managers and owners in the group are displayed; these options modify that behavior:
* `roles <GroupRoleList>` - Display specified roles
* `members` - Display members
* `managers` - Display managers
* `owners` - Display owners
By default, all types of members (customer, group, user) in the group are displayed; when `recursive` is specified,
the default is to only display type user members. This option modifies those behaviors:
* `types <GroupTypeList>` - Display specified types
By default, when displaying members from a group, all members, whether suspended/archived or not, are included.
* `notsuspended` - Display only non-suspended members
* `suspended` - Display only suspended members
* `notarchived` - Do not include archived members
* `archived` - Only include archived members, this is not common but allows creating groups that allow easy identification of archived users
* `notsuspended notarchived` - Do not include suspended and archived members
* `suspended archived` - Include only suspended or archived members
* `notsuspended archived` - Only include archived members, this is not common but allows creating groups that allow easy identification of archived users
* `suspended notarchived` - Only include suspended members, this is not common but allows creating groups that allow easy identification of suspended users
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
By default, the ID, role, email address, type and status of each member are displayed along with the group email address;
these options specify which fields to display:
* `membernames` - Display members full name; an additional API call per member is required
* `showdeliverysettings` - Display delivery settings; an additional API call per member is required
* `<MembersFieldName>*` - Individual field names
* `fields <MembersFieldNameList>` - A comma separated list of field names
* `delivery|deliverysettings` - Specify this field to get delivery information; an additional API call per member is required
* `userfields <UserFieldNameList>` - For members that are users, display these user fields; an additional API call per member is required
If member names are requested, names are not available for users not in the domain; you can request that GAM use the People API to retrieve
names for these users. Names are not retrieved in all cases and success is dependent on what user is used to perform the retrievals.
* `peoplelookup` - Use the administrator named in oauth2.txt to perform the retrievals
* `peoplelookupuser <EmailAddress>` - Use `<EmailAddress>` to perform the retrievals
By default, the group email address is always shown, you can suppress it with the `nogroupemail` option.
By default, members that are groups are displayed as a single entry of type GROUP; this option recursively expands group members to display their user members.
* `recursive` - Recursively expand group members
The `recursive` option does not expand or display members of type CUSTOMER.
The `recursive` option adds two columns, level and subgroup, to the output:
* `level` - At what level of the expansion does the user appear; level 0 is the top level
* `subgroup` - The group that contained the user
Displaying membership of multiple groups or recursive expansion may result in multiple instances of the same user being displayed; these multiple instances can be reduced to one entry.
* `noduplicates` - Reduce multiple instances of the same user to the first instance
The `includederivedmembership` option is an alternative to `recursive`; it causes the API to expand type GROUP and type CUSTOMER
members to display their constituent members while still displaying the original member.
The API produces inconsistent results, use with caution.
The options `recursive noduplicates` and `includederivedmembership types user noduplicates` return the same list of users.
The `includederivedmembership` option makes less API calls but doesn't show level and subgroup information.
Expanding a member of type CUSTOMER may produce a large volume of data as it will display all users in your domain.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display group membership in hierarchical format
```
gam show group-members
[([domain <DomainName>] ([member|showownedby <EmailItem>]|[query <QueryGroup>]))|
(group|group_ns|group_susp <GroupItem>)|
(select <GroupEntity>)]
[emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
[descriptionmatchpattern [not] <RegularExpression>]
[admincreatedmatch <Boolean>]
[roles <GroupRoleList>] [members] [managers] [owners] [depth <Number>]
[notsuspended|suspended] [notarchived|archived]
[types <GroupTypeList>]
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
[includederivedmembership]
```
By default, the group membership of all groups in the account are displayed, these options allow selection of subsets of groups:
* `domain <DomainName>` - Limit display to groups in the domain `<DomainName>`
* `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>`
* `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>`
* `query <QueryGroup>` - Limit display to groups that match `<QueryGroup>`, matching is done at Google; mutually exclusive with `member <UserItem>`
* `group <GroupItem>` - Limit display to the single group `<GroupItem>`
* `group_ns <GroupItem>` - Limit display to the single group `<GroupItem>`, display non-suspended members
* `group_susp <GroupItem>` - Limit display to the single group `<GroupItem>`, display suspended members
* `select <GroupEntity>` - Limit display to the groups specified in `<GroupEntity>`
* `showownedby <UserItem>` - Limit display to groups owned by `<UserItem>`
When using `query <QueryGroup>` with the `name:{PREFIX}*` query, `PREFIX` must contain at least three characters.
You can identify groups with the `All users in the organization` member with:
* `query "memberKey=<CustomerID>"` - All versions
* `member id:<CustomerID>` - Version 6.10.06 or later
These options further limit the list of groups selected above:
* `emailmatchpattern <RegularExpression>` - Limit display to groups whose email address matches `<RegularExpression>`
* `emailmatchpattern not <RegularExpression>` - Limit display to groups whose email address does not match `<RegularExpression>`
* `namematchpattern <RegularExpression>` - Limit display to groups whose name matches `<RegularExpression>`
* `namematchpattern not <RegularExpression>` - Limit display to groups whose name does not match `<RegularExpression>`
* `descriptionmatchpattern <RegularExpression>` - Limit display to groups whose description matches `<RegularExpression>`
* `descriptionmatchpattern not <RegularExpression>` - Limit display to groups whose description does not match `<RegularExpression>`
* `admincreatedmatch True` - Limit display to groups created by administrators
* `admincreatedmatch False` - Limit display to groups created by users
By default, all members, managers and owners in the group are displayed; these options modify that behavior:
* `roles <GroupRoleList>` - Display specified roles
* `members` - Display members
* `managers` - Display managers
* `owners` - Display owners
By default, when displaying members from a group, all members, whether suspended/archived or not, are included.
* `notsuspended` - Display only non-suspended members
* `suspended` - Display only suspended members
* `notarchived` - Do not include archived members
* `archived` - Only include archived members, this is not common but allows creating groups that allow easy identification of archived users
* `notsuspended notarchived` - Do not include suspended and archived members
* `suspended archived` - Include only suspended or archived members
* `notsuspended archived` - Only include archived members, this is not common but allows creating groups that allow easy identification of archived users
* `suspended notarchived` - Only include suspended members, this is not common but allows creating groups that allow easy identification of suspended users
By default, all types of members (customer, group, user) in the group are displayed; this option modifies that behavior:
* `types <GroupTypeList>` - Display specified types
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
By default, members of type GROUP are recursively expanded to show their constituent members. (Members of
type CUSTOMER are not expanded.) The `depth <Number>` argument controls the depth to which nested groups are displayed.
* `depth -1` - all groups in the selected group and below are displayed; this is the default.
* `depth 0` - the groups within a selected group are displayed, no descendants are displayed.
* `depth N` - the groups within the selected group and those groups N levels below the selected group are displayed.
The `includederivedmembership` option causes the API to expand type GROUP and type CUSTOMER
members to display their constituent members while still displaying the original member.
The options `types user` and `includederivedmembership types user` return the same list of users.
The `includederivedmembership` option makes less API calls but doesn't show hierarchy.
Expanding a member of type CUSTOMER may produce a large volume of data as it will display all users in your domain.
### Display group structure
To see a group's structure of nested groups use the `type group` option.
```
$ gam show group-members group testgroup5 types group
Group: testgroup5@domain.com
MEMBER, GROUP, testgroup1@domain.com, ACTIVE
MEMBER, GROUP, testgroup2@domain.com, ACTIVE
MEMBER, GROUP, testgroup3@domain.com, ACTIVE
MEMBER, GROUP, testgroup2@domain.com, ACTIVE
MEMBER, GROUP, testgroup4@domain.com, ACTIVE
```
To show the structure of all groups you can do the following; it will be time consuming for a large number of groups.
```
gam redirect stdout ./groups.txt show group-members types group
```
### Examples
#### Print a CSV of all members of a group regardless of role, all fields
```
gam print group-members <GroupEntity>
```
#### Print a CSV containing all managers emails
```
gam print group-members <GroupEntity> role manager fields email
```
#### Print a CSV output of all members and their emails only
```
gam print group-members <GroupEntity> role member fields email
```
#### Display group owners in your domain, but excluding groups where the email starts with a 4 digit code
```
gam print group-members domain <Your Domain> emailmatchpattern not '^1234.*' roles owners
```

558
docs/Groups.md Normal file
View File

@ -0,0 +1,558 @@
# Groups
- [API documentation](#api-documentation)
- [Name guidelines](#name-guidelines)
- [Query documentation](#query-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Cloud Identity Groups](#cloud-identity-groups)
- [Security Groups](#security-groups)
- [Transition to new Group Settings](#transition-to-new-Group-settings)
- [Collaborative Inbox](#collaborative-inbox)
- [Definitions](#definitions)
- [GUI API Group settings mapping](#gui-api-group-settings-mapping)
- [GUI API Group access type settings mapping](#gui-api-group-access-type-settings-mapping)
- [Manage groups](#manage-groups)
- [Update a group's settings with JSON data](#update-a-groups-settings-with-JSON-data)
- [Display information about specific groups](#display-information-about-specific-groups)
- [Display information about selected groups](#display-information-about-selected-groups)
- [Display a group and its parents](#Display-a-group-and-its-parents)
- [Examples](#Examples)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/groups
* https://developers.google.com/admin-sdk/groups-settings/v1/reference/groups
* https://cloud.google.com/identity/docs/groups
* https://cloud.google.com/identity/docs/reference/rest/v1/groups
## Name guidelines
* https://support.google.com/a/answer/9193374?hl=en
## Query documentation
* https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
* https://cloud.google.com/identity/docs/reference/rest/v1/groups#dynamicgroupquery
## Cloud Identity Groups
* https://gsuiteupdates.googleblog.com/2020/08/new-api-cloud-identity-groups-google.html
## Security Groups
* https://gsuiteupdates.googleblog.com/2020/09/security-groups-beta.html
## Transition to new Group Settings
* https://support.google.com/a/answer/9191148
* https://drive.google.com/file/d/1-ux3z6-hcjsPbhAj_EIwS7cd_emkE-NC/view
## Collaborative Inbox
* https://support.google.com/a/answer/167430
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<UniqueID> ::= id:<String>
<EmailItem> ::= <EmailAddress>|<UniqueID>|<String>
<GroupItem> ::= <EmailAddress>|<UniqueID>|<String>
<GroupList> ::= "<GroupItem>(,<GroupItem>)*"
<GroupEntity> ::= <GroupList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<GroupRole> ::= owner|manager|member
<GroupRoleList> ::= "<GroupRole>(,<GroupRole>)*"
<GroupType> ::= customer|group|user
<GroupTypeList> ::= "<GroupType>(,<GroupType>)*"
<QueryGroup> ::= <String>
See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
<QueryDynamicGroup> ::= <String>
See: https://cloud.google.com/identity/docs/reference/rest/v1/groups#dynamicgroupquery
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<GroupSettingsAttribute> ::=
(accesstype public|team|announcementonly|restricted)|
(allowexternalmembers <Boolean>)|
(allowwebposting <Boolean>)|
(archiveonly <Boolean>)|
(customfootertext <String>)|
(customreplyto <EmailAddress>)|
(defaultmessagedenynotificationtext <String>)|
(defaultsender self|group)|
(description <String>)|
(enablecollaborativeinbox|collaborative <Boolean>)|
(includeinglobaladdresslist|gal <Boolean>)|
(includecustomfooter <Boolean>)|
(isarchived <Boolean>)|
(memberscanpostasthegroup <Boolean>)|
(messagemoderationlevel moderate_all_messages|moderate_non_members|moderate_new_members|moderate_none)|
(name <String>)|
(primarylanguage <Language>)|
(replyto reply_to_custom|reply_to_sender|reply_to_list|reply_to_owner|reply_to_ignore|reply_to_managers)|
(sendmessagedenynotification <Boolean>)|
(spammoderationlevel allow|moderate|silently_moderate|reject)|
(whocanadd all_members_can_add|all_managers_can_add|all_owners_can_add|none_can_add)|
(whocancontactowner anyone_can_contact|all_in_domain_can_contact|all_members_can_contact|all_managers_can_contact|all_owners_can_contact)|
(whocanjoin anyone_can_join|all_in_domain_can_join|invited_can_join|can_request_to_join)|
(whocanleavegroup all_members_can_leave|all_managers_can_leave|all_owners_can_leave|none_can_leave)|
(whocanpostmessage none_can_post|all_managers_can_post|all_members_can_post|all_owners_can_post|all_in_domain_can_post|anyone_can_post)|
(whocanviewgroup anyone_can_view|all_in_domain_can_view|all_members_can_view|all_managers_can_view|all_owners_can_view)|
(whocanviewmembership all_in_domain_can_view|all_members_can_view|all_managers_can_view|all_owners_can_view)
<GroupWhoCanDiscoverGroupDeprecatedAttribute> ::=
(showingroupdirectory <Boolean>)
<GroupWhoCanAssistContentDeprecatedAttribute> ::=
(whocanassigntopics all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanenterfreeformtags all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanhideabuse all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmaketopicssticky all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmarkduplicate all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmarkfavoritereplyonanytopic all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmarknoresponseneeded all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmodifytagsandcategories all_members|owners_and_managers|managers_only|owners_only|none)|
(whocantaketopics all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanunassigntopic all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanunmarkfavoritereplyonanytopic all_members|owners_and_managers|managers_only|owners_only|none)
<GroupWhoCanModerateContentDeprecatedAttribute> ::=
(whocanapprovemessages all_members|owners_and_managers|owners_only|none)|
(whocandeleteanypost all_members|owners_and_managers|owners_only|none)|
(whocandeletetopics all_members|owners_and_managers|owners_only|none)|
(whocanlocktopics all_members|owners_and_managers|owners_only|none)|
(whocanmovetopicsin all_members|owners_and_managers|owners_only|none)|
(whocanmovetopicsout all_members|owners_and_managers|owners_only|none)|
(whocanpostannouncements all_members|owners_and_managers|owners_only|none)
<GroupWhoCanModerateMembersDeprecatedAttribute> ::=
(whocanadd all_members_can_add|all_managers_can_add|none_can_add)|
(whocanapprovemembers all_members_can_approve|all_managers_can_approve|all_owners_can_approve|none_can_approve)|
(whocanbanusers all_members|owners_and_managers|owners_only|none)|
(whocaninvite all_members_can_invite|all_managers_can_invite|all_owners_can_invite|none_can_invite)|
(whocanmodifymembers all_members|owners_and_managers|owners_only|none)
<GroupDeprecatedAttribute> ::=
(allowgooglecommunication <Boolean>)|
(favoriterepliesontop <Boolean>)|
(maxmessagebytes <ByteCount>)|
(messagedisplayfont default_font|fixed_width_font)|
(whocanaddreferences all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmarkfavoritereplyonowntopic all_members|owners_and_managers|managers_only|owners_only|none)
<GroupAttribute> ::=
<JSONData>|
<GroupSettingsAttribute>|
(whocandiscovergroup all_members_can_discover|all_in_domain_can_discover|anyone_can_discover)|
(whocanassistcontent all_members|owners_and_managers|managers_only|owners_only|none)|
(whocanmoderatecontent all_members|owners_and_managers|owners_only|none)|
(whocanmoderatemembers all_members|owners_and_managers|owners_only|none)|
<GroupWhoCanDiscoverGroupDeprecatedAttribute>|
<GroupWhoCanAssistContentDeprecatedAttribute>|
<GroupWhoCanModerateContentDeprecatedAttribute>|
<GroupWhoCanModerateMembersDeprecatedAttribute>|
<GroupDeprecatedAttribute>
```
```
<GroupFieldName> ::=
admincreated|
aliases|
allowexternalmembers|
allowgooglecommunication|
allowwebposting|
archiveonly|
customfootertext|
customreplyto|
customrolesenabledforsettingstobemerged|
defaultmessagedenynotificationtext|
description|
directmemberscount|
email|
enablecollaborativeinbox|collaborative|
favoriterepliesontop|
id|
includecustomfooter|
includeinglobaladdresslist|gal|
isarchived|
maxmessagebytes|
memberscanpostasthegroup|
messagedisplayfont|
messagemoderationlevel|
name|
primarylanguage|
replyto|
sendmessagedenynotification|
showingroupdirectory|
spammoderationlevel|
whocanaddreferences|
whocanadd|
whocanapprovemessages|
whocanassigntopics|
whocanassistcontent|
whocancontactowner|
whocandeleteanypost|
whocandeletetopics|
whocandiscovergroup|
whocanenterfreeformtags|
whocanhideabuse|
whocaninvite|
whocanjoin|
whocanleavegroup|
whocanlocktopics|
whocanmaketopicssticky|
whocanmarkduplicate|
whocanmarkfavoritereplyonanytopic|
whocanmarkfavoritereplyonowntopic|
whocanmarknoresponseneeded|
whocanmoderatecontent|
whocanmodifytagsandcategories|
whocanmovetopicsin|
whocanmovetopicsout|
whocanpostannouncements|
whocanpostmessage|
whocantaketopics|
whocanunassigntopic|
whocanunmarkfavoritereplyonanytopic|
whocanviewgroup|
whocanviewmembership
<GroupFieldNameList> ::= "<GroupFieldName>(,<GroupFieldName>)*"
```
```
<CIGroupFieldName> ::=
additionalgroupkeys|
createtime|
description|
displayname|
dynamicgroupmetadata|
groupkey|
labels|
name|
parent|
updatetime
<CIGroupFieldNameList> ::= "<CIGroupFieldName>(,<CIGroupFieldName>)*"
```
## GUI API Group settings mapping
The entries appear in the order presented on the GUI Group settings page.
| GUI setting | API setting |
|------------|------------|
| Group name | name |
| Group email | email |
| Group description | description |
| Welcome message | Not available |
| Collaborative Inbox | enableCollaborativeInbox |
| Enable shared labels for this group | Not available |
| Who can see group | whoCanDiscoverGroup |
| Who can join group | whoCanJoin |
| Allow external members | allowExternalMembers |
| Who can view conversations | whoCanViewGroup |
| Who can post | whoCanPostMessage |
| Who can view members | whoCanViewMembership |
| Identification required for new members | Not available |
| Who can contact group owners | whoCanContactOwner |
| Who can view member email addresses | Not available |
| Allow Email Posting | Not available |
| Allow web posting | allowWebPosting |
| Conversation history | isArchived |
| Who can reply privately to authors | Not available |
| Who can attach files | Not available |
| Who can moderate content | whoCanModerateContent |
| Who can moderate metadata | whoCanAssistContent |
| Who can post as group | membersCanPostAsTheGroup |
| Default sender | defaultSender |
| Message moderation | messageModerationLevel |
| New member restrictions | Not available |
| Spam message handling | spamModerationLevel |
| Rejected message notification | sendMessageDenyNotification |
| Include default rejected message response | defaultMessageDenyNotificationText |
| Subject prefix | Not available |
| Include the standard Groups footer | Not available |
| Include a custom footer | includeCustomFooter |
| Custom footer text | customFooterText |
| Group email language | primaryLanguage |
| Auto replies | Not available |
| Post replies to | replyTo |
| Custom address for replies | customReplyTo |
| Conversation mode | Not available |
| Who can manage members | whoCanModerateMembers |
| Who can manaage custom roles | Not available |
## GUI API Group access type settings mapping
You can apply these settings when creating/updating a group with the option:
```
accesstype public|team|announcementonly|restricted
```
```
Public
whoCanJoin ALL_IN_DOMAIN_CAN_JOIN
whoCanPostMessage ALL_IN_DOMAIN_CAN_POST
whoCanViewGroup ALL_IN_DOMAIN_CAN_VIEW
whoCanViewMembership ALL_IN_DOMAIN_CAN_VIEW
Team
whoCanJoin CAN_REQUEST_TO_JOIN
whoCanPostMessage ALL_IN_DOMAIN_CAN_POST
whoCanViewGroup ALL_IN_DOMAIN_CAN_VIEW
whoCanViewMembership ALL_IN_DOMAIN_CAN_VIEW
Announcement Only
whoCanJoin ALL_IN_DOMAIN_CAN_JOIN
whoCanPostMessage ALL_MANAGERS_CAN_POST
whoCanViewGroup ALL_IN_DOMAIN_CAN_VIEW
whoCanViewMembership ALL_MANAGERS_CAN_VIEW
Restricted
whoCanJoin CAN_REQUEST_TO_JOIN
whoCanPostMessage ALL_MEMBERS_CAN_POST
whoCanViewGroup ALL_MEMBERS_CAN_VIEW
whoCanViewMembership ALL_MEMBERS_CAN_VIEW
```
## Manage groups
These commands allow you to create, update and delete groups.
```
gam create group <EmailAddress>
[copyfrom <GroupItem>] <GroupAttribute>*
[verifynotinvitable]
gam update group|groups <GroupEntity> [email <EmailAddress>]
[copyfrom <GroupItem>] <GroupAttribute>*
[makesecuritygroup|security]
[admincreated <Boolean>]
[verifynotinvitable]
gam delete group|groups <GroupEntity> [noactionifalias]
```
The `copyfrom <GroupItem>` allows copying of group attributes from one group to another.
The following attributes are not copied: name, description, email, admincreated, aliases, noneditablealiases.
Any `<GroupAttribute>` specified will override the copied attributes.
You can update a group to a security group with the `makesecuritygroup` option.
* Warning: A Security Group cannot be changed back to a Google Group.
When deleting and `noactionifalias` is specified, no action is performed if `<GroupEntity>` specifies an alias rather than a primary email address.
## Update a group's settings with JSON data
You can save group settings in JSON format which can simplify updating multiple settings. Suppose you have
a set of test groups that you will use to experiment with the new group settings coming in May 2019. You
want to backup the current settings so you can restore them later after your experiments.
Backup the current settings.
```
$ gam redirect csv ./groups.csv print groups query "name:test*" settings formatjson quotechar "'"
Getting all Groups that match query (query="name:test*"), may take some time on a large Google Workspace Account...
Got 4 Groups: testgroup1@domain.com - testgroup4@domain.com
Getting Group Settings for testgroup1@domain.com (1/4)
Getting Group Settings for testgroup2@domain.com (2/4)
Getting Group Settings for testgroup3@domain.com (3/4)
Getting Group Settings for testgroup4@domain.com (4/4)
```
Perform your experiments and then restore the original settings.
```
$ gam csv ./groups.csv quotechar "'" gam update group ~email json ~JSON-settings
Using 4 processes...
Group: testgroup1@domain.com, Updated
Group: testgroup2@domain.com, Updated
Group: testgroup3@domain.com, Updated
Group: testgroup4@domain.com, Updated
```
## Display information about specific groups
The info command displays information as an indented list of keys and values.
```
gam info group|groups <GroupEntity>
[nousers] [quick] [noaliases] [groups]
[basic] <GroupFieldName>* [fields <GroupFieldNameList>] [nodeprecated]
[ciallfields|(cifields <CIGroupFieldNameList>)]
[roles <GroupRoleList>] [members] [managers] [owners]
[notsuspended|suspended] [notarchived|archived]
[types <GroupTypeList>]
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
[formatjson]
```
By default, all members, managers and owners in the group are displayed; these options modify that behavior:
* `members` - Display members
* `managers` - Display managers
* `owners` - Display owners
* `nousers` or `quick` - Do not display any members, managers or owners
* `roles <GroupRoleList>` - Display specified roles
By default, when displaying members from a group, all members, whether suspended or not, are included.
* `notsuspended` - Display only non-suspended members
* `suspended` - Display only suspended members
* `notarchived` - Display only non-archived members
* `archived` - Display only archived members
* `notsuspended notarchived` - Display only non-suspended and non-archived members
* `suspended archived` - Display only suspended or archived members
* `notsuspended archived` - Display only archived members
* `suspended notarchived` - Display only suspended members
By default, when displaying members from a group, all types of members (customer, group, user) in the group are displayed; this option modifies that behavior:
* `types <GroupTypeList>` - Display specified types
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
By default, all group aliases are displayed, these options modify that behavior:
* `noaliases` or `quick` - Do not display group aliases
By default, the groups of which this group is a member are not displayed, this option enables that display
* `groups` - Display groups of which this group is a member
These options specify what group fields to display:
* `basic` - These fields `id,name,description,directMembersCount,aliases,nonEditableAliases,adminCreated` are displayed
* `<GroupFieldName>*` - Individual fields to display
* `fields <GroupFieldNameList>` - A comma separated list of fields to display
* `ciallfields` - All Cloud Identity Group fields
* `cifields <CIGroupFieldNameList>` - A comma separated list of Cloud Identity Groups fields to display
* `nodeprecated` - Do not display deprecated fields
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the output in JSON notation
## Display information about selected groups
This command displays information in CSV format.
```
gam print groups [todrive <ToDriveAttribute>*]
[([domain <DomainName>] ([member|showownedby <EmailItem>]|[query <QueryGroup>]))|
(select <GroupEntity>)]
[emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
[descriptionmatchpattern [not] <RegularExpression>] (matchsetting [not] <GroupAttribute>)*
[admincreatedmatch <Boolean>]
[maxresults <Number>]
[allfields|([basic] [settings] <GroupFieldName>* [fields <GroupFieldNameList>])]
[ciallfields|(cifields <CIGroupFieldNameList>)]
[nodeprecated]
[roles <GroupRoleList>]
[members|memberscount] [managers|managerscount] [owners|ownerscount] [totalcount] [countsonly]
[includederivedmembership]
[notsuspended|suspended] [notarchived|archived]
[types <GroupTypeList>]
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
[convertcrnl] [delimiter <Character>] [sortheaders]
[formatjson [quotechar <Character>]]
```
By default, all groups in the account are displayed, these options allow selection of subsets of groups:
* `domain <DomainName>` - Limit display to groups in the domain `<DomainName>`
* `member <EmailItem>` - Limit display to groups that contain `<EmailItem>` as a member; mutually exclusive with `query <QueryGroup>`
* `showownedby <EmailItem>` - Limit display to groups that contain `<EmailItem>` as an owner; mutually exclusive with `query <QueryGroup>`
* `query <QueryGroup>` - Limit display to groups that match <QueryGroup>, matching is done at Google; mutually exclusive with `member <UserItem>`
* `select <GroupEntity>` - Limit display to the groups specified in `<GroupEntity>`
* `showownedby <UserItem>` - Limit display to groups owned by `<UserItem>`
When using `query <QueryGroup>` with the `name:{PREFIX}*` query, `PREFIX` must contain at least three characters.
You can identify groups with the `All users in the organization` member with:
* `query "memberKey=<CustomerID>"` - All versiona
* `member id:<CustomerID>` - Version 6.10.06 or later
These options further limit the list of groups selected above:
* `emailmatchpattern <RegularExpression>` - Limit display to groups whose email address matches `<RegularExpression>`
* `emailmatchpattern not <RegularExpression>` - Limit display to groups whose email address does not match `<RegularExpression>`
* `namematchpattern <RegularExpression>` - Limit display to groups whose name matches `<RegularExpression>`
* `namematchpattern not <RegularExpression>` - Limit display to groups whose name does not match `<RegularExpression>`
* `descriptionmatchpattern <RegularExpression>` - Limit display to groups whose description matches `<RegularExpression>`
* `descriptionmatchpattern not <RegularExpression>` - Limit display to groups whose description does not match `<RegularExpression>`
* `admincreatedmatch True` - Limit display to groups created by administrators
* `admincreatedmatch False` - Limit display to groups created by users
* `matchsetting <GroupAttribute>` - Limit display to groups that have `<GroupAttribute>`
* `matchsetting not <GroupAttribute>` - Limit display to groups that do not have `<GroupAttribute>`
* You can specify multiple `matchsetting` options, all of them must match for the group to be displayed.
* You can specify multiple `matchsetting` options for the same `<GroupAttribute>`, it is a match if the group has any of the `<GroupAttribute>` values.
* You can specify multiple `matchsetting not` options for the same `<GroupAttribute>`, it is a match if the group has none of the `<GroupAttribute>` values.
When retrieving lists of Google Groups from API, how many should be retrieved in each API call.
* `maxresults <Number>` - How many groups to retrieve in each API call; default is 200.
By default, only the group email address is displayed, these options specify what group fields to display:
* `basic` - These fields `id,name,description,directMembersCount,aliases,nonEditableAliases,adminCreated` are displayed
* `allfields` - All group fields are displayed
* `settings` - All group settings fields are displayed
* `<GroupFieldName>*` - Individual fields to display
* `fields <GroupFieldNameList>` - A comma separated list of fields to display
* `ciallfields` - All Cloud Identity Group fields
* `cifields <CIGroupFieldNameList>` - A comma separated list of Cloud Identity Groups fields to display
* `nodeprecated` - Do not display deprecated fields
Some text fields may contain carriage returns or line feeds, displaying fields containing these characters will make processing the CSV file with a script hard; this option converts those characters to a text form.
The default value is `csv_output_convert_cr_nl` from `gam.cfg`
* `convertcrnl` - Convert carriage return to \r and line feed to \n
When lists of items are displayed, the delimiter between items defaults to the `csv_output_column_delimiter` value in gam.cfg; you can specify a different delimiter:
* `delimiter <Character>` - Use `<Character>` as the list item delimiter, `<Character>` must be a single character after processing any escape character
By default, no members, managers or owners in the group are displayed; these options modify that behavior:
* `members` - Display list of members
* `memberscount` - Display count of members but not individual members
* `managers` - Display list of managers
* `managerscount` - Display count of managers but not individual managers
* `owners` - Display list of owners
* `roles <GroupRoleList>` - Display lists of the specified roles
* `ownerscount` - Display count of owners but not individual owners
* `countsonly` - Change any `members`, `managers`, `owners` or `roles` options to `memberscount`, `managerscount` or `ownerscount`
* `totalcount` - Display sum of counts of members, managers, owners.
The `includederivedmembership` option causes the API to expand type GROUP and type CUSTOMER
members to display their constituent members while still displaying the original member.
The API produces inconsistent results, use with caution.
By default, when displaying members from a group, all members, whether suspended or not, are included.
* `notsuspended` - Display only non-suspended members
* `suspended` - Display only suspended members
* `notarchived` - Display only non-archived members
* `archived` - Display only archived members
* `notsuspended notarchived` - Display only non-suspended and non-archived members
* `suspended archived` - Display only suspended or archived members
* `notsuspended archived` - Display only archived members
* `suspended notarchived` - Display only suspended members
By default, when displaying members from a group, all types of members (customer, group, user) in the group are displayed; this option modifies that behavior:
* `types <GroupTypeList>` - Display specified types
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Examples
### Some simple use cases.
#### Output can be either redirected to a file on the command line using ">file.ouput", or the csv redirect gam option
#### Print a list of all your groups
```
gam print groups
```
#### Display groups with no members.
```
gam config csv_output_row_filter "directMembersCount:count=0" print groups directmemberscount
```
## Display a group and its parents
Display a group and its parents as an indented list.
```
gam show grouptree <GroupEntity>
```
Display a group and its parents in CSV format.
```
gam print grouptree <GroupEntity> [todrive <ToDriveAttribute>*]
[showparentsaslist [<Boolean>]] [delimiter <Character>]
```
By default, the group parent emails and names are displayed in multiple indexed columns.
Use options `showparentsaslist [<Boolean>]` and `delimiter <Character>` to display
the group parent emails and names in two columns as delimited lists .
#### Examples
```
$ gam show grouptree testgroup2@domain.com
Show 1 Group Tree
testgroup2@domain.com: Test - Group 2
testgroup1@domain.com: Test Group1
testgroup@domain.com: Test Group Org
testgroup@domain.net: Test Group Net
$ gam print grouptree testgroup2@domain.com
Group,Name,parents,parents.0.email,parents.0.name,parents.1.email,parents.1.name
testgroup2@domain.com,Test - Group 2,2,testgroup1@domain.com,Test Group1,testgroup@domain.com,Test Group Org
testgroup2@domain.com,Test - Group 2,1,testgroup@domain.net,Test Group Net,,
$ gam print grouptree testgroup2@domain.com showparentsaslist delimiter "|"
Group,Name,ParentsCount,Parents,ParentsName
testgroup2@domain.com,Test - Group 2,2,testgroup1@domain.com|testgroup@domain.com,Test Group1|Test Group Org
testgroup2@domain.com,Test - Group 2,1,testgroup@domain.net,Test Group Net
```

33
docs/HTTPS-Proxy.md Normal file
View File

@ -0,0 +1,33 @@
# HTTPS Proxy
GAM should be run on a server with direct access to talk to Google servers via the Internet.
However, if you must push GAM traffic through an HTTPS proxy this can be done by setting the HTTPS_PROXY environment variable.
## Linux and MacOS and Google Cloud Shell
Add the following line (use the actual proxy IP address and port number):
```
export HTTPS_PROXY="http://192.168.1.1:3128"
```
to one of these files based on your shell:
```
~/.bash_profile
~/.bashrc
~/.zshrc
~/.profile
```
## Windows
Set a system environment variable (use the actual proxy IP address and port number):
```
Start Control Panel
Click System
Click Advanced system settings
Click Environment Variables...
Set Variable name: HTTPS_PROXY
Set Variable value: http://192.168.1.1:3128
Click OK
Click OK
Click OK
Exit Control Panel
```

70
docs/Home.md Normal file
View File

@ -0,0 +1,70 @@
- [Introduction](#introduction)
- [Requirements](#requirements)
- [Installation - First time GAM installation](#installation---first-time-GAM-installation)
- [Installation - Upgrading from a GAM version other than a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3](#installation---upgrading-from-a-gam-version-other-than-a-prior-version-of-gamadv-x-or-gamadv-xtd-or-gamadv-xtd3)
- [Installation - Upgrading from a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3](#installation---upgrading-from-a-prior-version-of-gamadv-x-or-gamadv-xtd-or-gamadv-xtd3)
# Introduction
GAMADV-XTD3 is a free, open source command line tool for Google Workspace Administrators to manage domain and user settings quickly and easily.
GAMADV-XTD3 is built with Python 3; as Python 2 support ends on 2020-01-01, this is the version of Advanced GAM that new/existing users should install.
This page provides simple instructions for downloading, installing and starting to use GAMADV-XTD3.
GAMADV-XTD3 requires paid, or Education/Non-profit, editions of Google Workspace. G Suite Legacy Free Edition has limited API support and not all GAM commands work.
GAMADV-XTD3 is a rewrite/extension of Jay Lee's [GAM], without his efforts, this version wouldn't exist.
GAMADV-XTD3 is backwards compatible with [GAM], meaning that if your command works with regular GAM, it will also work with GAMADV-XTD3. There may be differences in output, but the syntax is compatible.
# Documentation
Basic GAM documentation is hosted in the [GitHub Wiki]. Documentation specifically for GAMADV-XTD3 is hosted in the [GitHub GAMADV-XTD3 Wiki] and in Gam*.txt files.
# Mailing List / Discussion group
The GAM mailing list / discussion group is hosted on [Google Groups]. You can join the list and interact via email, or just post from the web itself.
# Source Repository
The official GAMADV-XTD3 source repository is on [GitHub] in the master branch.
# Author
GAMADV-XTD3 is maintained by <a href="mailto:ross.scroggs@gmail.com">Ross Scroggs</a>.
# Requirements
To run all commands properly, GAMADV-XTD3 requires three things:
* An API project which identifies your install of GAMADV-XTD3 to Google and keeps track of API quotas.
* Authorization to act as your Google Workspace Administrator in order to perform management functions like add users, modify group settings and membership and pull domain reports.
* A special service account that is authorized to act on behalf of your users in order to modify user-specific settings and data such as Drive files, Calendars and Gmail messages and settings like signatures.
# Installation - First time GAM installation
Use these steps if you have never used any version of GAM in your domain. They will create a GAM project
and all necessary authentications.
* Download: [Downloads](Downloads)
* Configuration: [GAM Configuration](gam.cfg)
* Install: [How to Install Advanced GAM](How-to-Install-Advanced-GAM)
# Installation - Upgrading from a GAM version other than a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3
Use these steps if you have used any version of GAM in your domain. They will update your GAM project
and all necessary authentications.
* Download: [Downloads](Downloads)
* Configuration: [GAM Configuration](gam.cfg)
* Upgrade: [How to Upgrade from Standard GAM](How-to-Upgrade-from-Standard-GAM)
# Installation - Upgrading from a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3
Use these steps if you already use GAMADV-X or GAMADV-XTD or GAMADV-XTD3. The updates may tell you to update your GAM project
or authentications because new features have been included.
* Updates: [GAM Updates]
* Download: [Downloads](Downloads)
You can install multiple versions of GAM and GAMADV-XTD3 in different parallel directories.
[GAM]: https://github.com/GAM-team/GAM
[GitHub Releases]: https://github.com/taers232c/GAMADV-XTD3/releases
[GitHub]: https://github.com/taers232c/GAMADV-XTD3/tree/master
[GitHub Wiki]: https://github.com/GAM-team/GAM/wiki/
[GitHub GAMADV-XTD3 Wiki]: https://github.com/taers232c/GAMADV-XTD3/wiki/
[Google Groups]: https://groups.google.com/group/google-apps-manager
[GAM Updates]: https://github.com/taers232c/GAMADV-XTD3/wiki/GamUpdates

View File

@ -0,0 +1,887 @@
# Installing GAMADV-XTD3
Use these steps if you have never used any version of GAM in your domain. They will create your GAM project
and all necessary authentications.
- [Downloads](Downloads)
- [GAM Configuration](gam.cfg)
- [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell)
- [Windows](#windows)
## Linux and MacOS and Google Cloud Shell
In these examples, your Google Super admin is shown as admin@domain.com; replace with the
actual email adddress.
In these examples, the user home folder is shown as /Users/admin; adjust according to your
specific situation; e.g., /home/administrator.
This example assumes that GAMADV-XTD3 has been installed in /Users/admin/bin/gamadv-xtd3.
If you've installed GAMADV-XTD3 in another directory, substitute that value in the directions.
### Set a configuration directory
The default GAM configuration directory is /Users/admin/.gam; for more flexibility you
probably want to select a non-hidden location. This example assumes that the GAM
configuration directory will be /Users/admin/GAMConfig; If you've chosen another directory,
substitute that value in the directions.
Add the following line:
```
export GAMCFGDIR="/Users/admin/GAMConfig"
```
to one of these files based on your shell:
```
~/.bash_profile
~/.bashrc
~/.zshrc
~/.profile
```
You need to enable this setting in the environment. The easiest way is probably to close your terminal and open a new session. This will load the environment variables, including the one you just added. Test this by issuing this command:
```
echo $GAMCFGDIR
```
This should print the name of the directory you used above.
Alternatively, without starting a new session, load the new variable in this session directly: issue the following command replacing `<Filename>` with the name of the file you edited:
```
source <Filename>
```
You need to make sure the GAM configuration directory actually exists. Test that like this:
```
ls -l $GAMCFGDIR
```
If this gives you an error, make the directory:
```
mkdir -p $GAMCFGDIR
```
### Set a working directory
You should establish a GAM working directory; you will store your GAM related
data in this folder and execute GAM commands from this folder. You should not use
/Users/admin/bin/gamadv-xtd3 or /Users/admin/GAMConfig for this purpose.
This example assumes that the GAM working directory will be /Users/admin/GAMWork; If you've chosen
another directory, substitute that value in the directions.
* Make the /Users/admin/GAMWork directory before proceeding.
### Set an alias
You should set an alias to point to /Users/admin/bin/gamadv-xtd3/gam so you can operate from the /Users/admin/GAMWork directory.
Aliases aren't available in scripts, so you may want to set a symlink instead, see below.
Add the following line:
```
alias gam="/Users/admin/bin/gamadv-xtd3/gam"
```
to one of these files based on your shell:
```
~/.bash_aliases
~/.bash_profile
~/.bashrc
~/.zshrc
~/.profile
```
Issue the following command replacing `<Filename>` with the name of the file you edited:
```
source <Filename>
```
### Set a symlink
Set a symlink in `/usr/local/bin` (or some other location on $PATH) to point to GAM.
```
ln -s "/Users/admin/bin/gamadv-xtd3/gam" /usr/local/bin/gam
```
### Initialize GAMADV-XTD3; this should be the first GAMADV-XTD3 command executed.
```
admin@server:~$ cd /Users/admin/bin/gamadv-xtd3
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam config drive_dir /Users/admin/GAMWork verify
Created: /Users/admin/GAMConfig
Created: /Users/admin/GAMConfig/gamcache
Config File: /Users/admin/GAMConfig/gam.cfg, Initialized
Section: DEFAULT
activity_max_results = 100
...
[long list of all config settings that should match the directories you specified]
...
admin@server:/Users/admin/bin/gamadv-xtd3$
```
### Verify initialization, this was a successful installation.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ls -l $GAMCFGDIR
total 48
-rw-r-----+ 1 admin staff 1069 Mar 3 09:23 gam.cfg
drwxr-x---+ 2 admin staff 68 Mar 3 09:23 gamcache
-rw-rw-rw-+ 1 admin staff 0 Mar 3 09:23 oauth2.txt.lock
admin@server:/Users/admin/bin/gamadv-xtd3$
```
### Create your project with local browser
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam create project
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: client_secrets_json, Value: /Users/admin/GAMConfig/client_secrets.json, Not Found
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: oauth2service_json, Value: /Users/admin/GAMConfig/oauth2service.json, Not Found
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) admin@domain.com
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/v2/auth?client_id=CLI...response_type=code
If your browser is on a different machine then press CTRL+C,
set no_browser = true in gam.cfg and re-run this command.
Authentication successful.
Creating project "GAM Project"...
Checking project status...
Project: gam-project-abc-def-ghi, Enable 23 APIs
API: admin.googleapis.com, Enabled (1/23)
API: alertcenter.googleapis.com, Enabled (2/23)
API: appsactivity.googleapis.com, Enabled (3/23)
API: audit.googleapis.com, Enabled (4/23)
API: calendar-json.googleapis.com, Enabled (5/23)
API: chat.googleapis.com, Enabled (6/23)
API: classroom.googleapis.com, Enabled (7/23)
API: contacts.googleapis.com, Enabled (8/23)
API: drive.googleapis.com, Enabled (9/23)
API: driveactivity.googleapis.com, Enabled (10/23)
API: gmail.googleapis.com, Enabled (11/23)
API: groupsmigration.googleapis.com, Enabled (12/23)
API: groupssettings.googleapis.com, Enabled (13/23)
API: iam.googleapis.com, Enabled (14/23)
API: iap.googleapis.com, Enabled (15/23)
API: licensing.googleapis.com, Enabled (16/23)
API: people.googleapis.com, Enabled (17/23)
API: pubsub.googleapis.com, Enabled (18/23)
API: reseller.googleapis.com, Enabled (19/23)
API: sheets.googleapis.com, Enabled (20/23)
API: siteverification.googleapis.com, Enabled (21/23)
API: storage-api.googleapis.com, Enabled (22/23)
API: vault.googleapis.com, Enabled (23/23)
Setting GAM project consent screen...
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Enabled
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Generating new private key
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Extracting public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Done generating private key and public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Service Account Key: SVCACCTKEY, Uploaded
Service Account OAuth2 File: /Users/admin/GAMConfig/oauth2service.json, Service Account Key: SVCACCTKEY, Updated
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Has rights to rotate own private key
Please go to:
https://console.cloud.google.com/apis/credentials/oauthclient?project=gam-project-abc-def-ghi
1. Choose "Desktop App" or "Other" for "Application type".
2. Enter "GAM" or another desired value for "Name".
3. Click the blue "Create" button.
4. Copy your "client ID" value that shows on the next page.
Enter your Client ID: CLIENTID
5. Go back to your browser and copy your "client secret" value.
Enter your Client Secret: CLIENTSECRET
6. Go back to your browser and click OK to close the "OAuth client" popup if it's still open.
That's it! Your GAM Project is created and ready to use.
admin@server:/Users/admin/bin/gamadv-xtd3$
```
### Create your project without local browser (Google Cloud Shell for instance)
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam config no_browser true save
admin@server:/Users/admin/bin/gamadv-xtd3$ gam create project
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: client_secrets_json, Value: /Users/admin/GAMConfig/client_secrets.json, Not Found
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Item: oauth2service_json, Value: /Users/admin/GAMConfig/oauth2service.json, Not Found
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) admin@domain.com
Go to the following link in a browser on other computer:
https://accounts.google.com/o/oauth2/v2/auth?re... m&prompt=consent
Enter verification code: abc...xyz
Authentication successful.
Creating project "GAM Project"...
Checking project status...
Project: gam-project-abc-def-ghi, Enable 23 APIs
API: admin.googleapis.com, Enabled (1/23)
API: alertcenter.googleapis.com, Enabled (2/23)
API: appsactivity.googleapis.com, Enabled (3/23)
API: audit.googleapis.com, Enabled (4/23)
API: calendar-json.googleapis.com, Enabled (5/23)
API: chat.googleapis.com, Enabled (6/23)
API: classroom.googleapis.com, Enabled (7/23)
API: contacts.googleapis.com, Enabled (8/23)
API: drive.googleapis.com, Enabled (9/23)
API: driveactivity.googleapis.com, Enabled (10/23)
API: gmail.googleapis.com, Enabled (11/23)
API: groupsmigration.googleapis.com, Enabled (12/23)
API: groupssettings.googleapis.com, Enabled (13/23)
API: iam.googleapis.com, Enabled (14/23)
API: iap.googleapis.com, Enabled (15/23)
API: licensing.googleapis.com, Enabled (16/23)
API: people.googleapis.com, Enabled (17/23)
API: pubsub.googleapis.com, Enabled (18/23)
API: reseller.googleapis.com, Enabled (19/23)
API: sheets.googleapis.com, Enabled (20/23)
API: siteverification.googleapis.com, Enabled (21/23)
API: storage-api.googleapis.com, Enabled (22/23)
API: vault.googleapis.com, Enabled (23/23)
Setting GAM project consent screen...
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Enabled
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Generating new private key
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Extracting public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Done generating private key and public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Service Account Key: SVCACCTKEY, Uploaded
Service Account OAuth2 File: /Users/admin/GAMConfig/oauth2service.json, Service Account Key: SVCACCTKEY, Updated
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Has rights to rotate own private key
Please go to:
https://console.cloud.google.com/apis/credentials/oauthclient?project=gam-project-abc-def-ghi
1. Choose "Desktop App" or "Other" for "Application type".
2. Enter "GAM" or another desired value for "Name".
3. Click the blue "Create" button.
4. Copy your "client ID" value that shows on the next page.
Enter your Client ID: CLIENTID
5. Go back to your browser and copy your "client secret" value.
Enter your Client Secret: CLIENTSECRET
6. Go back to your browser and click OK to close the "OAuth client" popup if it's still open.
That's it! Your GAM Project is created and ready to use.
admin@server:/Users/admin/bin/gamadv-xtd3$
```
### Enable GAMADV-XTD3 client access
You select a list of scopes, GAM uses a browser to get final authorization from Google for these scopes and
writes the credentials into the file oauth2.txt.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam oauth create
Select the authorized scopes by entering a number.
Append an 'r' to grant read-only access or an 'a' to grant action-only access.
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
[*] 2) Chrome Management API - Telemetry read only
[*] 3) Chrome Management API - read only
[*] 4) Chrome Policy API (supports readonly)
[*] 5) Chrome Printer Management API (supports readonly)
[*] 6) Chrome Version History API
[*] 7) Classroom API - Course Announcements (supports readonly)
[*] 8) Classroom API - Course Topics (supports readonly)
[*] 9) Classroom API - Course Work/Materials (supports readonly)
[*] 10) Classroom API - Course Work/Submissions (supports readonly)
[*] 11) Classroom API - Courses (supports readonly)
[*] 12) Classroom API - Profile Emails
[*] 13) Classroom API - Profile Photos
[*] 14) Classroom API - Rosters (supports readonly)
[*] 15) Classroom API - Student Guardians (supports readonly)
[*] 16) Cloud Identity Groups API (supports readonly)
[*] 17) Cloud Storage (Vault Export - read only)
[*] 18) Contact Delegation API (supports readonly)
[*] 19) Contacts API - Domain Shared and Users and GAL
[*] 20) Data Transfer API (supports readonly)
[*] 21) Directory API - Chrome OS Devices (supports readonly)
[*] 22) Directory API - Customers (supports readonly)
[*] 23) Directory API - Domains (supports readonly)
[*] 24) Directory API - Groups (supports readonly)
[*] 25) Directory API - Mobile Devices Directory (supports readonly and action)
[*] 26) Directory API - Organizational Units (supports readonly)
[*] 27) Directory API - Resource Calendars (supports readonly)
[*] 28) Directory API - Roles (supports readonly)
[*] 29) Directory API - User Schemas (supports readonly)
[*] 30) Directory API - User Security
[*] 31) Directory API - Users (supports readonly)
[*] 32) Email Audit API
[*] 33) Groups Migration API
[*] 34) Groups Settings API
[*] 35) License Manager API
[*] 36) People API (supports readonly)
[*] 37) People Directory API - read only
[ ] 38) Pub / Sub API
[*] 39) Reports API - Audit Reports
[*] 40) Reports API - Usage Reports
[ ] 41) Reseller API
[*] 42) Site Verification API
[*] 43) Sites API
[*] 44) Vault API (supports readonly)
s) Select all scopes
u) Unselect all scopes
e) Exit without changes
c) Continue to authorization
Please enter 0-44[a|r] or s|u|e|c: c
Enter your Google Workspace admin email address? admin@domain.com
Go to the following link in a browser on this computer or on another computer:
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=423565144751-10lsdt2lgnsch9jmdhl35uq4617u1ifp&redirect_uri=http%3A%2F%2F127.0.0.1%3A8080%2F&scope=...
If you use a browser on another computer, you will get a browser error that the site can't be reached AFTER you
click the Allow button, paste "Unable to connect" URL from other computer (only URL data up to &scope required):
Enter verification code or paste "Unable to connect" URL from other computer (only URL data up to &scope required):
The authentication flow has completed.
Client OAuth2 File: /Users/admin/GAMConfig/oauth2.txt, Created
admin@server:/Users/admin/bin/gamadv-xtd3$
```
If clicking on the link in the instructions does not work (i.e. you get a 404 or 400 error message, instead of something about 'unable to connect') the URL in the link is too long. Most likely, you have selected all scopes. Try again with fewer scopes until it works. (there is no harm in repeatedly trying)
### Enable GAMADV-XTD3 service account access.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user admin@domain.com check serviceaccount
$ gam user admin@domain.com check serviceaccount
System time status
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 0 days PASS
Domain-Wide Delegation authentication:, User: admin@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels FAIL (20/28)
https://www.googleapis.com/auth/drive.labels FAIL (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
Some scopes FAILED!
To authorize them, please go to:
https://admin.google.com/ac/owl/domainwidedelegation?clientScopeToAdd=https://mail.go...huser=admin@domain.com
You will be directed to the Google Workspace admin console Security/API Controls/Domain-wide Delegation page
The "Add a new Client ID" box will open
Make sure that "Overwrite existing client ID" is checked
Click AUTHORIZE
When the box closes you're done
After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
admin@server:/Users/admin/bin/gamadv-xtd3$
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
### Verify GAMADV-XTD3 service account access.
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user admin@domain.com check serviceaccount
System time status:
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication:
Authentication PASS
Domain-Wide Delegation authentication:, User: admin@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels PASS (20/28)
https://www.googleapis.com/auth/drive.labels PASS (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
admin@server:/Users/admin/bin/gamadv-xtd3$
```
### Update gam.cfg with some basic values
* `customer_id` - Having this data keeps Gam from having to make extra API calls
* `domain` - This allows you to omit the domain portion of email addresses
* `timezone local` - Gam will convert all UTC times to your local timezone
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam info domain
Customer ID: C01234567
Primary Domain: domain.com
Customer Creation Time: 2007-06-06T15:47:55.444Z
Primary Domain Verified: True
Default Language: en
...
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam config customer_id C01234567 domain domain.com timezone local save verify
Config File: /Users/admin/GAMConfig/gam.cfg, Saved
Section: DEFAULT
activity_max_results = 100
...
[long list of all config settings that should match the data you specified]
...
admin@server:/Users/admin/bin/gamadv-xtd3$
```
## Windows
In these examples, your Google Super admin is shown as admin@domain.com; replace with the
actual email adddress.
This example assumes that GAMADV-XTD3 has been installed in C:\GAMADV-XTD3; if you've installed
GAMADV-XTD3 in another directory, substitute that value in the directions.
These steps assume Command Prompt, adjust if you're using PowerShell.
### Set a configuration directory
The default GAM configuration directory is C:\Users\<UserName>\.gam; for more flexibility you
probably want to select a non user-specific location. This example assumes that the GAM
configuration directory will be C:\GAMConfig; If you've chosen another directory,
substitute that value in the directions.
* Make the C:\GAMConfig directory before proceeding.
### Set a working directory
You should extablish a GAM working directory; you will store your GAM related
data in this folder and execute GAM commands from this folder. You should not use
C:\GAMADV-XTD3 or C:\GAMConfig for this purpose.
This example assumes that the GAM working directory will be C:\GAMWork; If you've chosen
another directory, substitute that value in the directions.
* Make the C:\GAMWork directory before proceeding.
### Set system path and GAM configuration directory
You should set the system path to point to C:\GAMADV-XTD3 so you can operate from the C:\GAMWork directory.
```
Start Control Panel
Click System
Click Advanced system settings
Click Environment Variables...
Click Path under System variables
Click Edit...
If C:\GAMADV-XTD3 is already on the Path, skip the next three steps
Click New
Enter C:\GAMADV-XTD3
Click OK
Click New
Set Variable name: GAMCFGDIR
Set Variable value: C:\GAMConfig
Click OK
Click OK
Click OK
Exit Control Panel
```
At this point, you should restart Command Prompt so that it has the updated path and environment variables.
### Initialize GAMADV-XTD3; this should be the first GAMADV-XTD3 command executed.
```
C:>cd C:\GAMADV-XTD3
C:\GAMADV-XTD3>gam config drive_dir C:\GAMWork verify
Created: C:\GAMConfig
Created: C:\GAMConfig\gamcache
Config File: C:\GAMConfig\gam.cfg, Initialized
Section: DEFAULT
activity_max_results = 100
...
[long list of all config settings that should match the directories you specified]
...
C:\GAMADV-XTD3>
```
### Verify initialization, this was a successful installation.
```
C:\GAMADV-XTD3>dir %GAMCFGDIR%
Volume in drive C has no label.
Volume Serial Number is 663F-DA8B
Directory of C:\GAMConfig
03/03/2017 10:16 AM <DIR> .
03/03/2017 10:16 AM <DIR> ..
03/03/2017 10:15 AM 1,125 gam.cfg
03/03/2017 10:15 AM <DIR> gamcache
03/03/2017 10:15 AM 0 oauth2.txt.lock
2 File(s) 15,769 bytes
3 Dir(s) 110,532,562,944 bytes free
C:\GAMADV-XTD3>
```
### Create your project with local browser
```
C:\GAMADV-XTD3>gam create project
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: client_secrets_json, Value: C:\GAMConfig\client_secrets.json, Not Found
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: oauth2service_json, Value: C:\GAMConfig\oauth2service.json, Not Found
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) admin@domain.com
Your browser has been opened to visit:
https://accounts.google.com/o/oaut...pe=code
If your browser is on a different machine then press CTRL+C,
set no_browser = true in gam.cfg and re-run this command.
Authentication successful.
Creating project "GAM Project"...
Checking project status...
Project: gam-project-abc-def-ghi, Enable 23 APIs
API: admin.googleapis.com, Enabled (1/23)
API: alertcenter.googleapis.com, Enabled (2/23)
API: appsactivity.googleapis.com, Enabled (3/23)
API: audit.googleapis.com, Enabled (4/23)
API: calendar-json.googleapis.com, Enabled (5/23)
API: chat.googleapis.com, Enabled (6/23)
API: classroom.googleapis.com, Enabled (7/23)
API: contacts.googleapis.com, Enabled (8/23)
API: drive.googleapis.com, Enabled (9/23)
API: driveactivity.googleapis.com, Enabled (10/23)
API: gmail.googleapis.com, Enabled (11/23)
API: groupsmigration.googleapis.com, Enabled (12/23)
API: groupssettings.googleapis.com, Enabled (13/23)
API: iam.googleapis.com, Enabled (14/23)
API: iap.googleapis.com, Enabled (15/23)
API: licensing.googleapis.com, Enabled (16/23)
API: people.googleapis.com, Enabled (17/23)
API: pubsub.googleapis.com, Enabled (18/23)
API: reseller.googleapis.com, Enabled (19/23)
API: sheets.googleapis.com, Enabled (20/23)
API: siteverification.googleapis.com, Enabled (21/23)
API: storage-api.googleapis.com, Enabled (22/23)
API: vault.googleapis.com, Enabled (23/23)
Setting GAM project consent screen...
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Enabled
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Generating new private key
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Extracting public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Done generating private key and public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Service Account Key: SVCACCTKEY, Uploaded
Service Account OAuth2 File: C:\GAMConfig\oauth2service.json, Service Account Key: SVCACCTKEY, Updated
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Has rights to rotate own private key
Please go to:
https://console.cloud.google.com/apis/credentials/oauthclient?project=gam-project-abc-def-ghi
1. Choose "Desktop App" or "Other" for "Application type".
2. Enter "GAM" or another desired value for "Name".
3. Click the blue "Create" button.
4. Copy your "client ID" value that shows on the next page.
Enter your Client ID: CLIENTID
5. Go back to your browser and copy your "client secret" value.
Enter your Client Secret: CLIENTSECRET
6. Go back to your browser and click OK to close the "OAuth client" popup if it's still open.
That's it! Your GAM Project is created and ready to use.
C:\GAMADV-XTD3>
```
### Create your project without local browser (headless server for instance)
```
C:\GAMADV-XTD3>gam config no_browser true save
C:\GAMADV-XTD3>gam create project
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: client_secrets_json, Value: C:\GAMConfig\client_secrets.json, Not Found
WARNING: Config File: C:\GAMConfig\gam.cfg, Item: oauth2service_json, Value: C:\GAMConfig\oauth2service.json, Not Found
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) admin@domain.com
Go to the following link in a browser on other computer:
https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=...
Enter verification code: abc...xyz
Authentication successful.
Creating project "GAM Project"...
Checking project status...
Project: gam-project-abc-def-ghi, Enable 23 APIs
API: admin.googleapis.com, Enabled (1/23)
API: alertcenter.googleapis.com, Enabled (2/23)
API: appsactivity.googleapis.com, Enabled (3/23)
API: audit.googleapis.com, Enabled (4/23)
API: calendar-json.googleapis.com, Enabled (5/23)
API: chat.googleapis.com, Enabled (6/23)
API: classroom.googleapis.com, Enabled (7/23)
API: contacts.googleapis.com, Enabled (8/23)
API: drive.googleapis.com, Enabled (9/23)
API: driveactivity.googleapis.com, Enabled (10/23)
API: gmail.googleapis.com, Enabled (11/23)
API: groupsmigration.googleapis.com, Enabled (12/23)
API: groupssettings.googleapis.com, Enabled (13/23)
API: iam.googleapis.com, Enabled (14/23)
API: iap.googleapis.com, Enabled (15/23)
API: licensing.googleapis.com, Enabled (16/23)
API: people.googleapis.com, Enabled (17/23)
API: pubsub.googleapis.com, Enabled (18/23)
API: reseller.googleapis.com, Enabled (19/23)
API: sheets.googleapis.com, Enabled (20/23)
API: siteverification.googleapis.com, Enabled (21/23)
API: storage-api.googleapis.com, Enabled (22/23)
API: vault.googleapis.com, Enabled (23/23)
Setting GAM project consent screen...
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Enabled
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Generating new private key
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Extracting public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Done generating private key and public certificate
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Service Account Key: SVCACCTKEY, Uploaded
Service Account OAuth2 File: C:\GAMConfig\oauth2service.json, Service Account Key: SVCACCTKEY, Updated
Project: gam-project-abc-def-ghi, Service Account: gam-project-abc-def-ghi@gam-project-abc-def-ghi.iam.gserviceaccount.com, Has rights to rotate own private key
Please go to:
https://console.cloud.google.com/apis/credentials/oauthclient?project=gam-project-abc-def-ghi
1. Choose "Desktop App" or "Other" for "Application type".
2. Enter "GAM" or another desired value for "Name".
3. Click the blue "Create" button.
4. Copy your "client ID" value that shows on the next page.
Enter your Client ID: CLIENTID
5. Go back to your browser and copy your "client secret" value.
Enter your Client Secret: CLIENTSECRET
6. Go back to your browser and click OK to close the "OAuth client" popup if it's still open.
That's it! Your GAM Project is created and ready to use.
C:\GAMADV-XTD3>
```
### Enable GAMADV-XTD3 client access
You select a list of scopes, GAM uses a browser to get final authorization from Google for these scopes and
writes the credentials into the file oauth2.txt.
```
C:\GAMADV-XTD3>gam oauth create
Select the authorized scopes by entering a number.
Append an 'r' to grant read-only access or an 'a' to grant action-only access.
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
[*] 2) Chrome Management API - Telemetry read only
[*] 3) Chrome Management API - read only
[*] 4) Chrome Policy API (supports readonly)
[*] 5) Chrome Printer Management API (supports readonly)
[*] 6) Chrome Version History API
[*] 7) Classroom API - Course Announcements (supports readonly)
[*] 8) Classroom API - Course Topics (supports readonly)
[*] 9) Classroom API - Course Work/Materials (supports readonly)
[*] 10) Classroom API - Course Work/Submissions (supports readonly)
[*] 11) Classroom API - Courses (supports readonly)
[*] 12) Classroom API - Profile Emails
[*] 13) Classroom API - Profile Photos
[*] 14) Classroom API - Rosters (supports readonly)
[*] 15) Classroom API - Student Guardians (supports readonly)
[*] 16) Cloud Identity Groups API (supports readonly)
[*] 17) Cloud Storage (Vault Export - read only)
[*] 18) Contact Delegation API (supports readonly)
[*] 19) Contacts API - Domain Shared and Users and GAL
[*] 20) Data Transfer API (supports readonly)
[*] 21) Directory API - Chrome OS Devices (supports readonly)
[*] 22) Directory API - Customers (supports readonly)
[*] 23) Directory API - Domains (supports readonly)
[*] 24) Directory API - Groups (supports readonly)
[*] 25) Directory API - Mobile Devices Directory (supports readonly and action)
[*] 26) Directory API - Organizational Units (supports readonly)
[*] 27) Directory API - Resource Calendars (supports readonly)
[*] 28) Directory API - Roles (supports readonly)
[*] 29) Directory API - User Schemas (supports readonly)
[*] 30) Directory API - User Security
[*] 31) Directory API - Users (supports readonly)
[*] 32) Email Audit API
[*] 33) Groups Migration API
[*] 34) Groups Settings API
[*] 35) License Manager API
[*] 36) People API (supports readonly)
[*] 37) People Directory API - read only
[ ] 38) Pub / Sub API
[*] 39) Reports API - Audit Reports
[*] 40) Reports API - Usage Reports
[ ] 41) Reseller API
[*] 42) Site Verification API
[*] 43) Sites API
[*] 44) Vault API (supports readonly)
s) Select all scopes
u) Unselect all scopes
e) Exit without changes
c) Continue to authorization
Please enter 0-44[a|r] or s|u|e|c: c
Enter your Google Workspace admin email address? admin@domain.com
Go to the following link in a browser on this computer or on another computer:
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=423565144751-10lsdt2lgnsch9jmdhl35uq4617u1ifp&redirect_uri=http%3A%2F%2F127.0.0.1%3A8080%2F&scope=...
If you use a browser on another computer, you will get a browser error that the site can't be reached AFTER you
click the Allow button, paste "Unable to connect" URL from other computer (only URL data up to &scope required):
Enter verification code or paste "Unable to connect" URL from other computer (only URL data up to &scope required):
The authentication flow has completed.
Client OAuth2 File: C:\GAMConfig\oauth2.txt, Created
C:\GAMADV-XTD3>
```
### Enable GAMADV-XTD3 service account access.
```
C:\GAMADV-XTD3>gam user admin@domain.com check serviceaccount
System time status
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 0 days PASS
Domain-Wide Delegation authentication:, User: admin@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels FAIL (20/28)
https://www.googleapis.com/auth/drive.labels FAIL (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
Some scopes FAILED!
To authorize them, please go to:
https://admin.google.com/ac/owl/domainwide...thuser=admin@domain.com
You will be directed to the Google Workspace admin console Security/API Controls/Domain-wide Delegation page
The "Add a new Client ID" box will open
Make sure that "Overwrite existing client ID" is checked
Click AUTHORIZE
When the box closes you're done
After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
C:\GAMADV-XTD3>
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
### Verify GAMADV-XTD3 service account access.
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
C:\GAMADV-XTD3>gam user admin@domain.com check serviceaccount
System time status:
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication:
Authentication PASS
Domain-Wide Delegation authentication:, User: admin@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels PASS (20/28)
https://www.googleapis.com/auth/drive.labels PASS (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
C:\GAMADV-XTD3>
```
### Update gam.cfg with some basic values
* `customer_id` - Having this data keeps Gam from having to make extra API calls
* `domain` - This allows you to omit the domain portion of email addresses
* `timezone local` - Gam will convert all UTC times to your local timezone
```
C:\GAMADV-XTD3>gam info domain
Customer ID: C01234567
Primary Domain: domain.com
Customer Creation Time: 2007-06-06T15:47:55.444Z
Primary Domain Verified: True
Default Language: en
...
C:\GAMADV-XTD3>gam config customer_id C01234567 domain domain.com timezone local save verify
Config File: C:\GAMConfig\gam.cfg, Saved
Section: DEFAULT
activity_max_results = 100
...
[long list of all config settings that should match the directories you specified]
...
C:\GAMADV-XTD3>
```

View File

@ -0,0 +1,127 @@
# Uninstalling GAMADV-XTD3
- [Get Project Info](#get-project-info)
- [Remove Client API access](#remove-client-api-access)
- [Remove Service Account API access](#remove-service-account-api-access)
- [Delete GAM Project](#delete-gam-project)
- [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell)
- [Windows](#windows)
## Get Project Info
```
gam version
```
Note the `Config File:` path to `gam.cfg`. In that folder will be a file `oauth2service.json`; look at its contents.
You want these two lines:
```
"client_id": "123691089974044844789"
"project_id": "gam-project-123-456-789"
```
## Remove Client API access
```
gam oauth delete
```
## Remove Service Account API access
In a browser, go to `https://admin.google.com`, login and go to the Security/API Controls/Domain-wide Delegation page.
Find the `Client ID` that matches the `client_id` value from `oauth2service.json`, hover over it and click `Delete`.
## Delete GAM Project
In a browser, go to `https://console.cloud.google.com/cloud-resource-manager`, login. Find the `ID` that matches
the `project_id` value from `oauth2service.json`; click the three dots at the right end of the line and click `Delete`.
In the box that pops up, put the `project_id` value in ther `Project ID*` field and click `SHUT DOWN`
## Linux and MacOS and Google Cloud Shell
In these examples, the user home folder is shown as /Users/admin; adjust according to your
specific situation; e.g., /home/administrator.
This example assumes that GAMADV-XTD3 has been installed in /Users/admin/bin/gamadv-xtd3.
If you've installed GAMADV-XTD3 in another directory, substitute that value in the directions.
### Delete executable directory
```
rm -fr /Users/admin/bin/gamadv-xtd3
```
### Delete configuration directory
The default GAM configuration directory is /Users/admin/.gam; for more flexibility you
probably want to select a non-hidden location. This example assumes that the GAM
configuration directory will be /Users/admin/GAMConfig; If you've chosen another directory,
substitute that value in the directions.
```
rm -fr /Users/admin/GAMConfig
```
### Delete working directory
This example assumes that the GAM working directory is be /Users/admin/GAMWork; If you've chosen
another directory, substitute that value in the directions.
```
rm -fr /Users/admin/GAMConfig
```
### Remove executable alias and GAM configuration export
Remove the following line:
```
alias gam="/Users/admin/bin/gamadv-xtd3/gam"
export GAMCFGDIR="/Users/admin/GAMConfig"
```
from these files based on your shell:
```
~/.bash_profile
~/.bashrc
~/.zshrc
~/.profile
```
## Windows
This example assumes that GAMADV-XTD3 has been installed in C:\GAMADV-XTD3; if you've installed
GAMADV-XTD3 in another directory, substitute that value in the directions.
### Delete executable directory
In File Explorer, delete the `C:\GAMADV-XTD3` folder.
### Delete configuration directory
The default GAM configuration directory is C:\Users\<UserName>\.gam; for more flexibility you
probably want to select a non user-specific location. This example assumes that the GAM
configuration directory will be C:\GAMConfig; If you've chosen another directory,
substitute that value in the directions.
In File Explorer, delete the `C:\GAMConfig` folder.
### Delete working directory
This example assumes that the GAM working directory will be C:\GAMWork; If you've chosen
another directory, substitute that value in the directions.
In File Explorer, delete the `C:\GAMWork` folder.
### Reset system path and GAM configuration directory
```
Start Control Panel
Click System
Click Advanced system settings
Click Environment Variables...
Click Path under System variables
Click Edit...
If C:\GAMADV-XTD3 is not on the Path, click Cancel and skip the next three steps
Click C:\GAMADV-XTD3
Click Delete
Click OK
If GAMCFGDIR is not in System variables, skip the next two steps
Click GAMCFGDIR
Click Delete
Click OK
Click OK
Exit Control Panel
```

View File

@ -0,0 +1,537 @@
# Updating GAMADV-XTD3
Use these steps to update your version of GAMADV-XTD3.
- [Downloads](Downloads)
- [GAM Configuration](gam.cfg)
- [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell)
- [Windows](#windows)
## Linux and MacOS and Google Cloud Shell
### Download the latest version
This example assumes that GAMADV-XTD3 has been installed in /Users/admin/bin/gamadv-xtd3.
If you've installed GAMADV-XTD3 in another directory, substitute that value in the directions when downloading.
See: [Downloads](Downloads)
In these examples, your Google Super admin is shown as admin@domain.com; replace with the
actual email adddress.
In these examples, the user home folder is shown as /Users/admin; adjust according to your
specific situation; e.g., /home/administrator.
### Update your project with local browser to include the additional APIs that GAMADV-XTD3 uses.
This step may be omitted if you are updating from a recent version.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s): gam-project-abc-123-xyz? admin@domain.com
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=...
If your browser is on a different machine then press CTRL+C,
set no_browser = true in gam.cfg and re-run this command.
Authentication successful.
API: admin.googleapis.com, already enabled...
API: appsactivity.googleapis.com, already enabled...
API: calendar-json.googleapis.com, already enabled...
API: classroom.googleapis.com, already enabled...
API: contacts.googleapis.com, already enabled...
API: drive.googleapis.com, already enabled...
API: gmail.googleapis.com, already enabled...
API: groupssettings.googleapis.com, already enabled...
API: licensing.googleapis.com, already enabled...
API: plus.googleapis.com, already enabled...
API: reseller.googleapis.com, already enabled...
API: siteverification.googleapis.com, already enabled...
API: vault.googleapis.com, already enabled...
Enable 3 APIs
API: audit.googleapis.com, Enabled (1/3)
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
admin@server:/Users/admin/bin/gamadv-xtd3$
```
### Update your project without local browser (Google Cloud Shell for instance) to include the additional APIs that GAMADV-XTD3 uses
This step may be omitted if you are updating from a recent version.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam config no_browser true save
admin@server:/Users/admin/bin/gamadv-xtd3$ gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s): gam-project-abc-123-xyz? admin@domain.com
Go to the following link in a browser on other computer:
https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=...
Enter verification code: abc...xyz
Authentication successful.
API: admin.googleapis.com, already enabled...
API: appsactivity.googleapis.com, already enabled...
API: calendar-json.googleapis.com, already enabled...
API: classroom.googleapis.com, already enabled...
API: contacts.googleapis.com, already enabled...
API: drive.googleapis.com, already enabled...
API: gmail.googleapis.com, already enabled...
API: groupssettings.googleapis.com, already enabled...
API: licensing.googleapis.com, already enabled...
API: plus.googleapis.com, already enabled...
API: reseller.googleapis.com, already enabled...
API: siteverification.googleapis.com, already enabled...
API: vault.googleapis.com, already enabled...
Enable 3 APIs
API: audit.googleapis.com, Enabled (1/3)
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
admin@server:/Users/admin/bin/gamadv-xtd3$
```
### Update GAMADV-XTD3 client access
You select a list of scopes, GAMADV-XTD3 uses a browser to get final authorization from Google for these scopes and
writes the credentials into the file oauth2.txt.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam oauth create
Select the authorized scopes by entering a number.
Append an 'r' to grant read-only access or an 'a' to grant action-only access.
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
[*] 2) Chrome Management API - Telemetry read only
[*] 3) Chrome Management API - read only
[*] 4) Chrome Policy API (supports readonly)
[*] 5) Chrome Printer Management API (supports readonly)
[*] 6) Chrome Version History API
[*] 7) Classroom API - Course Announcements (supports readonly)
[*] 8) Classroom API - Course Topics (supports readonly)
[*] 9) Classroom API - Course Work/Materials (supports readonly)
[*] 10) Classroom API - Course Work/Submissions (supports readonly)
[*] 11) Classroom API - Courses (supports readonly)
[*] 12) Classroom API - Profile Emails
[*] 13) Classroom API - Profile Photos
[*] 14) Classroom API - Rosters (supports readonly)
[*] 15) Classroom API - Student Guardians (supports readonly)
[*] 16) Cloud Identity Groups API (supports readonly)
[*] 17) Cloud Storage (Vault Export - read only)
[*] 18) Contact Delegation API (supports readonly)
[*] 19) Contacts API - Domain Shared and Users and GAL
[*] 20) Data Transfer API (supports readonly)
[*] 21) Directory API - Chrome OS Devices (supports readonly)
[*] 22) Directory API - Customers (supports readonly)
[*] 23) Directory API - Domains (supports readonly)
[*] 24) Directory API - Groups (supports readonly)
[*] 25) Directory API - Mobile Devices Directory (supports readonly and action)
[*] 26) Directory API - Organizational Units (supports readonly)
[*] 27) Directory API - Resource Calendars (supports readonly)
[*] 28) Directory API - Roles (supports readonly)
[*] 29) Directory API - User Schemas (supports readonly)
[*] 30) Directory API - User Security
[*] 31) Directory API - Users (supports readonly)
[*] 32) Email Audit API
[*] 33) Groups Migration API
[*] 34) Groups Settings API
[*] 35) License Manager API
[*] 36) People API (supports readonly)
[*] 37) People Directory API - read only
[ ] 38) Pub / Sub API
[*] 39) Reports API - Audit Reports
[*] 40) Reports API - Usage Reports
[ ] 41) Reseller API
[*] 42) Site Verification API
[*] 43) Sites API
[*] 44) Vault API (supports readonly)
s) Select all scopes
u) Unselect all scopes
e) Exit without changes
c) Continue to authorization
Please enter 0-44[a|r] or s|u|e|c: c
Enter your Google Workspace admin email address? admin@domain.com
Go to the following link in a browser on this computer or on another computer:
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=423565144751-10lsdt2lgnsch9jmdhl35uq4617u1ifp&redirect_uri=http%3A%2F%2F127.0.0.1%3A8080%2F&scope=...
If you use a browser on another computer, you will get a browser error that the site can't be reached AFTER you
click the Allow button, paste "Unable to connect" URL from other computer (only URL data up to &scope required):
Enter verification code or paste "Unable to connect" URL from other computer (only URL data up to &scope required):
The authentication flow has completed.
Client OAuth2 File: /Users/admin/GAMConfig/oauth2.txt, Created
admin@server:/Users/admin/bin/gamadv-xtd3$
```
### Update GAMADV-XTD3 service account access.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user admin@domain.com check serviceaccount
$ gam user admin@domain.com check serviceaccount
System time status
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 0 days PASS
Domain-Wide Delegation authentication:, User: admin@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels FAIL (20/28)
https://www.googleapis.com/auth/drive.labels FAIL (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
Some scopes FAILED!
To authorize them, please go to:
https://admin.google.com/ac/owl/domainwidedelegation?clientScopeToAdd=https://mail.google.com/,https://sites.google.com/feeds,https://www.googleapis.com/auth/apps.alerts,https://www.googleapis.com/auth/calendar,https://www.googleapis.com/auth/classroom.announcements,https://www.googleapis.com/auth/classroom.coursework.students,https://www.googleapis.com/auth/classroom.courseworkmaterials,https://www.googleapis.com/auth/classroom.profile.emails,https://www.googleapis.com/auth/classroom.rosters,https://www.googleapis.com/auth/classroom.topics,https://www.googleapis.com/auth/cloud-identity,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/contacts,https://www.googleapis.com/auth/contacts.other.readonly,https://www.googleapis.com/auth/datastudio,https://www.googleapis.com/auth/directory.readonly,https://www.googleapis.com/auth/documents,https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/drive.activity,https://www.googleapis.com/auth/gmail.modify,https://www.googleapis.com/auth/gmail.settings.basic,https://www.googleapis.com/auth/gmail.settings.sharing,https://www.googleapis.com/auth/keep,https://www.googleapis.com/auth/spreadsheets,https://www.googleapis.com/auth/tasks,https://www.googleapis.com/auth/userinfo.profile,https://www.googleapis.com/auth/userinfo.email&clientIdToAdd=SVCACCTID&overwriteClientId=true&dn=domain.com&authuser=admin@domain.com
You will be directed to the Google Workspace admin console Security/API Controls/Domain-wide Delegation page
The "Add a new Client ID" box will open
Make sure that "Overwrite existing client ID" is checked
Click AUTHORIZE
When the box closes you're done
After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
admin@server:/Users/admin/bin/gamadv-xtd3$
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
### Verify GAMADV-XTD3 service account access.
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user admin@domain.com check serviceaccount
System time status:
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication:
Authentication PASS
Domain-Wide Delegation authentication:, User: admin@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels PASS (20/28)
https://www.googleapis.com/auth/drive.labels PASS (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
admin@server:/Users/admin/bin/gamadv-xtd3$
```
## Windows
### Download the latest version
This example assumes that GAMADV-XTD3 has been installed in C:\GAMADV-XTD3.
If you've installed GAMADV-XTD3 in another directory, substitute that value in the directions when downloading.
See: [Downloads](Downloads)
In these examples, your Google Super admin is shown as admin@domain.com; replace with the
actual email adddress.
This example assumes that GAMADV-XTD3 has been installed in C:\GAMADV-XTD3; if you've installed
GAMADV-XTD3 in another directory, substitute that value in the directions.
These steps assume Command Prompt, adjust if you're using PowerShell.
### Update your project with local browser to include the additional APIs that GAMADV-XTD3 uses.
This step may be omitted if you are updating from a recent version.
```
C:\GAMADV-XTD3>gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=...
Authentication successful.
API: admin.googleapis.com, already enabled...
API: appsactivity.googleapis.com, already enabled...
API: calendar-json.googleapis.com, already enabled...
API: classroom.googleapis.com, already enabled...
API: contacts.googleapis.com, already enabled...
API: drive.googleapis.com, already enabled...
API: gmail.googleapis.com, already enabled...
API: groupssettings.googleapis.com, already enabled...
API: licensing.googleapis.com, already enabled...
API: plus.googleapis.com, already enabled...
API: reseller.googleapis.com, already enabled...
API: siteverification.googleapis.com, already enabled...
API: vault.googleapis.com, already enabled...
Enable 3 APIs
API: audit.googleapis.com, Enabled (1/3)
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
C:\GAMADV-XTD3>
```
### Update your project without local browser (headless server for instance) to include the additional APIs that GAMADV-XTD3 uses
This step may be omitted if you are updating from a recent version.
```
C:\GAMADV-XTD3>gam config no_browser true save
C:\GAMADV-XTD3>gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
Go to the following link in a browser on other computer:
https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=...
Enter verification code: abc...xyz
Authentication successful.
API: admin.googleapis.com, already enabled...
API: appsactivity.googleapis.com, already enabled...
API: calendar-json.googleapis.com, already enabled...
API: classroom.googleapis.com, already enabled...
API: contacts.googleapis.com, already enabled...
API: drive.googleapis.com, already enabled...
API: gmail.googleapis.com, already enabled...
API: groupssettings.googleapis.com, already enabled...
API: licensing.googleapis.com, already enabled...
API: plus.googleapis.com, already enabled...
API: reseller.googleapis.com, already enabled...
API: siteverification.googleapis.com, already enabled...
API: vault.googleapis.com, already enabled...
Enable 3 APIs
API: audit.googleapis.com, Enabled (1/3)
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
C:\GAMADV-XTD3>
```
### Update GAMADV-XTD3 client access
You select a list of scopes, GAM uses a browser to get final authorization from Google for these scopes and
writes the credentials into the file oauth2.txt.
```
C:\GAMADV-XTD3>gam oauth create
Select the authorized scopes by entering a number.
Append an 'r' to grant read-only access or an 'a' to grant action-only access.
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
[*] 2) Chrome Management API - Telemetry read only
[*] 3) Chrome Management API - read only
[*] 4) Chrome Policy API (supports readonly)
[*] 5) Chrome Printer Management API (supports readonly)
[*] 6) Chrome Version History API
[*] 7) Classroom API - Course Announcements (supports readonly)
[*] 8) Classroom API - Course Topics (supports readonly)
[*] 9) Classroom API - Course Work/Materials (supports readonly)
[*] 10) Classroom API - Course Work/Submissions (supports readonly)
[*] 11) Classroom API - Courses (supports readonly)
[*] 12) Classroom API - Profile Emails
[*] 13) Classroom API - Profile Photos
[*] 14) Classroom API - Rosters (supports readonly)
[*] 15) Classroom API - Student Guardians (supports readonly)
[*] 16) Cloud Identity Groups API (supports readonly)
[*] 17) Cloud Storage (Vault Export - read only)
[*] 18) Contact Delegation API (supports readonly)
[*] 19) Contacts API - Domain Shared and Users and GAL
[*] 20) Data Transfer API (supports readonly)
[*] 21) Directory API - Chrome OS Devices (supports readonly)
[*] 22) Directory API - Customers (supports readonly)
[*] 23) Directory API - Domains (supports readonly)
[*] 24) Directory API - Groups (supports readonly)
[*] 25) Directory API - Mobile Devices Directory (supports readonly and action)
[*] 26) Directory API - Organizational Units (supports readonly)
[*] 27) Directory API - Resource Calendars (supports readonly)
[*] 28) Directory API - Roles (supports readonly)
[*] 29) Directory API - User Schemas (supports readonly)
[*] 30) Directory API - User Security
[*] 31) Directory API - Users (supports readonly)
[*] 32) Email Audit API
[*] 33) Groups Migration API
[*] 34) Groups Settings API
[*] 35) License Manager API
[*] 36) People API (supports readonly)
[*] 37) People Directory API - read only
[ ] 38) Pub / Sub API
[*] 39) Reports API - Audit Reports
[*] 40) Reports API - Usage Reports
[ ] 41) Reseller API
[*] 42) Site Verification API
[*] 43) Sites API
[*] 44) Vault API (supports readonly)
s) Select all scopes
u) Unselect all scopes
e) Exit without changes
c) Continue to authorization
Please enter 0-44[a|r] or s|u|e|c: c
Enter your Google Workspace admin email address? admin@domain.com
Go to the following link in a browser on this computer or on another computer:
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=423565144751-10lsdt2lgnsch9jmdhl35uq4617u1ifp&redirect_uri=http%3A%2F%2F127.0.0.1%3A8080%2F&scope=...
If you use a browser on another computer, you will get a browser error that the site can't be reached AFTER you
click the Allow button, paste "Unable to connect" URL from other computer (only URL data up to &scope required):
Enter verification code or paste "Unable to connect" URL from other computer (only URL data up to &scope required):
The authentication flow has completed.
Client OAuth2 File: C:\GAMConfig\oauth2.txt, Created
C:\GAMADV-XTD3>
```
### Update GAMADV-XTD3 service account access.
```
C:\GAMADV-XTD3>gam user admin@domain.com check serviceaccount
System time status
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication
Authentication PASS
Service Account Private Key age; Google recommends rotating keys on a routine basis
Service Account Private Key age: 0 days PASS
Domain-Wide Delegation authentication:, User: admin@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels FAIL (20/28)
https://www.googleapis.com/auth/drive.labels FAIL (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
Some scopes FAILED!
To authorize them, please go to:
https://admin.google.com/ac/owl/domainwidedelegation?clientScopeToAdd=https://mail.google.com/,https://sites.google.com/feeds,https://www.googleapis.com/auth/apps.alerts,https://www.googleapis.com/auth/calendar,https://www.googleapis.com/auth/classroom.announcements,https://www.googleapis.com/auth/classroom.coursework.students,https://www.googleapis.com/auth/classroom.courseworkmaterials,https://www.googleapis.com/auth/classroom.profile.emails,https://www.googleapis.com/auth/classroom.rosters,https://www.googleapis.com/auth/classroom.topics,https://www.googleapis.com/auth/cloud-identity,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/contacts,https://www.googleapis.com/auth/contacts.other.readonly,https://www.googleapis.com/auth/datastudio,https://www.googleapis.com/auth/directory.readonly,https://www.googleapis.com/auth/documents,https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/drive.activity,https://www.googleapis.com/auth/gmail.modify,https://www.googleapis.com/auth/gmail.settings.basic,https://www.googleapis.com/auth/gmail.settings.sharing,https://www.googleapis.com/auth/keep,https://www.googleapis.com/auth/spreadsheets,https://www.googleapis.com/auth/tasks,https://www.googleapis.com/auth/userinfo.profile,https://www.googleapis.com/auth/userinfo.email&clientIdToAdd=SVCACCTID&overwriteClientId=true&dn=domain.com&authuser=admin@domain.com
You will be directed to the Google Workspace admin console Security/API Controls/Domain-wide Delegation page
The "Add a new Client ID" box will open
Make sure that "Overwrite existing client ID" is checked
Click AUTHORIZE
When the box closes you're done
After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
C:\GAMADV-XTD3>
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
### Verify GAMADV-XTD3 service account access.
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
C:\GAMADV-XTD3>gam user admin@domain.com check serviceaccount
System time status:
Your system time differs from www.googleapis.com by less than 1 second PASS
Service Account Private Key Authentication:
Authentication PASS
Domain-Wide Delegation authentication:, User: admin@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels PASS (20/28)
https://www.googleapis.com/auth/drive.labels PASS (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
C:\GAMADV-XTD3>
```

View File

@ -0,0 +1,510 @@
# Installation - Upgrading from a prior version of GAMADV-X or GAMADV-XTD
Use these steps if you have used any version of GAMADV-X or GAMADV-XTD in your domain.
They will update your GAM project and all necessary authentications.
- [Downloads](Downloads)
- [GAM Configuration](gam.cfg)
- [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell)
- [Windows](#windows)
## Linux and MacOS and Google Cloud Shell
In these examples, your Google Super admin is shown as admin@domain.com; replace with the
actual email adddress.
In these examples, the user home folder is shown as /Users/admin; adjust according to your
specific situation; e.g., /home/administrator.
This example assumes that GAMADV-XTD3 has been installed in /Users/admin/bin/gamadv-xtd3.
If you've installed GAMADV-XTD3 in another directory, substitute that value in the directions.
GAMADV-XTD3 uses the same configuration directory and gam.cfg file as GAMADV-X and GAMADV-XTD.
### Update your alias
You should update your alias to point to /Users/admin/bin/gamadv-xtd3/gam.
Add the following line:
```
alias gam="/Users/admin/bin/gamadv-xtd3/gam"
```
to one of these files if you're running bash or an equivalent file if you're running some other shell:
```
~/.bash_aliases
~/.bash_profile
~/.bashrc
```
If you already have a gam alias for standard GAM and want to run it and GAMADV-XTD3, give your new alias a different name:
```
alias gam3="/Users/admin/bin/gamadv-xtd3/gam"
```
### Do you have a browser?
If your computer doesn't support a browser, Google Cloud Shell for instance, execute this command:
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam config no_browser true save
```
### Update your project to include the additional APIs that GAMADV-XTD3 uses.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=...
If your browser is on a different machine then press CTRL+C,
set no_browser = true in gam.cfg and re-run this command.
Authentication successful.
API: admin.googleapis.com, already enabled...
API: appsactivity.googleapis.com, already enabled...
API: calendar-json.googleapis.com, already enabled...
API: classroom.googleapis.com, already enabled...
API: contacts.googleapis.com, already enabled...
API: drive.googleapis.com, already enabled...
API: gmail.googleapis.com, already enabled...
API: groupssettings.googleapis.com, already enabled...
API: licensing.googleapis.com, already enabled...
API: plus.googleapis.com, already enabled...
API: reseller.googleapis.com, already enabled...
API: siteverification.googleapis.com, already enabled...
API: vault.googleapis.com, already enabled...
Enable 3 APIs
API: audit.googleapis.com, Enabled (1/3)
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
admin@server:/Users/admin/bin/gamadv-xtd3$
```
### Update GAMADV-XTD3 client access.
Update oauth2.txt; it must be updated to reflect the additional capabilites of GAMADV-XTD3.
You select a list of scopes, GAM uses a browser to get final authorization from Google for these scopes and
writes the credentials into the file oauth2.txt.
If the computer on which you are running GAM does not have access to a browser, issue this command:
```
gam config no_browser true oauth update
```
You will be given instructions on how to get the authorization on another computer and apply it locally.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam oauth update
Select the authorized scopes by entering a number.
Append an 'r' to grant read-only access or an 'a' to grant action-only access.
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
[*] 2) Chrome Management API - Telemetry read only
[*] 3) Chrome Management API - read only
[*] 4) Chrome Policy API (supports readonly)
[*] 5) Chrome Printer Management API (supports readonly)
[*] 6) Chrome Version History API
[*] 7) Classroom API - Course Announcements (supports readonly)
[*] 8) Classroom API - Course Topics (supports readonly)
[*] 9) Classroom API - Course Work/Materials (supports readonly)
[*] 10) Classroom API - Course Work/Submissions (supports readonly)
[*] 11) Classroom API - Courses (supports readonly)
[*] 12) Classroom API - Profile Emails
[*] 13) Classroom API - Profile Photos
[*] 14) Classroom API - Rosters (supports readonly)
[*] 15) Classroom API - Student Guardians (supports readonly)
[*] 16) Cloud Identity Groups API (supports readonly)
[*] 17) Cloud Storage (Vault Export - read only)
[*] 18) Contact Delegation API (supports readonly)
[*] 19) Contacts API - Domain Shared and Users and GAL
[*] 20) Data Transfer API (supports readonly)
[*] 21) Directory API - Chrome OS Devices (supports readonly)
[*] 22) Directory API - Customers (supports readonly)
[*] 23) Directory API - Domains (supports readonly)
[*] 24) Directory API - Groups (supports readonly)
[*] 25) Directory API - Mobile Devices Directory (supports readonly and action)
[*] 26) Directory API - Organizational Units (supports readonly)
[*] 27) Directory API - Resource Calendars (supports readonly)
[*] 28) Directory API - Roles (supports readonly)
[*] 29) Directory API - User Schemas (supports readonly)
[*] 30) Directory API - User Security
[*] 31) Directory API - Users (supports readonly)
[*] 32) Email Audit API
[*] 33) Groups Migration API
[*] 34) Groups Settings API
[*] 35) License Manager API
[*] 36) People API (supports readonly)
[*] 37) People Directory API - read only
[ ] 38) Pub / Sub API
[*] 39) Reports API - Audit Reports
[*] 40) Reports API - Usage Reports
[ ] 41) Reseller API
[*] 42) Site Verification API
[*] 43) Sites API
[*] 44) Vault API (supports readonly)
s) Select all scopes
u) Unselect all scopes
e) Exit without changes
c) Continue to authorization
Please enter 0-44[a|r] or s|u|e|c: c
Enter your Google Workspace admin email address?admin@domain.com
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/v2/auth?client_id=CLIENTID&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.courses+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.announcements+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.coursework.students+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.guardianlinks.students+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.profile.emails+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.profile.photos+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.rosters+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloudprint+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdevstorage.read_only+https%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.datatransfer+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.device.chromeos+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.customer+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.domain+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.group+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.device.mobile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.orgunit+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.resource.calendar+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.rolemanagement+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.userschema+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.user.security+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.user+https%3A%2F%2Fapps-apis.google.com%2Fa%2Ffeeds%2Fcompliance%2Faudit%2F+https%3A%2F%2Fapps-apis.google.com%2Fa%2Ffeeds%2Femailsettings%2F2.0%2F+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fapps.groups.migration+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fapps.groups.settings+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fapps.licensing+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcontacts+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.reports.audit.readonly+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.reports.usage.readonly+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fapps.order+https%3A%2F%2Fsites.google.com%2Ffeeds+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fediscovery&login_hint=admin%40domain.com&access_type=offline&response_type=code
If your browser is on a different machine then press CTRL+C,
set no_browser = true in gam.cfg and re-run this command.
Authentication successful.
Client OAuth2 File: /Users/admin/GAMConfig/oauth2.txt, Updated
admin@server:/Users/admin/bin/gamadv-xtd3$
```
### Update GAMADV-XTD3 service account access.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user user@domain.com check serviceaccount
System time status:
Your system time differs by less than 1 second from Google PASS
Service Account Private Key Authentication:
Authentication PASS
Domain-Wide Delegation authentication:, User: user@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels FAIL (20/28)
https://www.googleapis.com/auth/drive.labels FAIL (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
Some scopes FAILED! Please go to:
https://admin.google.com/domain.com/ManageOauthClients?clientScopeToAdd=https://mail.google.com/,https://sites.google.com/feeds,https://www.google.com/m8/feeds,https://www.googleapis.com/auth/activity,https://www.googleapis.com/auth/apps.alerts,https://www.googleapis.com/auth/calendar,https://www.googleapis.com/auth/classroom.announcements,https://www.googleapis.com/auth/classroom.coursework.students,https://www.googleapis.com/auth/classroom.rosters,https://www.googleapis.com/auth/classroom.topics,https://www.googleapis.com/auth/cloudprint,https://www.googleapis.com/auth/contacts,https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/drive.activity,https://www.googleapis.com/auth/gmail.modify,https://www.googleapis.com/auth/gmail.settings.basic,https://www.googleapis.com/auth/gmail.settings.sharing,https://www.googleapis.com/auth/iam,https://www.googleapis.com/auth/spreadsheets,https://www.googleapis.com/auth/userinfo.email&clientNameToAdd=SVCACCTID
You will be directed to the Google Workspace admin console. The Client Name and API
Scopes fields will be pre-populated. Please click Authorize to allow these
scopes access. After authorizing it may take some time for this test to pass so
wait a few moments and then try this command again.
admin@server:/Users/admin/bin/gamadv-xtd3$
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
### Verify GAMADV-XTD3 service account access.
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam user user@domain.com check serviceaccount
System time status:
Your system time differs by less than 1 second from Google PASS
Service Account Private Key Authentication:
Authentication PASS
Domain-Wide Delegation authentication:, User: user@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels PASS (20/28)
https://www.googleapis.com/auth/drive.labels PASS (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
admin@server:/Users/admin/bin/gamadv-xtd3$
```
## Windows
In these examples, your Google Super admin is shown as admin@domain.com; replace with the
actual email adddress.
This example assumes that GAMADV-XTD3 has been installed in C:\GAMADV-XTD3; if you've installed
GAMADV-XTD3 in another directory, substitute that value in the directions.
GAMADV-XTD3 uses the same configuration directory and gam.cfg file as GAMADV-X and GAMADV-XTD.
### Update system path
You should update the system path to point to C:\GAMADV-XTD3.
```
Start Control Panel
Click System
Click Advanced system settings
Click Environment Variables...
Click Path under System variables
Click Edit...
If you have an existing entry referencing GAMADV-X or GAMADV-XTD:
Click that entry
Click Delete
If C:\GAMADV-XTD3 is already on the Path, skip the next three steps
Click New
Enter C:\GAMADV-XTD3
Click OK
Click OK
Click OK
Exit Control Panel
```
### Do you have a compatible browser?
If the computer on which you are running GAM does not have access to a browser or
your default browser is Internet Explorer or Edge, issue this command:
```
C:\GAMADV-X>gam config no_browser true save
```
### Update your project to include the additional APIs that GAMADV-XTD3 uses.
```
C:\GAMADV-XTD3>gam update project
Enter your Google Workspace admin or GCP project manager email address authorized to manage project(s) gam-project-abc-123-xyz? admin@domain.com
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=...
If your browser is on a different machine then press CTRL+C,
set no_browser = true in gam.cfg and re-run this command.
Authentication successful.
API: admin.googleapis.com, already enabled...
API: appsactivity.googleapis.com, already enabled...
API: calendar-json.googleapis.com, already enabled...
API: classroom.googleapis.com, already enabled...
API: contacts.googleapis.com, already enabled...
API: drive.googleapis.com, already enabled...
API: gmail.googleapis.com, already enabled...
API: groupssettings.googleapis.com, already enabled...
API: licensing.googleapis.com, already enabled...
API: plus.googleapis.com, already enabled...
API: reseller.googleapis.com, already enabled...
API: siteverification.googleapis.com, already enabled...
API: vault.googleapis.com, already enabled...
Enable 3 APIs
API: audit.googleapis.com, Enabled (1/3)
API: groupsmigration.googleapis.com, Enabled (2/3)
API: sheets.googleapis.com, Enabled (3/3)
C:\GAMADV-XTD3>
```
### Update GAMADV-XTD3 client access.
Update oauth2.txt; it must be updated to reflect the additional capabilites of GAMADV-XTD3.
If the PC on which you are running GAM does not have access to a browser or if
your default browser is Internet Explorer or Edge, issue this command:
```
gam config no_browser true oauth update
```
You will be given instructions on how to get the authorization; this involves a long URL that must be copied/pasted.
Older versions of Command Prompt and PowerShell (Windows 7/8, Server 2008) can't properly copy/paste multi line strings;
GAM writes the long URL into the file `gamoauthurl.txt` in the folder with the GAM executable.
You can open the file with Notepad/Wordpad, do a control-A to select the text, control-C to copy the text,
start a browser and paste the URL (control-V) into the address bar. Authenticate and copy the Verification code
back to your Command Prompt/PowerShell window.
```
C:\GAMADV-XTD3>gam oauth update
Select the authorized scopes by entering a number.
Append an 'r' to grant read-only access or an 'a' to grant action-only access.
[*] 0) Calendar API (supports readonly)
[*] 1) Chrome Browser Cloud Management API (supports readonly)
[*] 2) Chrome Management API - Telemetry read only
[*] 3) Chrome Management API - read only
[*] 4) Chrome Policy API (supports readonly)
[*] 5) Chrome Printer Management API (supports readonly)
[*] 6) Chrome Version History API
[*] 7) Classroom API - Course Announcements (supports readonly)
[*] 8) Classroom API - Course Topics (supports readonly)
[*] 9) Classroom API - Course Work/Materials (supports readonly)
[*] 10) Classroom API - Course Work/Submissions (supports readonly)
[*] 11) Classroom API - Courses (supports readonly)
[*] 12) Classroom API - Profile Emails
[*] 13) Classroom API - Profile Photos
[*] 14) Classroom API - Rosters (supports readonly)
[*] 15) Classroom API - Student Guardians (supports readonly)
[*] 16) Cloud Identity Groups API (supports readonly)
[*] 17) Cloud Storage (Vault Export - read only)
[*] 18) Contact Delegation API (supports readonly)
[*] 19) Contacts API - Domain Shared and Users and GAL
[*] 20) Data Transfer API (supports readonly)
[*] 21) Directory API - Chrome OS Devices (supports readonly)
[*] 22) Directory API - Customers (supports readonly)
[*] 23) Directory API - Domains (supports readonly)
[*] 24) Directory API - Groups (supports readonly)
[*] 25) Directory API - Mobile Devices Directory (supports readonly and action)
[*] 26) Directory API - Organizational Units (supports readonly)
[*] 27) Directory API - Resource Calendars (supports readonly)
[*] 28) Directory API - Roles (supports readonly)
[*] 29) Directory API - User Schemas (supports readonly)
[*] 30) Directory API - User Security
[*] 31) Directory API - Users (supports readonly)
[*] 32) Email Audit API
[*] 33) Groups Migration API
[*] 34) Groups Settings API
[*] 35) License Manager API
[*] 36) People API (supports readonly)
[*] 37) People Directory API - read only
[ ] 38) Pub / Sub API
[*] 39) Reports API - Audit Reports
[*] 40) Reports API - Usage Reports
[ ] 41) Reseller API
[*] 42) Site Verification API
[*] 43) Sites API
[*] 44) Vault API (supports readonly)
s) Select all scopes
u) Unselect all scopes
e) Exit without changes
c) Continue to authorization
Please enter 0-44[a|r] or s|u|e|c: c
Enter your Google Workspace admin email address? admin@domain.com
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/v2/auth?client_id=CLIENTID&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.courses+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.announcements+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.coursework.students+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.guardianlinks.students+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.profile.emails+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.profile.photos+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclassroom.rosters+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloudprint+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdevstorage.read_only+https%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.datatransfer+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.device.chromeos+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.customer+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.domain+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.group+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.device.mobile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.orgunit+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.resource.calendar+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.rolemanagement+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.userschema+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.user.security+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.directory.user+https%3A%2F%2Fapps-apis.google.com%2Fa%2Ffeeds%2Fcompliance%2Faudit%2F+https%3A%2F%2Fapps-apis.google.com%2Fa%2Ffeeds%2Femailsettings%2F2.0%2F+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fapps.groups.migration+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fapps.groups.settings+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fapps.licensing+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcontacts+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.reports.audit.readonly+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadmin.reports.usage.readonly+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fapps.order+https%3A%2F%2Fsites.google.com%2Ffeeds+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fediscovery&login_hint=admin%40domain.com&access_type=offline&response_type=code
If your browser is on a different machine then press CTRL+C,
set no_browser = true in gam.cfg and re-run this command.
Authentication successful.
Client OAuth2 File: C:\GAMConfig\oauth2.txt, Updated
C:\GAMADV-XTD3>
```
### Enable GAMADV-XTD3 service account access.
```
C:\GAMADV-XTD3>gam user user@domain.com check serviceaccount
System time status:
Your system time differs by less than 1 second from Google PASS
Service Account Private Key Authentication:
Authentication PASS
Domain-Wide Delegation authentication:, User: user@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels FAIL (20/28)
https://www.googleapis.com/auth/drive.labels FAIL (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
Some scopes FAILED! Please go to:
https://admin.google.com/domain.com/ManageOauthClients?clientScopeToAdd=https://mail.google.com/,https://sites.google.com/feeds,https://www.google.com/m8/feeds,https://www.googleapis.com/auth/activity,https://www.googleapis.com/auth/apps.alerts,https://www.googleapis.com/auth/calendar,https://www.googleapis.com/auth/classroom.announcements,https://www.googleapis.com/auth/classroom.coursework.students,https://www.googleapis.com/auth/classroom.rosters,https://www.googleapis.com/auth/classroom.topics,https://www.googleapis.com/auth/cloudprint,https://www.googleapis.com/auth/contacts,https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/drive.activity,https://www.googleapis.com/auth/gmail.modify,https://www.googleapis.com/auth/gmail.settings.basic,https://www.googleapis.com/auth/gmail.settings.sharing,https://www.googleapis.com/auth/iam,https://www.googleapis.com/auth/spreadsheets,https://www.googleapis.com/auth/userinfo.email&clientNameToAdd=SVCACCTID
You will be directed to the Google Workspace admin console. The Client Name and API
Scopes fields will be pre-populated. Please click Authorize to allow these
scopes access. After authorizing it may take some time for this test to pass so
wait a few moments and then try this command again.
C:\GAMADV-XTD3>
```
The link shown in the error message should take you directly to the authorization screen.
If not, make sure that you are logged in as a domain admin, then re-enter the link.
### Verify GAMADV-XTD3 service account access.
Wait a moment and then perform the following command; it it still fails, wait a bit longer, it can sometimes take serveral minutes
for the authorization to complete.
```
C:\GAMADV-XTD3>gam user user@domain.com check serviceaccount
System time status:
Your system time differs by less than 1 second from Google PASS
Service Account Private Key Authentication:
Authentication PASS
Domain-Wide Delegation authentication:, User: user@domain.com, Scopes: 28
https://mail.google.com/ PASS (1/28)
https://sites.google.com/feeds PASS (2/28)
https://www.googleapis.com/auth/apps.alerts PASS (3/28)
https://www.googleapis.com/auth/calendar PASS (4/28)
https://www.googleapis.com/auth/classroom.announcements PASS (5/28)
https://www.googleapis.com/auth/classroom.coursework.students PASS (6/28)
https://www.googleapis.com/auth/classroom.courseworkmaterials PASS (7/28)
https://www.googleapis.com/auth/classroom.profile.emails PASS (8/28)
https://www.googleapis.com/auth/classroom.rosters PASS (9/28)
https://www.googleapis.com/auth/classroom.topics PASS (10/28)
https://www.googleapis.com/auth/cloud-identity PASS (11/28)
https://www.googleapis.com/auth/cloud-platform PASS (12/28)
https://www.googleapis.com/auth/contacts PASS (13/28)
https://www.googleapis.com/auth/contacts.other.readonly PASS (14/28)
https://www.googleapis.com/auth/datastudio PASS (15/28)
https://www.googleapis.com/auth/directory.readonly PASS (16/28)
https://www.googleapis.com/auth/documents PASS (17/28)
https://www.googleapis.com/auth/drive PASS (18/28)
https://www.googleapis.com/auth/drive.activity PASS (19/28)
https://www.googleapis.com/auth/drive.admin.labels PASS (20/28)
https://www.googleapis.com/auth/drive.labels PASS (21/28)
https://www.googleapis.com/auth/gmail.modify PASS (22/28)
https://www.googleapis.com/auth/gmail.settings.basic PASS (23/28)
https://www.googleapis.com/auth/gmail.settings.sharing PASS (24/28)
https://www.googleapis.com/auth/keep PASS (25/28)
https://www.googleapis.com/auth/spreadsheets PASS (26/28)
https://www.googleapis.com/auth/tasks PASS (27/28)
https://www.googleapis.com/auth/userinfo.profile PASS (28/28)
All scopes PASSED!
Service Account Client name: SVCACCTID is fully authorized.
C:\GAMADV-XTD3>
```

File diff suppressed because it is too large Load Diff

166
docs/Inbound-SSO.md Normal file
View File

@ -0,0 +1,166 @@
# Inbound SSO
- [Admin Console](#admin-console)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Manage profiles](#manage-profiles)
- [Display profiles](#display-profiles)
- [Manage credentials](#manage-credentials)
- [Display credentials](#display-credentials)
- [Manage assignments](#manage-assignments)
- [Display assignments](#display-assignments)
## Admin Console
* https://admin.google.com/ac/security/sso
## API documentation
* https://cloud.google.com/identity/docs/reference/rest/v1beta1/inboundSamlSsoProfiles
* https://cloud.google.com/identity/docs/reference/rest/v1beta1/inboundSamlSsoProfiles.idpCredentials
* https://cloud.google.com/identity/docs/reference/rest/v1beta1/inboundSsoAssignments
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<FileName> ::= <String>
<OrgUnitPath> ::= /|(/<String>)+
<SSOProfileDisplayName> ::= <String>
<SSOProfileName> ::= id:inboundSamlSsoProfiles/<String>
<SSOProfileItem> ::= <SSOProfileDisplayName>|<SSOProfileName>
<SSOProfileItemList> ::= "<SSOProfileItem>(,<SSOProfileItem>)*"
<SSOCredentialsName> ::= [id:]inboundSamlSsoProfiles/<String>/idpCredentials/<String>
<SSOAssignmentName> ::= [id:]inboundSsoAssignments/<String>
<SSOAssignmentSelector> ::=
<SSOAssignmentName> |
groups/<String> |
group:<EmailAddress> |
orgunits/<String> |
orgunit:<OrgUnitPath>
```
## Manage profiles
```
gam create inboundssoprofile [name <SSOProfileDisplayName>]
[entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
[returnnameonly]
gam update inboundssoprofile <SSOProfileItem>
[entityid <String>] [loginurl <URL>] [logouturl <URL>] [changepasswordurl <URL>]
[returnnameonly]
```
By default, all fields of the created|updated profile are displayed;
use the `returnnameonly` option to have GAM display just the profile name of the created|updated profile.
This will be useful in scripts that create|update a profile and then want to perform subsequent GAM commands that
reference the profile.
gam delete inboundssoprofile <SSOProfileItem>
```
## Display profiles
Display a specific profile.
```
gam info inboundssoprofile <SSOProfileItem>
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
Display all profiles.
```
gam show inboundssoprofiles
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
Display all profiles in a CSV file.
```
gam print inboundssoprofiles [todrive <ToDriveAttribute>*]
[[formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Manage credentials
```
gam create inboundssocredential profile <SSOProfileItem>
(pemfile <FileName>)|(generatekey [keysize 1024|2048|4096]) [replaceolddest]
gam delete inboundssocredential <SSOCredentialsName>
```
## Display credentials
Display a specific credential.
```
gam info inboundssocredential <SSOCredentialsName>
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
Display all credentials.
```
gam show inboundssocredentials [profile|profiles <SSOProfileItemList>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
Display all credentials in a CSV file.
```
gam print inboundssocredentials [profile|profiles <SSOProfileItemList>]
[[formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Manage assignments
```
gam create inboundssoassignment (group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)
(mode sso_off)|(mode saml_sso profile <SSOProfileItem>)(mode domain_wide_saml_if_enabled) [neverredirect]
gam update inboundssoassignment [(group <GroupItem> rank <Number>)|(ou|org|orgunit <OrgUnitItem>)]
[(mode sso_off)|(mode saml_sso profile <SSOProfileItem>)(mode domain_wide_saml_if_enabled)] [neverredirect]
gam delete inboundssoassignment <SSOAssignmentSelector>
```
## Display assignments
Display a specific assignment.
```
gam info inboundssoassignment <SSOAssignmentSelector>
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
Display all assignments.
```
gam show inboundssoassignments
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
Display all assignments in a CSV file.
```
gam print inboundssoassignments [todrive <ToDriveAttribute>*]
[[formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,59 @@
# Install GAM as Python Library
Thanks to Jay Lee for showing me how to do this.
On Windows, you need to install Git to use the pip command.
* See: https://pythoninoffice.com/python-pip-install-from-github/
Scroll down to Install Git
You can install GAM as a Python library with pip.
```
pip install git+https://github.com/taers232c/GAMADV-XTD3.git#subdirectory=src --use-pep517
```
Or as a PEP 508 Requirement Specifier, e.g. in requirements.txt file:
```
advanced-gam-for-google-workspace @ git+https://github.com/taers232c/GAMADV-XTD3.git#subdirectory=src
```
Or a pyproject.toml file:
```
[project]
name = "your-project"
# ...
dependencies = [
"advanced-gam-for-google-workspace @ git+https://github.com/taers232c/GAMADV-XTD3.git#subdirectory=src"
]
```
Target a specific revision or tag:
```
advanced-gam-for-google-workspace @ git+https://github.com/taers232c/GAMADV-XTD3.git@v6.58.00#subdirectory=src
```
## Using the library
```
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" Sample Python script to call GAM"""
import multiprocessing
import platform
from gam import initializeLogging, CallGAMCommand
if __name__ == '__main__':
# One time initialization
if platform.system() != 'Linux':
multiprocessing.freeze_support()
multiprocessing.set_start_method('spawn')
initializeLogging()
#
CallGAMCommand(['gam', 'version'])
# Issue command, output goes to stdout/stderr
rc = CallGAMCommand(['gam', 'info', 'domain'])
# Issue command, redirect stdout/stderr
rc = CallGAMCommand(['gam', 'redirect', 'stdout', 'domain.txt', 'redirect', 'stderr', 'stdout', 'info', 'domain'])
```

282
docs/Licenses.md Normal file
View File

@ -0,0 +1,282 @@
# Licenses
- [API documentation](#api-documentation)
- [License Products and SKUs](#license-products-and-skus)
- [Definitions](#definitions)
- [Notes](#Notes)
- [Display license counts](#display-license-counts)
- [Display licenses](#display-licenses)
- [Add licenses](#add-licenses)
- [Update licenses](#update-licenses)
- [Delete licenses](#delete-licenses)
- [Synchronize licenses](#synchronize-licenses)
## API documentation
* https://developers.google.com/admin-sdk/licensing/v1/reference/licenseAssignments
## License Products and SKUs
* https://developers.google.com/admin-sdk/licensing/v1/how-tos/products
| Product Name | Product ID |
|--------------|------------|
| AppSheet | 101038 |
| Assured Controls | 101039 |
| Beyond Corp Enterprise | 101040 |
| Cloud Identity Free | 101001 |
| Cloud Identity Premium | 101005 |
| Cloud Search | 101035 |
| Google Chrome Device Management | Google-Chrome-Device-Management |
| Google Drive Storage | Google-Drive-storage |
| Google Meet Global Dialing | 101036 |
| Google Vault |Google-Vault |
| Google Voice | 101033 |
| Google Workspace Archived User | 101034 |
| Google Workspace for Education | 101031 |
| Google Workspace for Education | 101037 |
| Google Workspace | Google-Apps |
| License Name | License SKU | Abbreviation |
|--------------|-------------|---------------|
| AppSheet Core | 1010380001 | appsheetcore |
| AppSheet Enterprise Standard | 1010380002 | appsheetstandard |
| AppSheet Enterprise Plus | 1010380003 | appsheetplus |
| Assured Controls | 1010390001 | assuredcontrols |
| Beyond Corp Enterprise | 1010400001 | bce |
| Cloud Identity Free | 1010010001 | cloudidentity |
| Cloud Identity Premium | 1010050001 | cloudidentitypremium |
| Cloud Search | 1010350001 | cloudsearch |
| G Suite Basic | Google-Apps-For-Business | gsuitebasic |
| G Suite Business | Google-Apps-Unlimited | gsuitebusiness |
| G Suite Legacy | Google-Apps | standard |
| G Suite Lite | Google-Apps-Lite | gsuitelite |
| Google Apps Message Security | Google-Apps-For-Postini | postini |
| Google Chrome Device Management | Google-Chrome-Device-Management | cdm |
| Google Drive Storage 16TB | Google-Drive-storage-16TB | 16tb |
| Google Drive Storage 1TB | Google-Drive-storage-1TB | 1tb |
| Google Drive Storage 200GB | Google-Drive-storage-200GB | 200gb |
| Google Drive Storage 20GB | Google-Drive-storage-20GB | 20gb |
| Google Drive Storage 2TB | Google-Drive-storage-2TB | 2tb |
| Google Drive Storage 400GB | Google-Drive-storage-400GB | 400gb |
| Google Drive Storage 4TB | Google-Drive-storage-4TB | 4tb |
| Google Drive Storage 50GB | Google-Drive-storage-50GB | 50gb |
| Google Drive Storage 8TB | Google-Drive-storage-8TB | 8tb |
| Google Meet Global Dialing | 1010360001 | meetdialing,googlemeetglobaldialing |
| Google Vault Former Employee | Google-Vault-Former-Employee | vfe |
| Google Vault | Google-Vault | vault |
| Google Voice Premier | 1010330002 | voicepremier |
| Google Voice Standard | 1010330004 | voicestandard |
| Google Voice Starter | 1010330003 | voicestarter |
| Google Workspace Business - Archived User | 1010340002 | gsuitebusinessarchived |
| Google Workspace Business Plus - Archived User | 1010340003 | wsbizplusarchived |
| Google Workspace Business Plus | 1010020025 | wsbizplus |
| Google Workspace Business Standard | 1010020028 | wsbizstan |
| Google Workspace Business Starter | 1010020027 | wsbizstarter |
| Google Workspace Enterprise Essentials | 1010060003 | wsentess |
| Google Workspace Enterprise Plus - Archived User | 1010340001 | gsuiteenterprisearchived |
| Google Workspace Enterprise Plus | 1010020020 | wsentplus |
| Google Workspace Enterprise Standard - Archived User | 1010340004 | wsentstanarchived |
| Google Workspace Enterprise Standard | 1010020026 | wsentstan |
| Google Workspace Enterprise Starter | 1010020029 | wsentstarter |
| Google Workspace Essentials | 1010060001 | wsess |
| Google Workspace Government | Google-Apps-For-Government | gsuitegov |
| Google Workspace for Education Plus (Extra Student) | 1010310010 | gwepstudent |
| Google Workspace for Education Plus (Staff) | 1010310009 | gwepstaff |
| Google Workspace for Education Plus - Legacy (Student) | 1010310003 | gsuiteenterpriseeducationstudent |
| Google Workspace for Education Plus - Legacy | 1010310002 | gsuiteenterpriseeducation |
| Google Workspace for Education Plus | 1010310008 | gwep |
| Google Workspace for Education Standard (Extra Student) | 1010310007 | gwesstudent |
| Google Workspace for Education Standard (Staff) | 1010310006 | gwesstaff |
| Google Workspace for Education Standard | 1010310005 | gwes |
| Google Workspace for Education: Teaching and Learning Upgrade | 1010370001 | gwetlu |
| Google Workspace Frontline | 1010020030 | wsflw,workspacefrontline,workspacefrontlineworker |
## Definitions
```
<ProductID> ::=
nv:<String> |
101001 |
101005 |
101031 |
101033 |
101034 |
101035 |
101036 |
101037 |
101038 |
101039 |
101040 |
Google-Apps |
Google-Chrome-Device-Management |
Google-Drive-storage |
Google-Vault
<ProductIDList> ::= "(<ProductID>|SKUID>)(,<ProductID>|SKUID>)*"
<SKUID> ::=
nv:<String>:<String> |
20gb | drive20gb | googledrivestorage20gb | Google-Drive-storage-20GB |
50gb | drive50gb | googledrivestorage50gb | Google-Drive-storage-50GB |
200gb | drive200gb | googledrivestorage200gb | Google-Drive-storage-200GB |
400gb | drive400gb | googledrivestorage400gb | Google-Drive-storage-400GB |
1tb | drive1tb | googledrivestorage1tb | Google-Drive-storage-1TB |
2tb | drive2tb | googledrivestorage2tb | Google-Drive-storage-2TB |
4tb | drive4tb | googledrivestorage4tb | Google-Drive-storage-4TB |
8tb | drive8tb | googledrivestorage8tb | Google-Drive-storage-8TB |
16tb | drive16tb | googledrivestorage16tb | Google-Drive-storage-16TB |
appsheetcore | 1010380001 |
appsheetstandard | appsheetenterprisestandard | 1010380002 |
appsheetplus | appsheetenterpriseplus | 1010380003 |
assuredcontrols | 1010390001 |
bce | beyondcorp | beyondcorpenterprise | 1010400001 |
cdm | chrome | googlechromedevicemanagement | Google-Chrome-Device-Management |
cloudidentity | identity | 1010010001 |
cloudidentitypremium | identitypremium | 1010050001 |
cloudsearch | 1010350001 |
gsuitebasic | gafb | gafw | basic | Google-Apps-For-Business |
gsuitebusiness | gau | gsb | unlimited | Google-Apps-Unlimited |
gsuitebusinessarchived | gsbau | businessarchived | 1010340002 |
gsuiteenterprisearchived | gseau | enterprisearchived | 1010340001 |
gsuiteenterpriseeducation | gsefe | e4e | 1010310002 |
gsuiteenterpriseeducationstudent | gsefes | e4es | 1010310003 |
gsuitegov | gafg | gsuitegovernment | Google-Apps-For-Government |
gsuitelite | gal | gsl | lite | Google-Apps-Lite |
gwep | workspaceeducationplus | 1010310008 |
gwepstaff | workspaceeducationplusstaff | 1010310009 |
gwepstudent | workspaceeducationplusstudent | 1010310010 |
gwes | workspaceeducationstandard | 1010310005 |
gwesstaff | workspaceeducationstandardstaff | 1010310006 |
gwesstudent | workspaceeducationstandardstudent | 1010310007 |
gwetlu | workspaceeducationupgrade | 1010370001 |
meetdialing | googlemeetglobaldialing | 1010360001 |
postini | gams | gsuitegams | gsuitepostini | gsuitemessagesecurity | Google-Apps-For-Postini |
standard | free | Google-Apps |
vault | googlevault | Google-Vault |
vfe | googlevaultformeremployee | Google-Vault-Former-Employee |
voicepremier | gvpremier | googlevoicepremier | 1010330002 |
voicestandard | gvstandard | googlevoicestandard | 1010330004 |
voicestarter | gvstarter | googlevoicestarter | 1010330003 |
wsbizplus | workspacebusinessplus | 1010020025 |
wsbizplusarchived | workspacebusinessplusarchived | 1010340003 |
wsbizstan | workspacebusinessstandard | 1010020028 |
wsbizstarter | workspacebusinessstarter | wsbizstart | 1010020027 |
wsentess | workspaceenterpriseessentials | 1010060003 |
wsentplus | workspaceenterpriseplus | gae | gse | enterprise | gsuiteenterprise | 1010020020 |
wsentstan | workspaceenterprisestandard | 1010020026 |
wsentstanarchived | workspaceenterprisestandardarchived | 1010340004 |
wsentstarter | workspaceenterprisestarter | 1010020029 | wes |
wsess | workspaceesentials | gsuiteessentials | essentials | d4e | driveenterprise | drive4enterprise | 1010060001 |
wsflw | workspacefrontline | workspacefrontlineworker | 1010020030
<SKUIDList> ::= "<SKUID>(,<SKUID>)*"
```
## Notes
GAM maintains a table of Products and SKUs that it uses to validate `<ProductID>` and `<SKUID>`;
an error is generated for values not in the table. This could cause a problem if Google adds
additional Products or SKUs that are not in the table.
You can enter a non-validated Product as follows:
```
nv:<String>
```
You can enter a non-validated SKU as follows:
```
nv:<String>:<String>
```
The first `<String>` is a Product and the second `<String>` is a SKU.
## Display license counts
```
gam show licenses
[(products|product <ProductIDList>)|(skus|sku <SKUIDList>)|allskus|gsuite]
[maxresults <Integer>]
```
By default, license counts are displayed for all Google products; use these options to select which products/SKU license counts to display:
* `products|product <ProductIDList>` - Select specific products
* `skus|sku <SKUIDList>` - Select specific SKUs
* `allskus` - Select all Google product SKUs
* `gsuite` - Select Google Workspace products: Google-Apps and 101031
By default, GAM asks the API for `license_max_results` from `gam.cfg` licenses per page of results,
* `maxresults` - Maximum number of results per page; range is 100-1000; the default is 100.
## Display licenses
```
gam print licenses [todrive <ToDriveAttributes>*]
[(products|product <ProductIDList>)|(skus|sku <SKUIDList>)|allskus|gsuite]
[maxresults <Integer>]
[countsonly]
```
By default, licenses are displayed for all Google products; use these options to select which products/SKU licenses to display:
* `products|product <ProductIDList>` - Select specific products
* `skus|sku <SKUIDList>` - Select specific SKUs
* `allskus` - Select all Google product SKUs
* `gsuite` - Select Google Workspace products: Google-Apps and 101031
By default, users and their licenses are displayed; use the `countsonly` option to only display total license counts.
By default, GAM asks the API for `license_max_results` from `gam.cfg` licenses per page of results,
* `maxresults` - Maximum number of results per page; range is 100-1000; the default is 100.
## Add licenses
```
gam <UserTypeEntity> add license <SKUIDList> [product|productid <ProductID>]
[preview] [actioncsv]
```
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `user,productId,skuId,action,message` is generated
that shows the actions performed when adding the licenses.
## Update licenses
```
gam <UserTypeEntity> update license <SKUID> [product|productid <ProductID>] [from] <SKUID>
[preview] [actioncsv]
```
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `user,productId,oldskuId,skuId,action,message` is generated
that shows the actions performed when updating the licenses.
## Delete licenses
```
gam <UserTypeEntity> delete|del license <SKUIDList> [product|productid <ProductID>]
[preview] [actioncsv]
```
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `user,productId,skuId,action,message` is generated
that shows the actions performed when deleting the licenses.
## Synchronize licenses
```
gam <UserTypeEntity> sync license <SKUIDList> [product|productid <ProductID>]
[addonly|removeonly] [allskus|onesku] [preview] [actioncsv]
```
* GAM determines which users currently hold a license for `<SKUID>`.
Default:
* The license will be deleted for all current license holders that are not in `<UserTypeEntity>`.
* The license will be added for all users in `<UserTypeEntity>` that are not current license holders.
When the `addonly` option is specified:
* The license will not be deleted for all current license holders that are not in `<UserTypeEntity>`.
* The license will be added for all users in `<UserTypeEntity>` that are not current license holders.
When the `removeonly` option is specified:
* The license will be deleted for all current license holders that are not in `<UserTypeEntity>`.
* The license will not be added for all users in `<UserTypeEntity>` that are not current license holders.
Option `allskus|onesku` is required when multiple SKUs are specified.
* `allskus` indicates that users in `<UserTypeEntity>` will be updated to have all of the SKUs in `<SKUIDList>`.
* This is typically used when assigning different types of licenses, such as an Enterprise license and a Voice license.
* `onesku` indicates that users in `<UserTypeEntity>` with none of the licenses in`<SKUIDList>` will be updated to have the first available license SKU in `<SKUIDList>`.
* This is typically used with Google Education Plus or Google Education Standard licenses, which are split across multiple SKUs.
If `preview` is specified, the changes will be previewed but not executed.
If `actioncsv` is specified, a CSV file with columns `user,productId,skuId,action,message` is generated
that shows the actions performed when adding and deleting the licenses.
### Example
Assign a Google Workspace for Education Plus license based on availability.
```
gam redirect csv ./LicenseUpdates.csv group_users all_google_eduplus_licenses@domain.edu recursive end sync licenses 1010310008,1010310010,1010310009 onesku actioncsv
```

113
docs/List-Items.md Normal file
View File

@ -0,0 +1,113 @@
# List Items
- [Lists of basic items](#lists-of-basic-items)
- [List quoting rules](#list-quoting-rules)
- [Basic Items](Basic-Items)
## Lists of basic items
```
<APIScopeURLList> ::= "<APIScopeURL>(,<APIScopeURL>)*"
<ASPIDList> ::= "<ASPID>(,<ASPID>)*"
<AssetTagList> ::= "<AssetTag>(,<AssetTag>)*"
<CalendarACLScopeList> ::= "<CalendarACLScope>(,<CalendarACLScope>)*"
<CalendarList> ::= "<CalendarItem>(,<CalendarItem>)*"
<ChatSpaceList> ::= "<ChatSpace>(,<ChatSpace>)*"
<CIGroupAliasList> ::= "<CIGroupAlias>(,<CIGroupAlias>)*"
<CIGroupTypeList> ::= "<CIGroupType>(,<CIGroupType>)*"
<ClassroomInvitationIDList> ::= "<ClassroomInvitationID>(,<ClassroomInvitationID>)*"
<ContactGroupList> ::= "<ContactGroupItem>(,<ContactGroupItem>)*"
<ContactIDList> ::= "<ContactID>(,<ContactID>)*"
<CourseAliasList> ::= "<CourseAlias>(,<CourseAlias>)*"
<CourseAnnouncementIDList> ::= "<CourseAnnouncementID>(,<CourseAnnouncementID>)*"
<CourseAnnouncementStateList> ::= all|"<CourseAnnouncementState>(,<CourseAnnouncementState>)*"
<CourseIDList> ::= "<CourseID>(,<CourseID>)*"
<CourseMaterialIDList> ::= "<CourseMaterialID>(,<CourseMaterialID>)*"
<CourseMaterialStateList> ::= all|"<CourseMaterialState>(,<CourseMaterialState>)*"
<CourseStateList> ::= all|"<CourseState>(,<CourseState>)*"
<CourseSubmissionIDList> ::= "<CourseSubmissionID>(,<CourseSubmissionID>)*"
<CourseSubmissionStateList> ::= all|"<CourseSubmissionState>(,<CourseSubmissionState>)*"
<CourseTopicIDList> ::= "<CourseTopicID>(,<CourseTopicID>)*"
<CourseTopicList> ::= "<CourseTopic>(,<CourseTopic>)*"
<CourseWorkIDList> ::= "<CourseWorkID>(,<CourseWorkID>)*"
<CourseWorkStateList> ::= all|"<CourseWorkState>(,<CourseWorkState>)*"
<CrOSIDList> ::= "<CrOSID>(,<CrOSID>)*"
<DataStudioAssetIDList> ::= "<DataStudioAssetID>(,<DataStudioAssetID>)*"
<DataStudioPermissionList> ::= "<DataStudioPermission>(,<DataStudioPermission>)*"
<DeviceIDList> ::= "<DeviceID>(,<DeviceID>)*"
<DeviceUserList> ::= "<DeviceUserID>(,<DeviceUserID>)*"
<DomainNameList> ::= "<DomainName>(,<DomainName>)*"
<DriveFileACLRoleList> ::= "<DriveFileACLRole>(,<DriveFileACLRole>)*"
<DriveFileList> ::= "<DriveFileItem>(,<DriveFileItem>)*"
<DriveFilePermissionList> ::= "<DriveFilePermission>(,<DriveFilePermission>)*"
<DriveFilePermissionIDList> ::= "<DriveFilePermissionID>(,<DriveFilePermissionID>)*"
<DriveFileRevisionIDList> ::= "<DriveFileRevisionID>(,<DriveFileRevisionID>)*"
<DriveFolderIDList> ::= "<DriveFolderID>(,<DriveFolderID>)*"
<DriveFolderNameList> ::= "<DriveFolderName>(,<DriveFolderName>)*"
<DriveLabelIDList> ::= "<DriveLabelID>(,<DriveLabelID>)*"
<DriveLabelNameList> ::= "<DriveLabelName>(,<DriveLabelName>)*"
<DriveLabelFieldIDList> ::= "<DriveLabelFieldID>(,<DriveLabelFieldID>)*"
<DriveLabelSelectionIDList> ::= "<DriveLabelSelectionID>(,<DriveLabelSelectionID>)*"
<EmailAddressList> ::= "<EmailAddress>(,<EmailAddress>)*"
<EmailItemList> ::= "<EmailItem>(,<EmailItem>)*"
<EventIDList> ::= "<EventID>(,<EventID>)*"
<EventNameList> ::= "<EventName>(,<EventName>)*"
<ExportStatusList> ::= "<ExportStatus>(,<ExportStatus>)*"
<FeatureNameList> ::= "'<FeatureName>'(,'<FeatureName>')*"
<FieldNameList> ::= "<FieldName>(,<FieldName>)*"
<FileFormatList> ::= "<FileFormat>(,<FileFormat>)*"
<FilterIDList> ::= "<FilterID>(,<FilterID>)*"
<GuardianItemList> ::= "<GuardianItem>(,<GuardianItem>)*"
<GuardianInvitationIDList> ::= "<GuardianInvitationID>(,<GuardianInvitationID>)*"
<GroupList> ::= "<GroupItem>(,<GroupItem>)*"
<GroupRoleList> ::= "<GroupRole>(,<GroupRole>)*"
<GroupTypeList> ::= "<GroupType>(,<GroupType>)*"
<LabelIDList> ::= "<LabelID>(,<LabelID>)*"
<LabelNameList> ::= "'<LabelName>'(,'<LabelName>')*"
<LanguageList> ::= "<Language>(,<Language>)*"
<MatterItemList> ::= "<MatterItem>(,<MatterItem>)*"
<MatterStateList> ::= "<MatterState>(,<MatterState>)*"
<MessageIDList> ::= "<MessageID>(,<MessageID>)*"
<MimeTypeList> ::= "<MimeType>(,<MimeType>)*"
<NamespaceList> ::= "<Namespace>(,<Namespace>)*"
<NotesNameList> ::= "<NotesName>(,<NotesName>)*"
<OrgUnitList> ::= "<OrgUnitItem>(,<OrgUnitItem>)*"
<OtherContactsResourceNameList> ::= "<OtherContactsResourceName>(,<OtherContactsResourceName>)*"
<PeopleResourceNameList> ::= "<PeopleResourceName>(,<PeopleResourceName>)*"
<PrinterIDList> ::= "<PrinterID>(,<PrinterID>)*"
<ProductIDList> ::= "(<ProductID>|<SKUID>)(,<ProductID>|<SKUID>)*"
<ProjectIDList> ::= "<ProjectID>(,<ProjectID>)*"
<QueryBrowserList> ::= "<QueryBrowser>(,<QueryBrowser>)*"
<QueryCrOSList> ::= "<QueryCrOS>(,<QueryCrOS>)*"
<QueryDeviceList> ::= "<QueryDevice>(,<QueryDevice>)*"
<QueryMobileList> ::= "<QueryMobile>(,<QueryMobile>)*"
<QueryUserList> ::= "<QueryUser>(,<QueryUser>)*"
<ResourceIDList> ::= "<ResourceID>(,<ResourceID>)*"
<SchemaNameList> ::= "<SchemaName>(,<SchemaName>)*"
<SerialNumberList> ::= "<SerialNumber>(,<SerialNumber>)*"
<ServiceAccountKeyList> ::= "<ServiceAccountKey>(,<ServiceAccountKey>)*"
<SiteACLScopeList> ::= "<SiteACLScope>(,<SiteACLScope>)*"
<SiteList> ::= "<SiteItem>(,<SiteItem>)*"
<SKUIDList> ="<SKUID>(,<SKUID>)*"
<SMTPHeaderList> ::= "<SMTPDateHeader>|<SMTPHeader>(,<SMTPDateHeader>|<SMTPHeader>)*"
<SharedDriveACLRoleList> ::= "<SharedDriveACLRole>(,<SharedDriveACLRole>)*"
<SharedDriveIDList> ::= "<SharedDriveID>(,<SharedDriveID>)*"
<StringList> ::= "<String>(,<String>)*"
<TasklistIDList> ::= "<TasklistID>(,<TasklistID>)*"
<TasklistIDTaskIDList> ::= "<TasklistIDTaskID>(,<TasklistIDTaskID>)*"
<ThreadIDList> ::= "<ThreadID>(,<ThreadID>)*"
<TimeList> ::= "<Time>(,<Time>)*"
<UserList> ::= "<UserItem>(,<UserItem>)*"
```
## List quoting rules
Items in a list can be separated by commas or spaces; if an item itself contains a comma, a space or a single quote, special quoting must be used.
Typically, you will enclose the entire list in double quotes and quote each item in the list as detailed below.
- Items, separated by commas, without spaces, commas or single quotes in the items themselves
* ```"item,item,item"```
- Items, separated by spaces, without spaces, commas or single quotes in the items themselves
* ```"item item item"```
- Items, separated by commas, with spaces, commas or single quotes in the items themselves
* ```"'it em','it,em',\"it'em\""```
- Items, separated by spaces, with spaces, commas or single quotes in the items themselves
* ```"'it em' 'it,em' \"it'em\""```
Typical places where these rules apply are lists of OUs and Contact Groups.

10
docs/List.md Normal file
View File

@ -0,0 +1,10 @@
# List
The list command is used to verify collections of objects. See GamDataSelection.txt/
## Commands
```
gam list [todrive <ToDriveAttribute>*] <EntityList> [data <CrOSTypeEntity>|<UserTypeEntity> [delimiter <Character>]]
gam <CrOSTypeEntity>|<UserTypeEntity> list [todrive <ToDriveAttribute>*] [data <EntityList> [delimiter <Character>]]
```

View File

@ -0,0 +1,230 @@
# Meta Commands and File Redirection
- [GAM Configuration](gam.cfg)
- [Todrive](Todrive)
- [Introduction](#introduction)
- [Meta Commands](#meta-commands)
- [Select section](#select-section)
- [Display sections](#display-sections)
- [Select output filter section](#select-output-filter-section)
- [Select input filter section](#select-input-filter-section)
- [Set configuration variables](#set-configuration-variables)
- [Specify multiprocessing termination return code](#specify-multiprocessing-termination-return-code)
- [File Redirection](#file-redirection)
## Introduction
Meta commands are used to configure GAM operation. File redirection is used to intelligently redirect output from GAM: CSV data, stdout and stderr.
The meta commands and file redirection must come before all other arguments and in this order, ... indicates that additional GAM arguments may appear.
```
gam [<Select>] [showsections] [<SelectOutputFilter>|<SelectInputFilter>] [<Config>] [<MultiprocessExit>] [<Redirect>] ...
```
## Meta Commands
### Select section
Select a section from gam.cfg and process a GAM command using values from that section.
```
<Select> ::=
select <Section> [save] [verify]
```
- `save`
- Set `section = <Section>` in the `[DEFAULT]` section and write configuration data to gam.cfg
- `verify`
- Print the variable values for the selected section
- Values are determined in this order: Selected section, DEFAULT section, Program default
### Display sections
Display all of the sections in gam.cfg and mark the currently selected section with a *.
```
showsections
```
### Select output filter section
Select an output filter section from gam.cfg and process a GAM command using values from that section.
```
<SelectOutputFilter> ::=
selectfilter|selectoutputfilter <Section>
```
The only `<VariableNames>` recognized in this `<Section>` are:
* `csv_output_header_filter`
* `csv_output_header_drop_filter`
* `csv_output_header_force`
* `csv_output_row_filter`
* `csv_output_row_filter_mode`
* `csv_output_row_drop_filter`
* `csv_output_row_drop_filter_mode`
* `csv_output_row_limit`
### Select input filter section
Select an input filter section from gam.cfg and process a GAM command using values from that section.
```
<SelectInputFilter> ::=
selectinputfilter <Section>
```
The only `<VariableNames>` recognized in this `<Section>` are:
* `csv_input_row_filter`
* `csv_input_row_filter_mode`
* `csv_input_row_drop_filter`
* `csv_input_row_drop_filter_mode`
* `csv_input_row_limit`
### Set configuration variables
Set variables in gam.cfg.
```
<Config> ::=
config (<VariableName> [=] <Value>)* [save] [verify]
```
- `<VariableName> [=] <Value>`
- Set `<VariableName> = <Value>` in the current section
- All `<VariableNames>` except section are allowed.
- The `=` is optional but must be surrounded by spaces if included.
- `save`
- Write configuration data to gam.cfg
- `verify`
- Print the variable values for the current section
- Values are determined in this order: Current section, DEFAULT section, Program default
You can prefix `<Config>` with `<Select>` to set a variable in a particular section.
* `select default <Config>` - Set a variable in the `DEFAULT` section
* `select xyz <Config>` - Set a variable in the `xyz` section
### Specify multiprocessing termination return code
Terminate processing of a CSV or batch file when one of the subprocesses returns a matching return code.
```
<Operator> ::= <|<=|>=|>|=|!=
<ReturnCodeSelection> ::=
rc<Operator><Number>|
rcrange=<Number>/<Number>|
rcrange!=<Number>/<Number>
<MultiProcessExit> :=
multiprocessexit <ReturnCodeSelection>
```
## File Redirection
You can redirect CSV file output and stdout/stderr output to files. By using redirect, you have more control over the output from GAM.
You can redirect stdout and stderr to null and stderr can be redirected to stdout.
```
<Redirect> ::=
redirect csv <FileName> [multiprocess] [append] [noheader] [charset <Charset>]
[columndelimiter <Character>] [quotechar <Character>]
[timestampcolumn <String>]
[todrive <ToDriveAttribute>*] |
redirect stdout <FileName> [multiprocess] [append] |
redirect stdout null [multiprocess] |
redirect stderr <FileName> [multiprocess] [append] |
redirect stderr null [multiprocess] |
redirect stderr stdout [multiprocess]
```
For `redirect`, the optional subarguments must appear in the order shown.
If `<FileName>` specifies a relative path, the file will be put in the directory specified by `drive_dir` in gam.cfg.
If `<FileName>` specifies an absolute path, the file will be put in the directory specified.
Specify `./<FileName>` to put the file in your current working directory.
The `multiprocess` subargument allows the multiple subprocesses started by `gam csv` to write intelligently
to a single redirected CSV/stdout/stderr file. If you don't specify `multiprocess`, each subprocess
writes `<FileName>` independently; you end up with a single file written by the last subprocess.
For `redirect csv`, if you don't specify `multiprocess` and do specify `todrive`, each subprocess uploads a separate Google sheet.
The `append` subargument causes GAM to append data to `<FileName>` rather that rewriting the file.
The `noheader` subargument causes GAM to suppress writing a CSV file header. This might be used when you are running
several GAM commands that output the same CSV columns but want all of the data in a single file; the second and
subsequent GAM commands specify `append noheader`.
The `charset <Charset>` subargument sets the character set of the CSV file; the default is the value of `charset`
in `gam.cfg` which defaults to UTF-8.
The `columndelimiter <Character>` sets the intercolumn delimiter of the CSV file; the default value
is the value of csv_output_column_delimiter` in `gam.cfg` which defaults to comma.
The `quotechar <Character>` subargument sets the character used to quote fields in the CSV file
that contaim special charactere; the default value is the value of `csv_output_quote_char` in `gam.cfg`
which defaults to double quote.
The `timestampcolumn <String>` adds a column named `<String>` to the CSV file; the value is the
timestamp of when the GAM command started.
If you are doing `redirect csv <FileName> multiprocess`, it is more efficient to specify `todrive <ToDriveAttribute>*` as part of
the redirect as verification of the `todrive` settings, which can involve several API calls, is done once rather than in each of the subprocesses.
By setting `<FileName>` to `-`, you can redirect to stdout/stderr rather than a file; this is typically used when `multiprocess` is specified.
* `redirect csv - multiprocess` - Send CSV output to stdout; intelligently aggregate data by process
* `redirect stdout - multiprocess` - Send normal output stdout; intelligently aggregate data by process
* `redirect stderr - multiprocess` - Send `getting` messages and error messages to stderr; intelligently aggregate data by process
If the pattern `{{Section}}` appears in `<FileName>`, it will be replaced with the name of the current section of gam.cfg.
### Examples - redirect CSV
Suppose that you have a CSV file CourseList.csv with a column labeled CourseId that contains course Ids. You want a single CSV file with participant information for these courses.
```
gam redirect csv ./CourseInfo.csv multiprocess csv CourseList.csv gam print course-participants course ~CourseId
```
`redirect csv ./CourseInfo.csv multiprocess` causes gam to collect output from all of the processes started by `csv CourseList.csv gam print course-participants course ~CourseId` and produces a single CSV file CourseInfo.csv.
Generate a list of CrOS devices and update an existing sheet in a Google spreadsheet. The file ID and sheet IDs are preserved so other appplications can access the data using the file ID and sheet ID.
By setting 'tdtimestamp true`, the file name will the updated to reflect the time of execution, but the file ID will not change.
```
gam redirect csv - todrive tdtitle "CrOS" tdtimestamp true tdfileid 12345-mizZ6Q2vP1rcHQH3tAZQt_NVB2EOxmS2SU3yM tdsheet id:0 tdupdatesheet true print cros fields deviceId,notes,orgUnitPath,serialNumber,osversion
```
For a collection of users, generate a list of files shared with anyone; combine the output for all users into a single file.
```
gam redirect csv - multiprocess todrive tdtitle AnyoneShares-All csv Users.csv gam user ~primaryEmail print filelist fields id,name,permissions pm type anyone em
```
For a collection of users, generate a list of files shared with anyone; generate a separate file for each user.
The two forms of the command are equivalent.
```
gam csv Users.csv gam redirect csv - todrive tdtitle "AnyoneShares-~~primaryEmail~~" user ~primaryEmail print filelist fields id,name,permissions pm type anyone em
gam csv Users.csv gam user ~primaryEmail print filelist fields id,name,permissions pm type anyone em todrive tdtitle "AnyoneShares-~~primaryEmail~~"
```
### Examples - Redirect stdout
The output from each of the `gam info user ~primaryEmail` commands will be combined into the single file Users.txt.
The value of `show_multiprocess_info` from `gam.cfg` controls whether information identifying the processes is also shown.
```
$ gam config show_multiprocess_info false redirect stdout ./Users.txt multiprocess csv Users.csv gam info user ~primaryEmail
$ more Users.txt
User: testuser1@domain.com (1/1)
Settings:
First Name: Test
Last Name: User1
Full Name: Test User1
...
User: testuser2@domain.com@ (1/1)
Settings:
First Name: Test
Last Name: User2
Full Name: Test User2
...
$ gam config show_multiprocess_info true redirect stdout ./Users.txt multiprocess csv Users.csv gam info user ~primaryEmail
$ more Users.txt
stdout: 0, Start: 2017-01-26T11:35:00.897773-08:00, RC: 0, Cmd: /Users/admin/gam config show_multiprocess_info true redirect stdout ./Users.txt multiprocess csv Users.csv gam info user ~primaryEmail
stdout: 1, Start: 2017-01-26T11:35:00.902709-08:00, RC: 0, Cmd: gam info user testuser1@domain.com
User: testuser1@domain.com (1/1)
Settings:
First Name: Test
Last Name: User1
Full Name: Test User1
...
stdout: 1, End: 2017-01-26T11:35:02.656837-08:00, RC: 0, Cmd: gam info user testuser1@domain.com
stdout: 2, Start: 2017-01-26T11:35:00.910729-08:00, RC: 0, Cmd: gam info user testuser2@domain.com
User: testuser2@domain.com@ (1/1)
Settings:
First Name: Test
Last Name: User2
Full Name: Test User2
...
stdout: 2, End: 2017-01-26T11:35:02.849646-08:00, RC: 0, Cmd: gam info user testuser2@domain.com
stdout: 0, End: 2017-01-26T11:35:02.907141-08:00, RC: 0, Cmd: /Users/admin/gam config show_multiprocess_info true redirect stdout ./Users.txt multiprocess csv Users.csv gam info user ~primaryEmail
```

152
docs/Mobile-Devices.md Normal file
View File

@ -0,0 +1,152 @@
# Mobile Devices
- [API documentation](#api-documentation)
- [Query documentation](#query-documentation)
- [Definitions](#definitions)
- [Manage mobile devices](#manage-mobile-devices)
- [Display mobile devices](#display-mobile-devices)
- [Print mobile devices](#print-mobile-devices)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/mobiledevices
## Query documentation
* https://developers.google.com/admin-sdk/directory/v1/search-operators
* https://support.google.com/a/answer/7549103
## Definitions
```
<QueryMobile> ::= <String>
See: https://support.google.com/a/answer/7549103
<QueryMobileList> ::= "<QueryMobile>(,<QueryMobile>)*"
<ResourceID> ::= <String>
<ResourceIDList> ::= "<ResourceID>(,<ResourceID>)*"
<MobileEntity> ::=
<ResourceIDList> |
(query:<QueryMobile>)|(query <QueryMobile>)
<MobileAction> ::=
admin_remote_wipe|wipe|
admin_account_wipe|accountwipe|wipeaccount|
approve|
block|
cancel_remote_wipe_then_activate|
cancel_remote_wipe_then_block)
<MobileFieldName> ::=
adbstatus|
applications|
basebandversion|
bootloaderversion|
brand|
buildnumber|
defaultlanguage|
developeroptionsstatus|
devicecompromisedstatus|
deviceid|
devicepasswordstatus|
email|
encryptionstatus|
firstsync|
hardware|
hardwareid|
imei|
kernelversion|
lastsync|
managedaccountisonownerprofile|
manufacturer|
meid|
model|
name|
networkoperator|
os|
otheraccountsinfo|
privilege|
releaseversion|
resourceid|
securitypatchlevel|
serialnumber|
status|
supportsworkprofile|
type|
unknownsourcesstatus|
useragent|
wifimacaddress
<MobileFieldNameList> ::= "<MobileFieldName>(,<MobileFieldName>)*"
<MobileOrderByFieldName> ::=
deviceid|email|lastsync|model|name|os|status|type
```
## Manage mobile devices
```
gam update mobile <MobileEntity> action <MobileAction>
[doit] [matchusers <UserTypeEntity>]
gam delete mobile <MobileEntity>
[doit] [matchusers <UserTypeEntity>]
```
If `<MobileEntity>` uses a query, the `doit` option must be used to enable execution.
The `matchusers <UserTypeEntity>` option disables execution on devices that don't have
have an email address contained in that list.
## Display mobile devices
```
gam info mobile <MobileEntity>
[basic|full|allfields] <MobileFieldName>* [fields <MobileFieldNameList>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
## Print mobile devices
```
gam print mobile [todrive <ToDriveAttribute>*]
[(query <QueryMobile>)|(queries <QueryMobileList>) (querytime.* <Time>)*]
[orderby <MobileOrderByFieldName> [ascending|descending]]
[basic|full|allfields] <MobileFieldName>* [fields <MobileFieldNameList>]
[delimiter <Character>] [appslimit <Number>] [oneappperrow] [listlimit <Number>]
[formatjson [quotechar <Character>]]
```
The `email`, `name` and `otheraccountsinfo` fields can have multiple values; the `listlimit` argument controls how these fields are displayed.
* `listlimit -1` - print no values for the field
* `listlimit 0` - print all values for the field
* `listlimit 1` - print one value for the field, default
* `listlinit N` - print the first N values for the field
The `applications` field can have multiple values; the `appslimit` argument controls how this field is displayed.
* `appslimit -1` - print no values for the field, default
* `appslimit 0` - print all values for the field
* `appslinit N` - print the first N values for the field
For a device with many applications, displaying all of the applications on one row can make an excessively long field;
use the `oneappperrow` option to have each application be displayed on a separate row with all of the other mobile device fields.
Use the `querytime<String> <Time>` option to allow times, usually relative, to be substituted into the `query <QueryMobile>` option.
The `querytime<String> <Time>` value replaces the string `#querytime<String>#` in any queries.
The characters following `querytime` can be any combination of lowercase letters and numbers. This is most useful in scripts
where you can specify a relative date without having to change the script.
For example, query for mobile devices synced more that 30 days ago.
```
gam print mobile fields querytime30d -30d query "sync:..#querytime30d#"
```
To AND query terms, put all of your terms in one query:
```
gam print mobile query "manufacturer:Meizu os:Android 7.0.0"
```
To OR query terms, put the terms im multiple queries:
```
gam print mobile queries "'model:iPhone 6','model:samsung'"
```
`delimiter` - The items in the `applications`, `email`, `name` and `otheraccountsinfo` fields are separated by `delimiter`, it defaults to the value of `csv_output_field_delimiter` in `gam.cfg`.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,251 @@
# Organizational Units
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Special quoting](#special-quoting)
- [Manage organizational units](#manage-organizational-units)
- [Add users to an organizational unit](#add-users-to-an-organizational-unit)
- [Synchronize users with an organizational unit](#synchronize-users-with-an-organizational-unit)
- [ChromeOS device update OU error handling](#chromeos-device-update-ou-error-handling)
- [Add ChromeOS devices to an organizational unit](#add-chromeos-devices-to-an-organizational-unit)
- [Example: Move CrOS devices from one OU to another](#example-move-cros-devices-from-one-ou-to-another)
- [Example: Add ChromeOS devices to a single OU](#example-add-chromeos-devices-to-a-single-ou)
- [Example: Add ChromeOS devices to multiple OUs](#example-add-chromeos-devices-to-multiple-ous)
- [Synchronize ChromeOS devices with an organizational unit](#synchronize-chromeos-devices-with-an-organizational-unit)
- [Display organizational units](#display-organizational-units)
- [Print organizational units](#print-organizational-units)
- [Display indented organizational unit tree](#display-indented-organizational-unit-tree)
- [Special case handling for large number of organizational units](#special-case-handling-for-large-number-of-organizational-units)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/orgunits
## Definitions
```
<OrgUnitID> ::= id:<String>
<OrgUnitPath> ::= /|(/<String)+
<OrgUnitItem> ::= <OrgUnitID>|<OrgUnitPath>
<OrgUnitList> ::= "<OrgUnitItem>(,<OrgUnitItem>)*"
<OrgUnitFieldName> ::=
description|
id|orgunitid|
inherit|blockinheritance|
name|
parentid|parentorgunitid|
parent|parentorgunitpath|
path|orgunitpath
<OrgUnitFieldNameList> ::= "<OrgUnitFieldName>(,<OrgUnitFieldName>)*"
<OrgUnitSelector> ::=
cros_ou | cros_ou_and_children|
ou | ou_ns | ou_susp|
ou_and_children | ou_and_children_ns | ou_and_children_susp
```
For `<OrgUnitEntity>`, see: [Collections of Items](Collections-of-Items)
For `<UserTypeEntity>`, see: [Collections of Users](Collections-Of-Users)
For `<CrOSTypeEntity>`, see: [Collections of ChromeOS Devices](Collections-of-ChromeOS-Devices)
## Special quoting
You specify a single organizational unit with `org <OrgUnitPath>` and a list of organizationsl units with `orgs <OrgUnitList>`.
As organizational unit paths can contain spaces, some care must be used when entering `<OrgUnitPath>` and `<OrgUnitList>`.
Suppose you have an organizational unit `/Foo Bar`. To get information about it you enter the command: `gam info org "/Foo Bar"`
The shell strips the `"` leaving a single argument `/Foo Bar`; gam correctly processes the argument.
Suppose you enter the command: `gam info orgs "/Foo Bar"`
The shell strips the `"` leaving a single argument `/Foo Bar`; gam splits the argument on space leaving two items and then tries to process `/Foo` and `Bar`, not what you want.
You must enter: `gam info orgs "'/Foo Bar'"`
The shell strips the `"` leaving a single argument `'/Foo Bar'`; gam splits the argument on space while honoring the `'` leaving one item `/Foo Bar` and correctly processes the item.
See: [List Items](List-Items)
## Manage organizational units
Create, update and delete organization units.
```
gam create org|ou <OrgUnitPath> [description <String>]
[parent <OrgUnitItem>] [inherit|noinherit|(blockinheritance <Boolean>)]
[buildpath]
gam update org|ou <OrgUnitPath> [name <String>] [description <String>]
[parent <OrgUnitItem>] [inherit|noinherit|(blockinheritance <Boolean>)]
gam delete org|ou <OrgUnitPath>
gam update orgs|ous <OrgUnitEntity> [name <String>] [description <String>]
[parent <OrgUnitItem>] [inherit|noinherit|(blockinheritance <Boolean>)]
gam delete orgs|ous <OrgUnitEntity>
```
## Add users to an organizational unit
When adding users to an OU, Gam uses a batch method to speed up processing.
For `<UserTypeEntity>`, see: [Collections of Users](Collections-Of-Users)
```
gam update org|ou <OrgUnitPath> add|move <UserTypeEntity>
gam update orgs|ous <OrgUnitEntity> add|move <UserTypeEntity>
```
The `batch_size` value from gam.cfg controls the number of users handled in each batch.
## Synchronize users with an organizational unit
When adding users to an OU, Gam uses a batch method to speed up processing.
For `<UserTypeEntity>`, see: [Collections of Users](Collections-Of-Users)
```
gam update org|ou <OrgUnitItem> sync <UserTypeEntity> [removetoou <OrgUnitItem>]
gam update orgs|ous <OrgUnitEntity> sync <UserTypeEntity> [removetoou <OrgUnitItem>]
```
* Users in the `OU` but not in `<UserTypeEntity>` will be moved to `OU` / or the `OU` specified in `removetoou <OrgUnitItem>`
* Users in `<UserTypeEntity>` but not in the `OU` are moved to the `OU`
* Users in the `OU` and in `<UserTypeEntity>` are unaffected
The `batch_size` value from gam.cfg controls the number of users handled in each batch.
## ChromeOS device update OU error handling
If you get the following error when trying to update the OU of a ChromeOS device:
```
400: invalidInput - Invalid Input: Inconsistent Orgunit id and path in request
```
issue the following command to work around the Google problem causing the wrror:
```
gam select default config update_cros_ou_with_id true save
```
## Add ChromeOS devices to an organizational unit
When adding ChromeOS devices to an OU, Gam uses a batch method to speed up processing.
For `<CrOSTypeEntity>`, see: [Collections of ChromeOS Devices](Collections-of-ChromeOS-Devices)
```
gam update org|ou <OrgUnitPath> add|move <CrOSTypeEntity>
[quickcrosmove [<Boolean>]]
gam update orgs|ous <OrgUnitEntity> add|move <CrOSTypeEntity>
[quickcrosmove [<Boolean>]]
```
Google has introduced a new, faster batch method for moving CrOS devices to a new OU. The `quickcrosmove` option controls which method Gam uses.
* `quickcrosmove not specified` - use value from `quick_cros_move` in `gam.cfg` to select previous/new batch method
* `quickcrosmove False` - use previous batch method
* `quickcrosmove True` - use new batch method
* `quickcrosmove` - use new batch method
The `batch_size` value from gam.cfg controls the number of deviceIds handled in each batch by either method.
In the new method, Google doesn't seem to do any error checking of the CrOS deviceIds, there is no error message
given if invalid CrOS deviceIds are specified.
### Example: Move CrOS devices from one OU to another
```
gam update ou /Students/2022 add cros_ou /Students/2021 quickcrosmove
```
### Example: Add ChromeOS devices to a single OU
Suppose you have a CSV file cros.csv with a single column: deviceId
```
gam update ou /Students/2022 add croscsvfile cros.csv:deviceId quickcrosmove
```
### Example: Add ChromeOS devices to multiple OUs
Suppose you have a CSV file cros.csv with a two columns: deviceId,OU
All OUs will be updated with their associated devices.
```
gam update ou csvkmd cros.csv keyfield OU datafield deviceId add croscsvdata deviceId quickcrosmove
```
## Synchronize ChromeOS devices with an organizational unit
When adding ChromeOS devices to an OU, Gam uses a batch method to speed up processing.
For `<CrOSTypeEntity>`, see: [Collections of ChromeOS Devices](Collections-of-ChromeOS-Devices)
```
gam update org|ou <OrgUnitItem> sync <CrOSTypeEntity> [removetoou <OrgUnitItem>]
[quickcrosmove [<Boolean>]]
gam update orgs|ous <OrgUnitEntity> sync <CrOSTypeEntity> [removetoou <OrgUnitItem>]
[quickcrosmove [<Boolean>]]
```
* Cros devices in the `OU` but not in `<CrOSTypeEntity>` will be moved to `OU` / or the `OU` specified in removetoou <OrgUnitItem>
* CrOS devices in `<CrOSTypeEntity>` but not in the `OU` are moved to the `OU`
* CrOS devices in the `OU` and in `<CrOSTypeEntity>` are unaffected
Google has introduced a new, faster batch method for moving CrOS devices to a new OU. The `quickcrosmove` option controls which method Gam uses.
* `quickcrosmove not specified` - use value from `quick_cros_move` in `gam.cfg` to select previous/new batch method
* `quickcrosmove False` - use previous batch method
* `quickcrosmove True` - use new batch method
* `quickcrosmove` - use new batch method
The `batch_size` value from gam.cfg controls the number of deviceIds handled in each batch by either method.
In the new method, Google doesn't seem to do any error checking of the CrOS deviceIds, there is no error message
given if invalid CrOS deviceIds are specified.
## Display organizational units
These commands display information as an indented list of keys and values.
```
gam info org|ou <OrgUnitPath> [nousers|notsuspended|suspended] [children|child]
gam info orgs|ous <OrgUnitEntity> [nousers|notsuspended|suspended] [children|child]
```
By default, all users of the org units are displayed:
* `nousers` - Don't display users of the org units
* `notsuspended` - Display non-suspended users of the org units
* `suspended` - Display suspended users of the org units
## Print organizational units
This command displays information in CSV format.
```
gam print orgs|ous [todrive <ToDriveAttribute>*]
[fromparent <OrgUnitItem>] [showparent [Boolean>]] [toplevelonly]
[parentselector <OrgUnitSelector> childselector <OrgUnitSelector>]
[allfields|<OrgUnitFieldName>*|(fields <OrgUnitFieldNameList>)]
[convertcrnl] [batchsuborgs [<Boolean>]]
[mincroscount <Number>] [maxcroscount <Number>]
[minusercount <Number>] [maxusercount <Number>]
```
By default, Gam prints all child org units of /.
* `fromparent <OrgUnitItem>` - Print all child org units of `<OrgUnitItem>`.
* `showparent` - Print the parent org unit, either / or `fromparent <OrgUnitItem>`.
* `toplevelonly` - Do not print any sub org units.
* `convertcrnl` - In the description field, convert carriage return to \r and new line to \n.
Options `parentselector <OrgUnitSelector>` and `childselector <OrgUnitSelector>` add an additional column `orgUnitSelector` to the output.
This column value can be used in subsequent `gam csv` commands to appropriateley select members without duplication.
By default, all OUs are displayed. You can limit the display of OUs to those where the number
of ChromeOS devices/users falls within a range. Gathering this data requires additional API calls
to download information about all ChromeOS devices and users.
Additional columns are generated to display the number and status of ChromeOS devices and users in each OU.
* `mincroscount <Number>` - Display the OU if it has at leaset `<Number>` ChromeOS devices
* `maxcroscount <Number>` - Display the OU if it has no more than `<Number>` ChromeOS devices
* `minusercount <Number>` - Display the OU if it has at leaset `<Number>` users
* `maxusercount <Number>` - Display the OU if it has no more than `<Number>` users
### Examples:
Show all OUs with at least one user.
```
gam print orgs minusercount 1
```
Show all OUs with no users.
```
gam print orgs maxusercount 0
```
Get file count summaries by OU; top level selector is ou, sub level selectors are ou_and_children
```
gam redirect csv ./TopLevelOUs.csv print ous showparent toplevelonly parentselector ou childselector ou_and_children fields orgunitpath
gam redirect csv ./FileCounts.csv multiprocess csv ./TopLevelOUs.csv gam "~orgUnitSelector" "~orgUnitPath" print filecounts excludetrashed summary only summaryuser "~orgUnitPath"
```
## Display indented organizational unit tree
```
gam show orgtree [fromparent <OrgUnitItem>] [batchsuborgs [<Boolean>]]
```
By default, Gam displays the organizational unit tree starting at /.
* `fromparent <OrgUnitItem>` - Display the organizational unit tree starting at `<OrgUnitItem>`.
## Special case handling for large number of organizational units
By default, the `print orgs` and `show orgtree` commands issue a single API call to get the
list of organizational units. If the number is large, greater than 5000 in an observed case, the API call may fail.
When `batchsuborgs` is specified, Gam gets all of the top level org units with one API call; then Gam uses batch processing
in subsequent API calls to get the sub org units. There is no benefit to using this option unless the commands fail
without it. The number of sub org units processed in each batch is controlled by `batch_size` in `gam.cfg`.

13
docs/Other-Resources.md Normal file
View File

@ -0,0 +1,13 @@
# Other Resources
The following are links to contributions of others in support of GAMADV-XTD3.
Thank you.
* Gabriel Clifton - https://docs.google.com/document/d/1p32QOBTr89GaG7RfCafSbFuhlUQ9r3qBM_666E0xvQM/edit
* Steve Larsen - https://docs.google.com/spreadsheets/d/1MzzA-u-cmoQcJnQOovCnZcEKMjvOyFhfkdFdf10X_GI/edit
* Kevin Melillo - https://github.com/KevinMelilloIEEE/gam-script
* James Seymour - https://sites.google.com/jis.edu.bn/gam-commands/home
* Amado Tejada - https://github.com/amadotejada/GAMpass
* Workspace Admins YouTube Channel - https://youtube.com/@googleworkspaceadmins
* Goldy Arora - https://www.goldyarora.com/license-notifier/

161
docs/Permission-Matches.md Normal file
View File

@ -0,0 +1,161 @@
# Permission Matches
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [File Selection](#file-selection)
- [Permission Selection](#permission-selection)
- [Define a Match](#define-a-match)
- [File Selection Examples](#file-selection-examples)
- [Permission Selection Examples](#permission-selection-examples)
## Definitions
```
<DomainName> ::= <String>(.<String>)+
<DomainNameList> ::= "<DomainName>(,<DomainName>)*"
<DriveFileACLRole> ::=
commenter|
contentmanager|fileorganizer|
contributor|editor|writer|
manager|organizer|owner|
reader|viewer
<DriveFileACLType> ::= anyone|domain|group|user
<EmailAddress> ::= <String>@<DomainName>
<EmailAddressList> ::= "<EmailAddress>(,<EmailAddress>)*"
<Time> ::=
<Year>-<Month>-<Day>(<Space>|T)<Hour>:<Minute>:<Second>[.<MilliSeconds>](Z|(+|-(<Hour>:<Minute>))) |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
<PermissionMatch> ::=
pm|permissionmatch [not]
[type <DriveFileACLType>] [role|notrole <DriveFileACLRole>]
[allowfilediscovery|withlink <Boolean>]
[emailaddress <RegularExpression>] [emailaddressList <EmailAddressList>]
[name|displayname <String>]
[domain|notdomain <RegularExpression>] [domainlist|notdomainlist <DomainNameList>]
[expirationstart <Time>] [expirationend <Time>]
[deleted <Boolean>] [inherited <Boolean>]
em|endmatch
<PermissionMatchMode> ::=
pmm|permissionmatchmode or|and
<PermissionMatchAction> ::=
pma|permissionmatchaction process|skip
```
## File Selection
In the `print/show filecounts/filelists/filetree` commands you can limit the files counted/displayed by specifying permissions
that the file must/must not have. Permission matching is expensive on Shared Drives as retrieving the permissions requires a separate API call per file.
You can define multiple `<PermissionMatches>`; each match specifies a set of required fields/values. A permission
matches if all of its fields/values match the required fields/values; you can negate the match with `not`.
### Permission Match Mode
When you specify multiple `<PermissionMatches>`, `<PermissionMatchMode>` controls whether there is a permissions match
when any or all or the `<PermissionMatches>` match.
* `pmm or` - If any `<PermissionMatch>` matches, then there is a permissions match. This is the default.
* `pmm and` - If all `<PermissionMatches>` match, then there is a permissions match.
### Permission Match Action
`<PermissionMatchAction>` controls processing when there is a permissions match.
* `pma process` - If there is a permissions match, count/display the file. This is the default.
* `pma skip` - If there is a permissions match, do not count/display the file.
## Permission Selection
In the `print/show drivefileacls` and `create/delete permissions` commands you can limit the permissions displayed/processed.
* `pma process` - If a permission matches, display/process the permission. This is the default.
* `pma skip` - If a permission matches, do not display/process the permission.
## Define a Match
* `pm|permissionmatch` - Start of permission match definition.
* `not` - Negate the match.
* `type <DriveFileACLType>` - The type of the grantee.
* `role <DriveFileACLRole>` - The role granted by this permission.
* `notrole <DriveFileACLRole>` - The role granted by this permission.
* `allowfilediscovery|withlink <Boolean>` - Whether a link is required or whether the file can be discovered through search.
* `emailaddress <RegularExpression>` - For types user and group, the required email address.
* `emailaddresslist <EmailAddressList>` - For types user and group, a list of required email addresses; any one of which must match.
* `name|displayname <RegularExpression>` - For types domain, user and group, the displayable name.
* `domain <RegularExpression>` - For type domain, the required domain name. For types user and group, the required domain name in the email address.
* `notdomain <RegularExpression>` - For type domain, any domain name that doesn't match. For types user and group, any domain name that doesn't match in the email address.
* `domainlist <DomainNameList>` - For type domain, the required domain name. For types user and group, the required domain name in the email address.
* `notdomainlist <DomainNameList>` - For type domain, any domain name that doesn't match. For types user and group, any domain name that doesn't match in the email address.
* `expirationstart <Time>` - For types user and group, will the permission expire on or after <Time>.
* `expirationend <Time>` - For types user and group, will the permission expire before or on <Time>.
* `deleted <Boolean>` - For types user and groups, has the user or group been deleted.
* `inherited <Boolean>` - For Shared Drive files/folders, is the permission inherited
* `em|endmatch` - End of permission match definition
## File Selection Examples
These are the permission match definitions that would be appended to a command like:
```
gam user user@domain.com print filelist ...
```
Process all files with permissions type anyone:
```
pm type anyone em
```
Process all files except those with permissions type anyone:
```
pm type anyone em
pma skip
```
Process all files owned by someout outside of your domain
```
pm type user role owner notdomain mydomain.com em
```
Process all files shared to users outside of your domains
```
pm type user notrole owner notdomainlist mydomain1.com,mydomain2.com em
```
Process all files with write access for group@domain.com or user@domain.com:
```
pm role writer type group emailaddress group@domain.com em
pm role writer type user emailaddress user@domain.com em
```
Process all files with write access for group@domain.com and user@domain.com:
```
pm role writer type group emailaddress group@domain.com em
pm role writer type user emailaddress user@domain.com em
pmm and
```
Process all files where neither user1@domain.com or user2@domain.com have access:
```
pm type user emailaddress user1@domain.com em
pm type user emailaddress user2@domain.com em
pma skip
```
or you can use regular expressions
```
pm type user emailaddress "user[1|2]@domain.com" em
pma skip
```
Process all files shared with group group@domain.com and not shared with user user@domain.com:
```
pm type group emailaddress group@domain.com em pm not type user user@domain.com em pmm and
```
Process all files shared with domain.com either directly or via a user or group.
```
pm domain domain.com em pm emailaddress ".*@domain.com" em
```
Display all non-inherited permissions on a Shared Drive.
```
pm inherited false em
```
## Permission Selection Examples
These are the permission match definitions that would be appended to a command like:
```
gam user user@domain.com print drivefileacls ...
```
Display all permissions shared with domain.com either directly or via a user or group.
```
pm domain domain.com em pm emailaddress ".*@domain.com" em
```

View File

@ -0,0 +1,216 @@
# Python Regular Expressions
- [Documentation](#documentation)
- [Match function](#match-function)
- [Sub function](#sub-function)
- [Search function](#search-function)
## Documentation
* https://docs.python.org/3/library/re.html
* https://www.regular-expressions.info/python.html
## Match function
When matching, Gam uses the match function which always looks for a match at the beginning of a string.
* "^Foo Bar$" - match the entire string "Foo Bar"
* "Foo Bar" - match a string that starts with "Foo Bar"
* ".*Foo Bar" - match a string that contains "Foo Bar"
* ".*Foo Bar$" - match a string that ends with "Foo Bar"
Select Aliases to display
```
gam print aliases [todrive <ToDriveAttribute>*]
[aliasmatchpattern <RegularExpression>]
```
Collections
```
matchfield|skipfield <FieldName> <RegularExpression>
keypattern <RegularExpression>
```
Display Classroom courses based on owner's email address
```
gam print courses [todrive <ToDriveAttribute>*]
[owneremailmatchpattern <RegularExpression>]
```
Clear Contacts based on email address
```
gam <UserTypeEntity> clear contacts
emailmatchpattern <RegularExpression>
emailclearpattern <RegularExpression>
```
Display Contacts based on email address
```
gam <UserTypeEntity> print contacts
emailmatchpattern <RegularExpression>
```
Delete Gmail labels based on label names
```
gam <UserTypeEntity> delete labels regex:<RegularExpression>
```
Display Gmail messages based on label names
```
gam <UserTypeEntity> print|show messages|threads
[labelmatchpattern <RegularExpression>
```
Display Gmail messages based on sender email address
```
gam <UserTypeEntity> print|show messages|threads
[sendermatchpattern <RegularExpression>]
<LabelName>|regex:<RegularExpression>
```
Display Gmail messages based on attachment names
```
gam <UserTypeEntity> print|show messages|threads
[showattachments [attachmentnamepattern <RegularExpression>]]
```
Save Gmail message attachments based on attachment names
```
gam <UserTypeEntity> show messages|threads
[saveattachments [attachmentnamepattern <RegularExpression>]]
```
Select Groups to display and which members to display
```
gam print groups
[emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
[descriptionmatchpattern [not] <RegularExpression>]
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
```
Select Groups to display membership and which members to display
```
gam print group-members
[emailmatchpattern [not] <RegularExpression>] [namematchpattern [not] <RegularExpression>]
[descriptionmatchpattern [not] <RegularExpression>]
[memberemaildisplaypattern|memberemailskippattern <RegularExpression>]
```
Manage Group membership
```
gam update group|groups <GroupEntity> clear [member] [manager] [owner]
[emailclearpattern|emailretainpattern <RegularExpression>]
```
Select User aliases to display
```
gam print users
[aliasmatchpattern <RegularExpression>]
```
Display Drive file information based on file names
```
gam <UserTypeEntity> print|show filecounts
[filenamematchpattern <RegularExpression>]
gam <UserTypeEntity> print filelist
[filenamematchpattern <RegularExpression>]
gam <UserTypeEntity> print|show filetree
[filenamematchpattern <RegularExpression>]
```
Update Drive file name based on a pattern
```
gam <UserTypeEntity> update drivefile <DriveFileEntity>
(replacefilename <RegularExpression> <String>)*
```
Select Vault exports to download
```
gam download vaultexport <ExportItem> matter <MatterItem>
[bucketmatchpattern <RegularExpression>] [objectmatchpattern <RegularExpression>]
```
## Sub function
When substituting, Gam uses the sub function which looks for a match anywhere in a string.
* "^Foo Bar$"` - match the entire string "Foo Bar"
* "^Foo Bar"` - match a string that starts with "Foo Bar"
* "Foo Bar"` - match a string that contains "Foo Bar"
* "Foo Bar$"` - match a string that ends with "Foo Bar"
Collections
```
keypattern <RegularExpression> keyvalue <String>
```
Updating Calendar event descriptions uses the search function which looks for a match anywhere in a string.
```
gam calendars <CalendarEntity> update events [<EventEntity>] replacedescription <RegularExpression> <String>
gam <UserTypeEntity> update events <UserCalendarEntity> [<EventEntity>] replacedescription <RegularExpression> <String>
```
Updating Drive file names uses the search function which looks for a match anywhere in a string.
```
gam <UserTypeEntity> update drivefile <DriveFileEntity>
replacefilename <RegularExpression> <String>
replacefilename "^(.+) (.+)$" "\2 \1" - swap the two words separated by space, e.g. "Foo Bar" becomes "Bar Foo"
```
Updating Gmail label names uses the search function which looks for a match anywhere in a string.
```
gam <UserTypeEntity> update label
search <RegularExpression> replace <LabelReplacement>
search "^Foo Bar$" replace "Doodle" - replace the entire string "Foo Bar" with "Doodle"
```
Updating User primary email addresses uses the search function which looks for a match anywhere in a string.
```
gam <UserTypeEntity> update user
updateprimaryemail <RegularExpression> <EmailReplacement>
updateprimaryemail "^(.).*_(.+)@(.+)$" <\1\2@\3> - replace "first_last@domain.com" with "flast@domain.com"
```
## Search function
When searching, Gam uses the search function which always looks for a match anywhere in a string.
* "^Foo Bar$"` - match the entire string "Foo Bar"
* "^Foo Bar"` - match a string that starts with "Foo Bar"
* "Foo Bar"` - match a string that contains "Foo Bar"
* "Foo Bar$"` - match a string that ends with "Foo Bar"
CSV input and output row filtering use the search function which looks for a match anywhere in a string.
```
<FieldNameFilter> :: = <RegularExpression>
<RowValueFilter> ::=
[(any|all):]regex:<RegularExpression>|
[(any|all):]regexcs:<RegularExpression>|
[(any|all):]notregex:<RegularExpression>|
[(any|all):]notregexcs:<RegularExpression>
```
Calendar event matchfields use the search function which looks for a match anywhere in a string.
```
<EventMatchProperty> ::=
(matchfield attendees <EmailAddressEntity>)|
(matchfield attendeespattern <RegularExpression>)|
(matchfield attendeesstatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddressEntity>)|
(matchfield creatoremail <RegularExpression>)|
(matchfield creatorname <RegularExpression>)|
(matchfield description <RegularExpression>)|
(matchfield location <RegularExpression>)|
(matchfield organizeremail <RegularExpression>)|
(matchfield organizername <RegularExpression>)|
(matchfield status <RegularExpression>)|
(matchfield summary <RegularExpression>)|
(matchfield transparency <RegularExpression>)|
(matchfield visibility <RegularExpression>)
<EventSelectEntity> ::=
(<EventSelectProperty>+ <EventMatchProperty>*)
```
Updating user primary email addresses uses the search function which looks for a match anywhere in a string.
```
gam <UserTypeEntity> update user <UserAttribute>* updateprimaryemail <RegularExpression> <EmailReplacement>
```

38
docs/Rclone.md Normal file
View File

@ -0,0 +1,38 @@
# Rclone
GAMADV-XTD3 has the capability to upload and download single files between your local computer and Google Drive;
it has no capability for uploading and dowloading folders. For this you can use Rclone: https://rclone.org/
## Authorization
Rclone uses client and service account access to perform its operations; you can use your existing GAMADV-XTD3
authorization for Rclone, you don't need to create a new project or service account within your project.
You can use your Client ID and Client Secret from `client_secrets.json` and you can use your `oauth2service.json` file with rclone.
```
Google Application Client Id
client_id>
Google Application Client Secret
client_secret>
Scope that rclone should use when requesting access from drive.
Choose a number from below, or type in your own value
1 / Full access all files, excluding Application Data Folder.
\ "drive"
2 / Read-only access to file metadata and file contents.
\ "drive.readonly"
/ Access to files created by rclone only.
3 | These are visible in the drive website.
| File authorization is revoked when the user deauthorizes the app.
\ "drive.file"
/ Allows read and write access to the Application Data folder.
4 | This is not visible in the drive website.
\ "drive.appfolder"
/ Allows read-only access to file metadata but
5 | does not allow any access to read or download file content.
\ "drive.metadata.readonly"
scope> 1
Service Account Credentials JSON file path
service_account_file>

398
docs/Reports.md Normal file
View File

@ -0,0 +1,398 @@
# Reports
- [API documentation](#api-documentation)
- [Collections of Users](Collections-of-Users)
- [Definitions](#definitions)
- [Activity reports](#activity-reports)
- [Customer and user reports parameters](#customer-and-user-reports-parameters)
- [Customer usage reports](#customer-usage-reports)
- [Customer reports](#customer-reports)
- [User usage reports](#user-usage-reports)
- [User reports](#user-reports)
## API documentation
* https://developers.google.com/admin-sdk/reports/v1/reference/activities
* https://developers.google.com/admin-sdk/reports/v1/reference/customerUsageReports
* https://developers.google.com/admin-sdk/reports/v1/reference/userUsageReport
## Definitions
```
<DayOfWeek> ::= mon|tue|wed|thu|fri|sat|sun
<Time> ::=
<Year>-<Month>-<Day>(<Space>|T)<Hour>:<Minute>:<Second>[.<MilliSeconds>](Z|(+|-(<Hour>:<Minute>))) |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
```
## Activity reports
```
<ActivityApplicationName> ::=
access|accesstransparency|
admin|
calendar|calendars|
chat|
chrome|
contextawareaccess|
currents|gplus|google+|
datastudio|
devices|mobile|
domain|
drive|doc|docs|
gcp|
groups|group|
groupsenterprise|enterprisegroups|
jamboard|
keep|
login|logins|
meet|hangoutsmeet|
mobile|devices|
rules|
saml|
token|tokens|oauthtoken|
useraccounts
gam report <ActivityApplicationName> [todrive <ToDriveAttributes>*]
[(user all|<UserItem>)|(orgunit|org|ou <OrgUnitPath> [showorgunit])|(select <UserTypeEntity>)]
[([start <Time>] [end <Time>])|(range <Time> <Time>)|
yesterday|today|thismonth|(previousmonths <Integer>)]
[filtertime.* <Time>] [filter|filters <String>]
[event|events <EventNameList>] [ip <String>]
[groupidfilter <String>]
[maxactivities <Number>] [maxresults <Number>]
[countsonly [summary] [eventrowfilter]]
```
Select the application with `<ActivityApplicationName>`.
Select the users for whom information is desired.
* `user all` - All users, the default; there is one API call
* `user <UserItem>` - An individual user; there is one API call
* `orgunit|org|ou <OrgUnitPath>` - All users in the specified OU; there is one API call
* `showorgunit` - Add a column labelled `actor.orgUnitPath` to the output; an additional API call is made to get the email addresses of the users in `<OrgUnitPath>`
* `select <UserTypeEntity>` - A selected collection of users, e.g., `select group staff@domain.com`; there is one API call per user
Limit the time period.
* `start <Time>`
* `end <Time>`
* `range <Time> <Time>` - Equivalent to `start <Time> end <Time>`
* `yesterday` - Yesterday
* `today` - Today
* `thismonth` - The current calendar month up to the current time
* `previousmonths <Integer>` - A number in the range 1 to 6 indicating calendar months previous to the current month
Apply API filters.
* `filter|filters <String>` - `<String>` is a comma separated list of filter expressions.
Use the `filtertime.* <Time>` option to allow times, usually relative, to be substituted into the `filter <String>` option.
The characters following `filtertime` can be any combination of lowercase letters and numbers.
You can use `config csv_output_row_filter` to filter the events if the API filter can't produce the results you want.
Limit to a list of specific events.
* `event|events <EventNameList>`
Limit to a specific IP address.
* `ip <String>`
Limit to those users that are a member of at least one of a list of groups.
* `groupidfilter <String>` - Format: "id:abc123,id:xyz456"
Limit the total number of activites.
* `maxactivities <Number>`
Limit the number of activities downloaded per API call; infrequently used.
* `maxresults <Number>`
By default, individual event details are displayed, these options modify what's displayed.
* `countsonly` - Limit the display to the number of occurences of each event for each user
* `countsonly summary` - Limit the display to the number of occurences of each event summarized across all users
* `countsonly [summary] eventrowfilter` - Apply `config csv_output_row_filter` to the event details rather than the event counts
### Example
You're interested in files with extension `xyz` created yesterday.
Details for each file
```
gam config csv_output_row_filter "doc_title:regex:\.xyz" report drive event create yesterday
```
Number of files by each user
```
gam config csv_output_row_filter "doc_title:regex:\.xyz" report drive event create yesterday countsonly eventrowfilter
```
Number of files summarized across all users
```
gam config csv_output_row_filter "doc_title:regex:\.xyz" report drive event create yesterday countsonly summary eventrowfilter
```
## Customer and user reports parameters
Display the valid parameters for customer and user reports.
```
gam report usageparameters customer|user [todrive <ToDriveAttribute>*]
```
## Customer usage reports
Display customer usage data over a date range.
```
gam report usage customer [todrive <ToDriveAttribute>*]
[([start|startdate <Date>] [end|enddate <Date>])|(range <Date> <Date>)|
thismonth|(previousmonths <Integer>)]
[skipdates <Date>[:<Date>](,<Date>[:<Date>])*] [skipdaysofweek <DayOfWeek>(,<DayOfWeek>)*]
[fields|parameters <String>]
```
Limit the time period.
* `start <Date>` - Default value is 30 days prior to `end <Date>`
* `end <Date>` - Default value is today
* `range <Date> <Date>` - Equivalent to `start <Date> end <Date>`
* `thismonth` - The current calendar month up to the current time
* `previousmonths <Integer>` - A number in the range 1 to 6 indicating calendar months previous to the current month
### Example
Jay provided this example.
```
gam report usage customer parameters meet:total_call_minutes,meet:total_meeting_minutes start_date 2020-03-01 skipdaysofweek sat,sun todrive
```
A bit about this command
* call minutes = 1 device joined to a meeting
* 5 users on a 10 minute meeting = 50 call minutes
* 2 users on 5 minute call = 10 call minutes
* meeting minutes = length of actual meeting
* 2 users on 10 minute meeting = 10 meeting minutes
* 10 users on 10 minute meeting = 10 meeting minutes.
I excluded weekend days when the organization was closed to avoid dramatic "camel humps" in the data.
Open the Sheet and click Insert > Chart
## Customer reports
Customer reports are generally available up to two days before the current date.
```
<CustomerServiceName> ::=
accounts|
app_maker|
apps_scripts|
calendar|
classroom|
cros|
device_management|
docs|
drive|
gmail|
gplus|
meet|
sites
<CustomerServiceNameList> ::= "<CustomerServiceName>(,<CustomerServiceName>)*"
gam report customers|customer|domain [todrive <ToDriveAttributes>*]
[(date <Date>)|(range <Date> <Date>)|
yesterday|today|thismonth|(previousmonths <Integer>)]
[nodatechange|(fulldatarequired all|<CustomerServiceNameList>)]
[(fields|parameters <String>)|(services <CustomerServiceNameList>)]
[noauthorizedapps]
```
Specify the report date; the default is today's date.
* `date <Date>` - A single date; there is one API call
* `range <Date> <Date>` - A range of dates; there is an API call per date
* `yesterday` - Yesterday; there is one API call
* `today` - Today; there is one API call
* `thismonth` - The current calendar month up to the current time; there is an API call per date
* `previousmonths <Integer>` - A number in the range 1 to 6 indicating calendar months previous to the current month; there is an API call per date
If no report is available for the specified date, can an earlier date be used?
* `nodatechange` - Do not report on an earlier date if no report is available for the specified date.
If only partial report data is available for the specified date and applications, can an earlier date be used?
* `fulldatarequired all` - Back up to an earlier date to get complete data until all applications have full report data
* `fulldatarequired <UserServiceNameList>` - Back up to an earlier date to get complete data until all applications in `<UserServiceNameList>` have full report data
By default, all parameters for all services are displayed, you can select to display fewer parameters.
* `fields|parameters <String>` - A list of service parameters separated by commas
* `services <CustomerServiceNameList>` - All parameters for a list of services
* `noauthorizedapps` - Do not display the `authorized_apps` parameter for the `accounts` service
When no date is specified or `date <Date>` is specified, the data is output in three columns: `date,name,value`.
`name` is the parameter name and `value` is its value. This format is useful for human reading but as useful for manipulating in a spreadsheet.
When `range <Date> <Date>` is specified, the data is output in multiple columns: `date,name1,name2,name3...`.
This format is useful for manipulating in a spreadsheet.
### Examples
Display Gmail traffic for a single day.
```
$ gam report customer parameters gmail:num_emails_sent,gmail:num_emails_received date -2d
date,name,value
2019-03-01,gmail:num_emails_received,4009
2019-03-01,gmail:num_emails_sent,618
$ gam report customer parameters gmail:num_emails_sent,gmail:num_emails_received range -2d -2d
date,gmail:num_emails_received,gmail:num_emails_sent
2019-03-01,4009,618
```
Display Gmail traffic for the last week.
```
$ gam report customer parameters gmail:num_emails_sent,gmail:num_emails_received range -8d -2d
date,gmail:num_emails_received,gmail:num_emails_sent
2019-02-23,772,92
2019-02-24,1015,112
2019-02-25,4544,800
2019-02-26,5429,803
2019-02-27,5232,951
2019-02-28,4691,766
2019-03-01,4009,618
```
## User usage reports
Display user usage data over a date range.
```
gam report usage user [todrive]
[(user all|<UserItem>)|(orgunit|org|ou <OrgUnitPath> [showorgunit])|(select <UserTypeEntity>)]
[([start|startdate <Date>] [end|enddate <Date>])|(range <Date> <Date>)|
thismonth|(previousmonths <Integer>)]
[skipdates <Date>[:<Date>](,<Date>[:<Date>])*] [skipdaysofweek <DayOfWeek>(,<DayOfWeek>)*]
[fields|parameters <String>]
```
Select the users for whom information is desired.
* `user all` - All users, the default; there is one API call
* `user <UserItem>` - An individual user; there is one API call
* `orgunit|org|ou <OrgUnitPath>` - All users in the specified OU; there is one API call
* `showorgunit` - Add a column labelled `orgUnitPath` to the output; an additional API call is made to get the email addresses of the users in `<OrgUnitPath>`
* `select <UserTypeEntity>` - A selected collection of users, e.g., `select group staff@domain.com`; there is one API call per user
Limit the time period.
* `start <Date>` - Default value is 30 days prior to `end <Date>`
* `end <Date>` - Default value is today
* `range <Date> <Date>` - Equivalent to `start <Date> end <Date>`
* `thismonth` - The current calendar month up to the current time
* `previousmonths <Integer>` - A number in the range 1 to 6 indicating calendar months previous to the current month
## User reports
User reports are generally available up to four days before the current date.
```
<UserServiceName> ::=
accounts|
classroom|
docs|
drive|
gmail|
gplus
<UserServiceNameList> ::= "<UserServiceName>(,<UserServiceName>)*"
gam report users|user [todrive <ToDriveAttributes>*]
[(user all|<UserItem>)|(orgunit|org|ou <OrgUnitPath> [showorgunit])|(select <UserTypeEntity>)]
[allverifyuser <UserItem>]
[(date <Date>)|(range <Date> <Date>)|
yesterday|today|thismonth|(previousmonths <Integer>)]
[nodatechange|(fulldatarequired all|<UserServiceNameList>)]
[filtertime.* <Time>] [filter|filters <String>]
[(fields|parameters <String>)|(services <UserServiceNameList>)]
[aggregatebydate|aggregatebyuser [Boolean]]
[maxresults <Number>]
```
Select the users for whom information is desired.
* `user all` - All users, the default; there is one API call
* `user <UserItem>` - An individual user; there is one API call
* `orgunit|org|ou <OrgUnitPath>` - All users in the specified OU; there is one API call
* `showorgunit` - Add a column labelled `orgUnitPath` to the output; an additional API call is made to get the email addresses of the users in `<OrgUnitPath>`
* `select <UserTypeEntity>` - A selected collection of users, e.g., `select group staff@domain.com`; there is one API call per user
Specify the report date; the default is today's date.
* `date <Date>` - A single date; there is one API call
* `range <Date> <Date>` - A range of dates; there is an API call per date
* `yesterday` - Yesterday; there is one API call
* `today` - Today; there is one API call
* `thismonth` - The current calendar month up to the current time; there is an API call per date
* `previousmonths <Integer>` - A number in the range 1 to 6 indicating calendar months previous to the current month; there is an API call per date
If no report is available for the specified date, can an earlier date be used?
* `nodatechange` - Do not report on an earlier date if no report is available for the specified date.
If only partial report data is available for the specified date and applications, can an earlier date be used?
* `fulldatarequired all` - Back up to an earlier date to get complete data until all applications have full report data
* `fulldatarequired <UserServiceNameList>` - Back up to an earlier date to get complete data until all applications in `<UserServiceNameList>` have full report data
Apply filters.
* `filter|filters <String>` - `<String>` is a comma separated list of filter expressions.
Use the `filtertime.* <Time>` option to allow times, usually relative, to be substituted into the `filter <String>` option.
The characters following `filtertime` can be any combination of lowercase letters and numbers.
Select the fields/parameters to display.
* `fields|parameters <String>` - A list of parameters separated by commas
* `services <UserServiceNameList>` - All parameters for a list of services
Select data format.
* `aggregatebydate|aggregatebyuser` is omitted or <Boolean> is False, there is one row of data per user per date.
* `aggregatebydate` is present and <Boolean> is omitted or is True, the data is aggregated by date for all users so that there is one row per date.
* `aggregatebyuser` is present and <Boolean> is omitted or is True, the data is aggregated by user for all dates so that there is one row per user.
Limit the number of activities downloaded per API call; infrequently used.
* `maxresults <Number>`
### Examples
Report on the users that haven't logged in in the last 5 years.
```
gam report users parameters accounts:last_login_time filters "accounts:last_login_time<#filtertime#" filtertime -5y
```
Report on the users that haven't ever logged in.
```
gam report users parameters accounts:last_login_time filters "accounts:last_login_time==#filtertime#" filtertime never
```
Report on users Google Drive usage.
```
gam report users parameters accounts:drive_used_quota_in_mb,accounts:total_quota_in_mb,accounts:used_quota_in_mb,accounts:used_quota_in_percentage
```
Report on email activity for individual users.
```
$ gam report users select users testuser1,testuser2,testuser3 fields gmail:num_emails_received,gmail:num_emails_sent range 2019-02-01 2019-02-07
Getting Reports for testuser1@domain.com (1/3)
Getting Reports for testuser2@domain.com (2/3)
Getting Reports for testuser3@domain.com (3/3)
email,date,gmail:num_emails_received,gmail:num_emails_sent
testuser1@domain.com,2019-02-01,34,0
testuser1@domain.com,2019-02-02,12,0
testuser1@domain.com,2019-02-03,15,0
testuser1@domain.com,2019-02-04,23,0
testuser1@domain.com,2019-02-05,30,0
testuser1@domain.com,2019-02-06,26,0
testuser1@domain.com,2019-02-07,23,0
testuser2@domain.com,2019-02-01,136,18
testuser2@domain.com,2019-02-02,24,0
testuser2@domain.com,2019-02-03,59,1
testuser2@domain.com,2019-02-04,146,19
testuser2@domain.com,2019-02-05,141,17
testuser2@domain.com,2019-02-06,124,36
testuser2@domain.com,2019-02-07,137,26
testuser3@domain.com,2019-02-01,144,5
testuser3@domain.com,2019-02-02,49,0
testuser3@domain.com,2019-02-03,59,1
testuser3@domain.com,2019-02-04,111,4
testuser3@domain.com,2019-02-05,136,11
testuser3@domain.com,2019-02-06,114,12
testuser3@domain.com,2019-02-07,139,10
```
Report on email activity for individual users, aggregate by date.
```
gam report users select users testuser1,testuser2,testuser3 fields gmail:num_emails_received,gmail:num_emails_sent range 2019-02-01 2019-02-07 aggregatebydate
Getting Reports for testuser1@domain.com (1/3)
Getting Reports for testuser2@domain.com (2/3)
Getting Reports for testuser3@domain.com (3/3)
date,gmail:num_emails_received,gmail:num_emails_sent
2019-02-01,314,23
2019-02-02,85,0
2019-02-03,133,2
2019-02-04,280,23
2019-02-05,307,28
2019-02-06,264,48
2019-02-07,299,36
```
## Monthly Report
### An example, running this on 3rd December 2020;-
If combined with a scheduled task or cron job, this will produce an ongoing report with a new tab/sheet for each month.
```
$ gam report usage customer parameters meet:total_call_minutes,meet:total_meeting_minutes skipdaysofweek sat,sun previousmonths 1 todrive tdfileid <File ID> tdtitle "Meet Usage" tdtimeformat %Y-%m-%d tdaddsheet tdsheet "" tdsheettimeformat "%B %Y" tdsheetdaysoffset 6
```
**Breakdown**
* **gam report usage customer parameters meet:total_call_minutes,meet:total_meeting_minutes** - The GAM command
* **skipdaysofweek sat,sun** - exclude Sat & Sun, so only working days
* **previousmonths 1** - run against the previous months date range (regardless of how many days in the month, leap year etc)
* **todrive tdfileid <File ID> tdtitle "Meet Usage" tdtimeformat %Y-%m-%d** - write the data to an existing Google Sheet and append with current date, so it will be called "Meet Usage - 2020-12-03"
* **tdaddsheet tdsheet ""** - Add a new tab/sheet with no name
* **tdsheettimeformat "%B %Y" tdsheetdaysoffset 6** - give the new tab/sheet a time stamp backdated by 6 days of 'Month Year', so for this example "November 2020", which will become the name of the new tab/sheet. The offset number must take you back in time into the previous month.
**Notes**
You need to have already created the Google Sheet, to get the File ID. And tdtitle is not optional, although you should be able to specify "" (a blank name) if you just want the Google Sheet to show the updated date.

149
docs/Reseller.md Normal file
View File

@ -0,0 +1,149 @@
# Reseller
- [API documentation](#api-documentation)
- [Notes](#notes)
- [Definitions](#definitions)
- [Manage Resold Customers](#manage-resold-customers)
- [Display Resold Customers](#display-resold-customers)
- [Manage Resold Subscriptions](#manage-resold-subscriptions)
- [Display Resold Subscriptions](#display-resold-subscriptions)
## API documentation
* https://developers.google.com/admin-sdk/reseller/v1/reference/customers
* https://developers.google.com/admin-sdk/reseller/v1/reference/subscriptions
## Notes
Updated handling of `seats` option in `gam create|update resoldsubscription` to properly assign
the API fields `numberOfSeats` and `maximumNumberOfSeats`.
Prior to version 6.50.00, this is how the `seats <NumberOfSeats> <MaximumNumberOfSeats>` option was processed:
* Plan name `ANNUAL_MONTHLY_PAY` or `ANNUAL_YEARLY_PAY`
* `seats <NumberOfSeats>` - `<NumberOfSeats>` was properly passed to the API
* `seats <NumberOfSeats> <MaximumNumberOfSeats>` - `<NumberOfSeats>` was properly passed to the API; `<MaximumNumberOfSeats>` was passed to the API which ignored it
* Plan name `FLEXIBLE` or `TRIAL`
* `seats <NumberOfSeats>` - `<NumberOfSeats>` was improperly passed to the API; an API error was generated
* `seats <NumberOfSeats> <MaximumNumberOfSeats>` - `<MaximumNumberOfSeats>` was properly passed to the API; `<NumberOfSeats>` was passed to the API which ignored it
Now, you can still use the above option which has been corrected or you can specify `seats <Number>` which will be properly passed in the correct form to the API based on plan name.
## Definitions
```
<CustomerID> ::= <String>
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<ResoldCustomerAttribute> ::=
(email|alternateemail <EmailAddress>)|
(contact|contactname <String>)|
(phone|phonenumber <String>)|
(name|organizationname <String>)|
(address|address1|addressline1 <String>)|
(address2|addressline2 <String>)|
(address3|addressline3 <String>)|
(city|locality <String>)|
(state|region <String>)|
(zipcode|postal|postalcode <String>)|
(country|countrycode <String>)
<SKUID> ::=
nv:<String>:<String> |
20gb | drive20gb | googledrivestorage20gb | Google-Drive-storage-20GB |
50gb | drive50gb | googledrivestorage50gb | Google-Drive-storage-50GB |
200gb | drive200gb | googledrivestorage200gb | Google-Drive-storage-200GB |
400gb | drive400gb | googledrivestorage400gb | Google-Drive-storage-400GB |
1tb | drive1tb | googledrivestorage1tb | Google-Drive-storage-1TB |
2tb | drive2tb | googledrivestorage2tb | Google-Drive-storage-2TB |
4tb | drive4tb | googledrivestorage4tb | Google-Drive-storage-4TB |
8tb | drive8tb | googledrivestorage8tb | Google-Drive-storage-8TB |
16tb | drive16tb | googledrivestorage16tb | Google-Drive-storage-16TB |
assuredcontrols | 1010390001 |
bce | beyondcorp | beyondcorpenterprise | 1010400001 |
cdm | chrome | googlechromedevicemanagement | Google-Chrome-Device-Management |
cloudidentity | identity | 1010010001 |
cloudidentitypremium | identitypremium | 1010050001 |
cloudsearch | 1010350001 |
gsuitebasic | gafb | gafw | basic | Google-Apps-For-Business |
gsuitebusiness | gau | gsb | unlimited | Google-Apps-Unlimited |
gsuitebusinessarchived | gsbau | businessarchived | 1010340002 |
gsuiteenterprisearchived | gseau | enterprisearchived | 1010340001 |
gsuiteenterpriseeducation | gsefe | e4e | 1010310002 |
gsuiteenterpriseeducationstudent | gsefes | e4es | 1010310003 |
gsuitegov | gafg | gsuitegovernment | Google-Apps-For-Government |
gsuitelite | gal | gsl | lite | Google-Apps-Lite |
gwep | workspaceeducationplus | 1010310008 |
gwepstaff | workspaceeducationplusstaff | 1010310009 |
gwepstudent | workspaceeducationplusstudent | 1010310010 |
gwes | workspaceeducationstandard | 1010310005 |
gwesstaff | workspaceeducationstandardstaff | 1010310006 |
gwesstudent | workspaceeducationstandardstudent | 1010310007 |
gwetlu | workspaceeducationupgrade | 1010370001 |
meetdialing | googlemeetglobaldialing | 1010360001 |
postini | gams | gsuitegams | gsuitepostini | gsuitemessagesecurity | Google-Apps-For-Postini |
standard | free | Google-Apps |
vault | googlevault | Google-Vault |
vfe | googlevaultformeremployee | Google-Vault-Former-Employee |
voicepremier | gvpremier | googlevoicepremier | 1010330002 |
voicestandard | gvstandard | googlevoicestandard | 1010330004 |
voicestarter | gvstarter | googlevoicestarter | 1010330003 |
wsbizplus | workspacebusinessplus | 1010020025 |
wsbizplusarchived | workspacebusinessplusarchived | 1010340003 |
wsbizstan | workspacebusinessstandard | 1010020028 |
wsbizstarter | workspacebusinessstarter | wsbizstart | 1010020027 |
wsentess | workspaceenterpriseessentials | 1010060003 |
wsentplus | workspaceenterpriseplus | gae | gse | enterprise | gsuiteenterprise | 1010020020 |
wsentstan | workspaceenterprisestandard | 1010020026 |
wsentstanarchived | workspaceenterprisestandardarchived | 1010340004 |
wsentstarter | workspaceenterprisestarter | 1010020029 | wes |
wsess | workspaceesentials | gsuiteessentials | essentials | d4e | driveenterprise | drive4enterprise | 1010060001 |
wsflw | workspacefrontline | workspacefrontlineworker | 1010020030
```
## Manage Resold Customers
```
gam create resoldcustomer <CustomerDomain> (customer_auth_token <String>)
<ResoldCustomerAttribute>+
gam update resoldcustomer <CustomerID> [customer_auth_token <String>]
<ResoldCustomerAttribues>+
```
## Display Resold Customers
```
gam info resoldcustomer <CustomerID> [formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
## Manage Resold Subscriptions
```
gam create resoldsubscription <CustomerID> (sku <SKUID>)
(plan annual_monthly_pay|annual_yearly_pay|flexible|trial)
(seats <Number>)
[customer_auth_token <String>] [deal <String>] [purchaseorderid <String>]
gam update resoldsubscription <CustomerID> <SKUID>
activate|suspend|startpaidservice|
(renewal auto_renew_monthly_pay|auto_renew_yearly_pay|cancel|
renew_current_users_monthly_pay|renew_current_users_yearly_pay|
switch_to_pay_as_you_go)|
(seats <Number>)|
(plan annual_monthly_pay|annual_yearly_pay|flexible|trial [deal <String>]
[purchaseorderid <String>] [seats <Number>])
gam delete resoldsubscription <CustomerID> <SKUID> cancel|downgrade|transfer_to_direct
```
## Display Resold Subscriptions
```
gam info resoldsubscription <CustomerID> <SKUID>
[formatjson]
gam show resoldsubscriptions
[customerid <CustomerID> [customer_auth_token <String>]] [customer_prefix <String>]
[maxresults <Number>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `maxresults` - Maximum number of results per page. The default is 100 (maximum).
* `formatjson` - Display the fields in JSON format.
```
gam print resoldsubscriptions [todrive <ToDriveAttribute>*]
[customerid <CustomerID> [customer_auth_token <String>]] [customer_prefix <String>]
[maxresults <Number>]
[formatjson [quotechar <Character>]]
```
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

287
docs/Resources.md Normal file
View File

@ -0,0 +1,287 @@
# Resources
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Special quoting](#special-quoting)
- [Manage buildings](#manage-buildings)
- [Display buildings](#display-buildings)
- [Manage features](#manage-features)
- [Display features](#display-features)
- [Manage resources](#manage-resources)
- [Display resources](#display-resources)
- [Manage resource calendar ACLs](#manage-resource-calendar-acls)
- [Display resource calendar ACLs](#display-resource-calendar-acls)
## API documentation
* https://support.google.com/a/answer/1033925
* https://support.google.com/a/answer/7540850
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/resources.calendars
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/resources.buildings
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/resources.features
* https://developers.google.com/my-business/reference/rest/v4/PostalAddress
As resource calendar ids can contain spaces, some care must be used when entering `<ResourceID>` and `<ResourceEntity>`.
Suppose you have an resource calendar `Foo Bar`. To get information about it you enter the command: `gam info resource "Foo Bar"`
The shell strips the `"` leaving a single argument `Foo Bar`; gam correctly processes the argument.
Suppose you enter the command: `gam info resources "Foo Bar"`
The shell strips the `"` leaving a single argument `Foo Bar`; gam splits the argument on space leaving two items and then tries to process `Foo` and `Bar`, not what you want.
You must enter: `gam info resources "'Foo Bar'"`
The shell strips the `"` leaving a single argument `'Foo Bar'`; gam splits the argument on space while honoring the `'` leaving one item `Foo Bar` and correctly processes the item.
In general, when you're accessing a single resource calendar, use the `resource` option to minimize quoting issues.
## Definitions
See [Collections of Items](Collections-of-Items)
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<CalendarACLRole> ::= editor|freebusy|freebusyreader|owner|reader|writer
<CalendarACLScope> ::= <EmailAddress>|user:<EmailAdress>|group:<EmailAddress>|domain:<DomainName>)|domain|default
<CalendarACLScopeList> ::= "<CalendarACLScope>(,<CalendarACLScope>)*"
<CalendarACLScopeEntity>::= <CalendarACLScopeList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<BuildingID> ::= <String>|id:<String>
<FeatureName> ::= <String>
<FeatureNameList> ::= "'<FeatureName>'(,'<FeatureName>')*"
<ResourceID> ::= <String>
<ResourceIDList> ::= "<ResourceID>(,<ResourceID>)*"
<ResourceEntity> ::= <ResourceIDList> | <FileSelector> | <CSVkmdSelector>
<BuildingFieldName> ::=
address|
buildingid|
buildingname|
coordinates|
description|
floors|
floornames|
id|
name
<BuildingFieldNameList> ::= "<BuildingFieldName>(,<BuildingFieldName>)*"
<BuildingAttribute> ::=
(address|addresslines <String>)|
(city|locality <String>)|
(country|regioncode <String>)|
(description <String>)|
(floors <FloorNameList>)|
(id <String>)|
(language|languageCode <Language>)|
(latitude <Float>)|
(longitude <Float>)|
(name <String>)
(state|administrativearea <String>)|
(sublocality <String>)|
(zipcode|postalcode <String>)
<ResourceAttribute> ::=
(addfeatures <FeatureNameList>)|
(buildingid <BuildingID>)|
(capacity <Number>)|
(category other|room|conference_room|category_unknown|unknown)|
(description <String>)|
(features <FeatureNameList>)|
(floor <FloorName>)|
(floorsection <String>)|
(name <String>)|
(removefeatures <FeatureNameList>)|
(type <String>)|
(uservisibledescription <String>)
<ResourceFieldName> ::=
acls|
buildingid|
calendar|
capacity|
category|
description|
email|
featureinstances|
features|
floor|
floorsection|
generatedresourcename|
id|
name|
resourcecategory|
resourcedescription|
resourceemail|
resourceid|
resourcename|
resourcetype|
type|
uservisibledescription
<ResourceFieldNameList> ::= "<ResourceFieldName>(,<ResourceFieldName>)*"
```
## Special quoting
When entering `<FeatureNameList>` with `<FeatureName>s`containing spaces, enclose the list in `"` and the names containing spaces in `'`.
```
features "CameraSet"
features "'Laptop Cart'"
features "CameraSet,'Laptop Cart'"
```
## Manage buildings
When creating a building, at a minimum you must enter `address|addresslines` and `country|regioncode`.
* Enter a single-line address as `address "123 Main Street"`
* Enter a multi-line address as `addresslines "123 Main Street\nAnytown, US"`
For `country|regioncode` see: http://www.unicode.org/cldr/charts/30/supplemental/territory_information.html
```
gam create|add building <BuildIngID> <Name> <BuildingAttribute>*
gam update building <BuildIngID> <BuildingAttribute>*
gam delete building <BuildingID>
```
## Display buildings
```
gam info building <BuildingID>
[formatjson]
gam show buildings
[allfields|<BuildingFildName>*|(fields <BuildingFieldNameList>)]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print buildings [todrive <ToDriveAttribute>*]
[allfields|<BuildingFildName>*|(fields <BuildingFieldNameList>)]
[delimiter <Character>] [formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Manage features
```
gam create|add feature <Name>
gam update feature <Name> name <Name>
gam delete feature <Name>
```
## Display features
```
gam show features
gam print features [todrive <ToDriveAttribute>*]
```
## Manage resources
These commands operate on a single resource.
```
gam create|add resource <ResourceID> <Name> <ResourceAttribute>*
gam update resource <ResourceID> <ResourceAttribute>*
gam delete resource <ResourceID>
```
These commands operate on multiple resources.
```
gam update resources <ResourceEntity> <ResourceAttribute>*
gam delete resources <ResourceEntity>
```
When updating a resource, use the following options to manage the features.
* `features <FeatureNameList>` - Replace the current set of features with a list of features
* `addfeatures <FeatureNameList>` - Add a list of features to the current set of features
* `removefeatures <FeatureNameList>` - Remove a list features from the current set of features
## Display resources
```
gam info resource <ResourceID>
[acls]Documents/GoogleApps/GAM3/Docs/ [calendar]
[formatjson]
gam info resources <ResourceEntity>
[acls]Documents/GoogleApps/GAM3/Docs/ [calendar]
[formatjson]
gam show resources
[allfields|<ResourceFieldName>*|(fields <ResourceFieldNameList>)]
[query <String>]
[acls] [noselfowner] [calendar] [convertcrnl]
[formatjson]
```
Optional data may be displayed for the resource:
* `acls` - Display the resource calendar ACLs
* `calendar` - Display the resource calendar settings
Option `noselfowner` suppresses the display of ACLs that reference the calendar itself as its owner.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print resources [todrive <ToDriveAttribute>*]
[allfields|<ResourceFieldName>*|(fields <ResourceFieldNameList>)]
[query <String>]
[acls] [noselfowner] [calendar] [convertcrnl]
[formatjson [quotechar <Character>]]
```
Optional data may be displayed for the resource:
* `acls` - Display the resource calendar ACLs
* `calendar` - Display the resource calendar settings
Option `noselfowner` suppresses the display of ACLs that reference the calendar itself as its owner.
Some text fields may contain carriage returns or line feeds, displaying fields containing these characters will make processing the CSV file with a script hard; this option converts those characters to a text form.
The default value is `csv_output_convert_cr_nl` from `gam.cfg`
* `convertcrnl` - Convert carriage return to \r and line feed to \n
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
### Example
Print all resources and their owners.
```
gam config csv_output_row_filter "role:regex:owner" redirect csv Resource.csv print resources acls
```
## Manage resource calendar ACLs
These commands operate on a single resource calendar.
```
gam resource <ResourceID> add acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity>
gam resource <ResourceID> update acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity>
gam resource <ResourceID> delete acls|calendaracls [<CalendarACLRole>] <CalendarACLScopeEntity>
```
These commands operate on multiple resource calendars.
```
gam resources <ResourceEntity> add acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity>
gam resources <ResourceEntity> update acls|calendaracls <CalendarACLRole> <CalendarACLScopeEntity>
gam resources <ResourceEntity> delete acls|calendaracls [<CalendarACLRole>] <CalendarACLScopeEntity>
```
## Display resource calendar ACLs
```
gam resource <ResourceID> info acls|calendaracls <CalendarACLScopeEntity>
[formatjson]
gam resources <ResourceEntity> info acls|calendaracls <CalendarACLScopeEntity>
[formatjson]
gam resources <ResourceEntity> show acls|calendaracls
[noselfowner]
[formatjson]
```
Option `noselfowner` suppresses the display of ACLs that reference the calendar itself as its owner.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam resources <ResourceEntity> print acls|calendaracls [todrive <ToDriveAttribute>*]
[noselfowner]
[formatjson [quotechar <Character>]]
```
Option `noselfowner` suppresses the display of ACLs that reference the calendar itself as its owner.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

View File

@ -0,0 +1,62 @@
# Running GAMADV-XTD3 securely on a Google Compute Engine
- [Thanks](#Thanks)
- [Introduction](#introduction)
- [Setup Steps](#setup-steps)
## Thanks
Thanks to Jay Lee for the original version of this document.
## Introduction
GAMADV-XTD3 can run on a Linux or Windows Google Compute Engine (GCE) VM and use the attached service account to access Google Workspace APIs. The advantage of this configuration is that no service account private key is accessible to GAMADV-XTD3 directly and there is no risk of the key being stolen/lost.
GAMADV-XTD3 version 6.50.00 or higher is required.
## Setup Steps
1. Create a [GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
2. Create [a service account](https://cloud.google.com/iam/docs/creating-managing-service-accounts) which will be used by GAMADV-XTD3. Continue steps 2 and 3 without granting the new service account any special access to the project and without granting users access to the service account.
3. Grant the service account rights to generate authentication tokens.
* go to [console.cloud.google.com](https://console.cloud.google.com).
* go to "IAM & Admin" > Service accounts
* click on the service account you created (not the default service account).
* copy the email address of your service account to the clipboard.
* click on the Permissions tab.
* click "Grant Access".
* In the "New principals text box, paste the service account email you copied.
* Give your service account the "Service Account Token Creator" and "View Service Accounts" roles.
4. [Create a Windows or Linux virtual machine](https://cloud.google.com/compute/docs/instances/create-start-instance).
* You can choose a region physically close to you though you may be limited in your choices if you want to use the free tier.
* GAMADV-XTD3 can run on the minimal `e2-micro` [free tier VM](https://cloud.google.com/free/docs/free-cloud-features#compute) though performance may suffer. If you are performing batch operations, raising the CPU count will help performance. If you have a very large and busy Workspace instance downloading reports or Drive file lists may require more RAM.
* [DO NOT use the default service account](https://cloud.google.com/iam/docs/best-practices-service-accounts#single-purpose). Choose the service account you created above instead.
* GAMADV-XTD3 does not use a significant amount of storage, unless you have specific storage needs the default disk size should suffice.
* leave other VM instance settings at their defaults unless you know what you are doing.
5. Install GAMADV-XTD3 on the VM
* See: https://github.com/taers232c/GAMADV-XTD3/wiki/How-to-Install-Advanced-GAM
6. Logout and log back in to the VM, you should now be able to run GAMADV-XTD3 commands like:
```
gam version
```
7. Create the special `oauth2service.json` file GAMADV-XTD3 will use:
```
gam create gcpserviceaccount
```
If you'd like, take a look at the generated ```oauth2service.json``` file;
you'll notice that while the file has some fields similar to a normal service account file, there is no `private_key` attribute containing an RSA private key.
8. Enable the Google APIs GAMADV-XTD3 will use:
```
gam enable apis
```
You are given the option to enable them automatically or manually. Automatic enablement will ask you to authenticate to GAMADV-XTD3. You should authenticate as a user with rights to manage project APIs, probably a project owner. If you are not the project owner you can choose manual enablement and GAMADV-XTD3 will provide two or more URLs which you can send to the project owner. When the owner opens these URLs, they'll be prompted to enable all the APIs GAMADV-XTD3 needs.
9. Manage user data
* Run ```gam user user@domain.com check serviceaccount``` and follow the instructions to perform domain-wide delegation.
10. Perform admin actions (manage users, groups, orgunits, Chrome devices, etc)
* [Configure delegated admin service account (DASA)](https://github.com/taers232c/GAMADV-XTD3/wiki/Using-GAMADV-XTD3-with-a-delegated-admin-service-account); start at step 4.

View File

@ -0,0 +1,26 @@
# SSL Root CA Certificates
For an overall discussion of SSL, see: https://sites.google.com/site/x509certificateusage/
Google Internet Authority, see: https://pki.google.com/index.html
Trusted Roots, see: https://pki.google.com/faq.html What roots should we trust for connecting to Google?
GAM internally uses the PEM file mentioned in the previous link; it is also included in the GAM distribution
as `cacerts.pem`.
If your site uses a firewall that does SSL inspection/decryption, you will need a vendor specific certificate.
If your vendor's certificate is in DER format, you will have to convert it to PEM format.
* `openssl x509 -inform DER -in firewallcert.crt -out firewallcert.pem -outform PEM`
Copy cacerts.pem from the folder containing gam.exe/gam.py to the folder containing gam.cfg.
Append the contents of firewallcert.pem to cacerts.pem
* Linux/Mac OS - `cat firewallcert.pem >> cacerts.pem`
* Windows - `type firewallcert.pem >> cacerts.pem`
Tell GAM to use the new cacerts.pem:
```
gam config cacerts_pem cacerts.pem save
```

50
docs/Schemas.md Normal file
View File

@ -0,0 +1,50 @@
# Schemas
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Manage schemas](#manage-schemas)
- [Display schemas](#display-schemas)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/schemas
## Definitions
```
<SchemaName> ::= <String>
<FieldName> ::= <String>
<SchemaNameList> ::= "<SchemaName>(,<SchemaName>)*"
<SchemaEntity> ::= <SchemaNameList> | <FileSelector> | <CSVkmdSelector>
<SchemaFieldDefinition> ::=
field <FieldName> [displayname <String>]
(type bool|date|double|email|int64|phone|string)
[multivalued|multivalue] [indexed] [restricted]
[range <Number> <Number>]
endfield
```
## Manage schemas
When creating and updating schemas, spaces are converted to `_` in schema
and field names as spaces are not valid. The schema and field display names will
retain the spaces. You can specify schema/field display names independently of the schema/field name.
```
gam create|add schema|schemas <SchemaName> [displayname <String>] <SchemaFieldDefinition>+
gam update schema <SchemaName> [displayname <String>] <SchemaFieldDefinition>* (deletefield <FieldName>)*
gam delete schema <SchemaName>
gam update schema|schemas <SchemaEntity> [displayname <String>] <SchemaFieldDefinition>* (deletefield <FieldName>)*
gam delete schema|schemas <SchemaEntity>
```
To create a field for your users pronouns you can use:
```gam create schema pronouns field pronouns type string```
And to update a users custom field you can use:
```gam update <UserTypeEntity> pronouns.pronouns "they/them"```
## Display schemas
```
gam info schema|schemas <SchemaEntity>
gam show schema|schemas
gam print schema|schemas [todrive <ToDriveAttribute>*]
```

7
docs/Scripts.md Normal file
View File

@ -0,0 +1,7 @@
# Scripts
These scripts can be used to enhance GAM's capabilities; all are supported with Advanced GAM,
many are supported with Standard GAM. They require that Python 3 be installed on you computer.
* https://github.com/taers232c/GAM-Scripts3
* https://www.python.org/

440
docs/Send-Email.md Normal file
View File

@ -0,0 +1,440 @@
# Send Email
- [Note](#note)
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Use Gmail API to send messages](#use-gmail-api-to-send-messages)
- [Use SMTP to send messages](#use-smtp-to-send-messages)
- [Google Workspace SMTP relay service](#google-workspace-smtp-relay-service)
- [Send an email](#send-an-email)
- [Send an email from a user sendas](#send-an-email-from-a-user-sendas)
- [Send an email from a group](#send-an-email-from-a-group)
- [Send an email to notify a person of their new Google Workspace account](#send-an-email-to-notify-a-person-of-their-new-google-workspace-account)
- [Send an email from users](#send-an-email-from-users)
- [Send an email to users](#send-an-email-to-users)
- [Simple `replace <Tag> <String>` processing](Tag-Replace)
- [Example](#example)
## Note
Thanks to @bousquf for the following enhancement. You want to send a message from an authorized group
but a group email address can't be used in the Gmail API as the sender. Alternatively, you want to send
a message from a user's alternate sendas address.
Added the option `mailbox <EmailAddress>` to `gam sendemail` to allow specifying the sender email address used in the Gmail API as different from `from <EmailAddress>`.
## API documentation
* https://developers.google.com/gmail/api/v1/reference/users/messages
* https://support.google.com/a/answer/176600?hl=en
## Definitions
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::=
<String>@<DomainName> |
<String> <<String>@<DomainName>> # The outer <> around <String>@<DomainName> are literal, e.g., IT Group<group@domain.com>
<EmailAddressList> ::= "<EmailAddress>(,<EmailAddress>)*"
<EmailAddressEntity> ::= <EmailAddressList> | <FileSelector> | <CSVkmdSelector>
<RecipientEntity> ::= <EmailAddressEntity> | (select <UserTypeEntity>)
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
<UserGoogleDoc> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
<MessageContent> ::=
(message|textmessage|htmlmessage <String>)|
(file|textfile|htmlfile <FileName> [charset <Charset>])|
(gdoc|ghtml <UserGoogleDoc>)|
(gcsdoc|gcshtml <StorageBucketObjectName>)|
(emlfile <FileName>)
```
```
<Time> ::=
<Year>-<Month>-<Day>(<Space>|T)<Hour>:<Minute>:<Second>[.<MilliSeconds>](Z|(+|-(<Hour>:<Minute>))) |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
<SMTPDateHeader> ::=
date|
delivery-date|
expires|
expiry-date|
latest-delivery-time|
reply-by|
resent-date
<SMTPHeader> ::=
accept-language|
alternate-recipient|
autoforwarded|
autosubmitted|
bcc|
cc|
comments|
content-alternative|
content-base|
content-description|
content-disposition|
content-duration|
content-id|
content-identifier|
content-language|
content-location|
content-md5|
content-return|
content-transfer-encoding|
content-type|
content-features|
conversion|
conversion-with-loss|
dl-expansion-history|
deferred-delivery|
delivered-to|
discarded-x400-ipms-extensions|
discarded-x400-mts-extensions|
disclose-recipients|
disposition-notification-options|
disposition-notification-to|
encoding|
encrypted|
from|
generate-delivery-report|
importance|
in-reply-to|
incomplete-copy|
keywords|
language|
list-archive|
list-help|
list-id|
list-owner|
list-post|
list-subscribe|
list-unsubscribe|
mime-version|
message-context|
message-id|
message-type|
obsoletes|
original-encoded-information-types|
original-message-id|
originator-return-address|
pics-label|
prevent-nondelivery-report|
priority|
received|
references|
reply-to|
resent-bcc|
resent-cc|
resent-from|
resent-message-id|
resent-reply-to|
resent-sender|
resent-to|
return-path|
sender|
sensitivity|
subject|
supersedes|
to|
x400-content-identifier|
x400-content-return|
x400-content-type|
x400-mts-identifier|
x400-originator|
x400-received|
x400-recipients|
x400-trace
<SMTPHeaderList> ::= "<SMTPDateHeader|SMTPHeader>(,<SMTPDateHeader|SMTPHeader>)*"
```
## Use Gmail API to send messages
By default, GAM uses the Gmail API to send email messages. Typically, Service Account access is used
but Client access will be used when `gam.cfg todrive_clientaccess = True`.
## Use SMTP to send messages
Alternatively, GAM can use SMTP to send email messages. Messages are always sent on port 587 using `starttls`.
There are four `gam.cfg` variables used to configure SMTP.
* `smtp-fqdn` - Fully qualified domain name used in SMTP EHLO command; default is to use system FQDN
* `smtp-host` - The host name or IP address of the SMTP server
* `smtp-username` - The username used for SMTP authentication; default is to not use authentication
* `smtp-password` - The password used for SMTP authentication; default is to not use authentication
GAM uses SMTP to send email messages when `smtp-host` is defined. SMTP authentication is performed
when both `smtp_username` and `smtp_password` are defined; otherwise, the connection is made without authentication.
The `smtp_password` can be specified as a plain text string or a Base64 encoded string.
* `plain text gam.cfg` - `smtp_password = password`
* `plain text command line` - `gam config smtp_password password save`
* `Base64 gam.cfg` - `smtp_password = b'base64string'`
* `Base64 command line` - `gam config smtp_password = "b'base64string'"` save
To convert a plain text string to Base 64 encoded string perform the following command:
* Windows - `powershell "[convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(\"password\"))"`
* Linux/MacOS - `echo -n "password" | base64`
## Google Workspace SMTP relay service
You can have GAM use SMTP in conjunction with the Google Workspace SMTP relay service.
Configure it at Admin Console > Apps > Google Workspace > Gmail > Routing > SMTP relay service > CONFIGURE
* Give the service a name, e.g., "GAM SMTP"
* `1. Allowed senders` - `Only addresses in my domain(s)`
* `2. Authentication`
* Check `Only accept mail from the specified IP addresses`
* Click `Add`
* `Description` - Describe the IP address, e.g., "GAM Server IP"
* `IP address/range` - Enter the public IP address of your GAM server, e.g., 1.2.3.4/32
* Check `Enabled`
* Click `SAVE`
* Check/uncheck `Require SMTP Authentication` as desired. If checked, `smtp-password` must be a Gmail Application Specific password
* `3. Encryption`
* Check `Require TLS encryption`
* Click `SAVE` in the lower right
![image](https://user-images.githubusercontent.com/46608557/160944041-1b3781d4-ad6b-4d86-b7fc-4acb9965a808.png)
## Send an email
```
gam sendemail [recipient|to] <RecipientEntity>
[from <EmailAddress>] [mailbox <EmailAddress>] [replyto <EmailAddress>]
[cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage]
[subject <String>]
[<MessageContent>] (replace <Tag> <String>)*
[html [<Boolean>]] (attach <FileName> [charset <CharSet>])*
(embedimage <FileName> <String>)*
[newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>]
(<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
```
By default, emails will be sent from the admin user named in oauth2.txt, override this with the `from <EmailAddress>` option.
When using the Gmail API/SMTP, GAM gets no/little indication as to the status of the message delivery; the from user will get a non-delivery receipt if the message
could not be sent to the specified recipients.
By default, messages are sent as plain text, use `html` or `html true` to indicate that the message is HTML.
By default, a separate email is sent to each recipient; this isolates the recipient email addresses.
If any of these options are specified, a single email will be sent to all of the recipients:
* `cc <RecipientEntity>`
* `bcc <RecipientEntity>`
* `singlemessage`
The `<SMTPDateHeader> <Time>` argument requires `<Time>` values which will be converted to RFC2822 dates. If you have these headers with values that
are not in `<Time>` format, use the argument `header <SMTPDateHeader> <String>`.
If you have an SMTP header that is not found in `<SMTPDateHeader>` or `<SMTPHeader>`, use `header <String> <String>`.
You can embed images in HTML email messages.
Your HTML message will contain lines like this:
```
<img src="cid:image1"/>
<img src="cid:image2"/>
```
Your command line will have: `embedimage file1.jpg image1` embedimage file2.jpg image2`
## Send an email from a user sendas
You want to send an email from a user's sendas address.
Use the `mailbox <EmailAddress>` to specify the user's primary email address and `from <EmailAddress>` to specify the sendas address.
```
gam sendemail destination@email.com from useralias@domain.com mailbox user@domain.com subject "test subject" message "text body" ...
```
## Send an email from a group
You want to send an email from a group for which you are an authorized sender.
Use the `mailbox <EmailAddress>` to specify the sender email address used in the Gmail API as different from `from <EmailAddress>`.
```
gam sendemail destination@email.com from "IT Group<group@domain.com>" mailbox user@domain.com subject "test subject" message "text body" ...
```
## Send an email to notify a person of their new Google Workspace account
You can send a message with account details to an email address when creating|updating a user; this might be the user's secondary email address.
You can specify additional recipients, e.g., help desk personnel.
```
gam sendemail [recipient|to] <RecipientEntity> [from <EmailAddress>]
[replyto <EmailAddress>]
[cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage]
[subject <String>]
[<MessageContent>] (replace <Tag> <String>)*
[html [<Boolean>]] (attach <FileName> [charset <CharSet>])*
(embedimage <FileName> <String>)*
[newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>]
(<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
```
By default, emails will be sent from the admin user named in oauth2.txt, override this with the `from <EmailAddress>` option.
When using the Gmail API, GAM gets no/little indication as to the status of the message delivery; the from user will get a non-delivery receipt if the message
could not be sent to the specified recipients.
By default, messages are sent as plain text, use `html` or `html true` to indicate that the message is HTML.
The `recipient|to`, `firstname|givenname`, `lastname|familyname` and `password` options are required when `newuser <EmailAddress>` is specified.
In the subject and message, these strings will be replaced with the specified values:
* `#givenname#` - first/given name
* `#familyname#` - last/family name
* `#email#` - user's email address
* `#user#` - user's email address
* `#username#` - portion of user's email address before @
* `#domain#` - portion of user's email after after @
* `#password#` - password
If `subject` is not specified, the following value will be used:
* `Welcome to #domain#`
If `message` is not specified, the following value will be used:
* `Hello #givenname# #familyname#,\n\nYou have a new account at #domain#\nAccount details:\n\nUsername\n#user#\n\nPassword\n#password#\n\n
Start using your new account by signing in at\nhttps://www.google.com/accounts/AccountChooser?Email=#user#&continue=https://apps.google.com/user/hub\n`
If you want a language/organization specific message, use a template file: `message file <FileName> [charset <CharSet>]`
The `<SMTPDateHeader> <Time>` argument requires `<Time>` values which will be converted to RFC2822 dates. If you have these headers with values that
are not in `<Time>` format, use the argument `header <SMTPDateHeader> <String>`.
If you have an SMTP header that is not found in `<SMTPDateHeader>` or `<SMTPHeader>`, use `header <String> <String>`.
You can embed images in HTML email messages.
Your HTML message will contain lines like this:
```
<img src="cid:image1"/>
<img src="cid:image2"/>
```
Your command line will have: `embedimage file1.jpg image1` embedimage file2.jpg image2`
### Examples
Send an email to a user's personal address notifying them of their new Google Workspace account;
use the `newuser` option and default subject and message.
```
gam sendemail bob@gmail.com newuser bob@domain.com firstname Bob lastname Smith password xxxxxx
```
Send an email to a user's personal address notifying them of their new Google Workspace account;
use custom subject and message.
```
gam sendemail bob@gmail.com subject "Your new #domain# account` message 'Bob, your new domain email address is bob@domain.com with password xxxxxx'
```
You can use a CSV file to do multiple new users.
```
Users.csv
personal,primaryemail,firstname,password
bob@gmail.com,bob@domain.com,Bob,xxxxxx
mary@gmail.com,mary@domain.com,Mary,xxxxxx
...
gam csv Users.csv gam sendemail "~personal" subject "Your new #domain# account` message '~~firstname~~, your new domain email address is ~~primaryemail~~ with password ~~password~~'
```
## Send an email from users
```
gam <UserTypeEntity> sendemail recipient|to <RecipientEntity>
[replyto <EmailAddress>]
[cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage]
[subject <String>]
[<MessageContent>] (replace <Tag> <String>)*
[html [<Boolean>]] (attach <FileName> [charset <CharSet>])*
(embedimage <FileName> <String>)*
[newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>]
(<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
```
Emails will be sent from the users in `<UserTypeEntity>` to the recipients in `<RecipientEntity>`.
When using the Gmail API/SMTP, GAM gets no/little indication as to the status of the message delivery; the from user will get a non-delivery receipt if the message
could not be sent to the specified recipients.
By default, messages are sent as plain text, use `htmlmessage`, `htmlfile` or `html true` to indicate that the message is HTML.
By default, a separate email is sent to each recipient; this isolates the recipient email addresses.
If any of these options are specified, a single email will be sent to all of the recipients:
* `cc <RecipientEntity>`
* `bcc <RecipientEntity>`
* `singlemessage`
The `<SMTPDateHeader> <Time>` argument requires `<Time>` values which will be converted to RFC2822 dates. If you have these headers with values that
are not in `<Time>` format, use the argument `header <SMTPDateHeader> <String>`.
If you have an SMTP header that is not found in `<SMTPDateHeader>` or `<SMTPHeader>`, use `header <String> <String>`.
You can embed images in HTML email messages.
Your HTML message will contain lines like this:
```
<img src="cid:image1"/>
<img src="cid:image2"/>
```
Your command line will have: `embedimage file1.jpg image1` embedimage file2.jpg image2`
## Send an email to users
```
gam <UserTypeEntity> sendemail [from <EmailAddress>]
[replyto <EmailAddress>]
[cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage]
[subject <String>]
[<MessageContent>] (replace <Tag> <String>)*
[html [<Boolean>]] (attach <FileName> [charset <CharSet>])*
(embedimage <FileName> <String>)*
[newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>]
(<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
```
Emails will be sent to the users in `<UserTypeEntity>`.
By default, emails will be sent from the admin user named in oauth2.txt, override this with the `from <EmailAddress>` option.
When using the Gmail API/SMTP, GAM gets no/little indication as to the status of the message delivery; the from user will get a non-delivery receipt if the message
could not be sent to the specified recipients.
By default, messages are sent as plain text, use `htmlmessage`, `htmlfile` or `html true` to indicate that the message is HTML.
By default, a separate email is sent to each recipient; this isolates the recipient email addresses.
If any of these options are specified, a single email will be sent to all of the recipients:
* `cc <RecipientEntity>`
* `bcc <RecipientEntity>`
* `singlemessage`
The `<SMTPDateHeader> <Time>` argument requires `<Time>` values which will be converted to RFC2822 dates. If you have these headers with values that
are not in `<Time>` format, use the argument `header <SMTPDateHeader> <String>`.
If you have an SMTP header that is not found in `<SMTPDateHeader>` or `<SMTPHeader>`, use `header <String> <String>`.
You can embed images in HTML email messages.
Your HTML message will contain lines like this:
```
<img src="cid:image1"/>
<img src="cid:image2"/>
```
Your command line will have: `embedimage file1.jpg image1` embedimage file2.jpg image2`
## Example
Send a message to a user, save the Message-ID so that a later reminder message can be sent
referring to the first message.
```
$ gam user user1@domain.com sendemail to user2domain.com subject Test textmessage "Message"
User: user1@domain.com, Send Email to 1 Recipient
Recipient: user2@domain.com, Message: Test, Email Sent: 17677ccdfdeae7ad
$ gam redirect csv UserEmail.csv user user1@domain.com print messages ids 17677ccdfdeae7ad headers To,Subject,Message-ID
$ more UserEmail.csv
User,threadId,id,Subject,To,Message-ID
user1@comain.com,17677d3e79d5f68a,17677d3e79d5f68a,Test,user2@domain.com,<CAPMj=+p3vdDz1Mjfpe1BpNPT7g-MN1SKifjjCFDme2ftppsMJA@mail.gmail.com>
```
Send reminder message.
```
$ gam csv UserEmail.csv gam user "~User" sendemail to "~To" subject "~Subject" textmessage "Reminder Message" references "~Message-ID" in-reply-to "~Message-ID"
User: user1@domain.com, Send Email to 1 Recipient
Recipient: user2@domain.com, Message: Test, Email Sent: 17677cdfbe1146f4
```

702
docs/Shared-Drives.md Normal file
View File

@ -0,0 +1,702 @@
# Domain Administrators - Shared Drives
- [API documentation](#api-documentation)
- [Query documentation](#query-documentation)
- [Definitions](#definitions)
- [Introduction](#introduction)
- [GUI API permission name mapping](#gui-api-permission-name-mapping)
- [Display Shared Drive themes](#display-shared-drive-themes)
- [Manage Shared Drives](#manage-shared-drives)
- [Create a Shared Drive](#create-a-shared-drive)
- [Bulk Create Shared Drives](#bulk-create-shared-drives)
- [Update Shared Drive settings](#update-shared-drive-settings)
- [Delete a Shared Drive](#delete-a-shared-drive)
- [Change Shared Drive visibility](#change-shared-drive-visibility)
- [Display Shared Drives](#display-shared-drives)
- [Display List of Shared Drives in an Organizational Unit](#display-list-of-shared-drives-in-an-organizational-unit)
- [Manage Shared Drive access](#manage-shared-drive-access)
- [Transfer Shared Drive access](#transfer-shared-drive-access)
- [Display Shared Drive access](#display-shared-drive-access)
- [Display Shared Drive access for specific Shared Drives](#display-shared-drive-access-for-specific-shared-drives)
- [Display Shared Drive access for selected Shared Drives](#display-shared-drive-access-for-selected-shared-drives)
- [Display ACLs for Shared Drives with no organizers](#display-acls-for-shared-drives-with-no-organizers)
- [Display ACLs for Shared Drives with all organizers outside of your domain](#display-acls-for-shared-drives-with-all-organizers-outside-of-your-domain)
- [Display ACLs for Shared Drives with all ACLs outside of your domain](#display-acls-for-shared-drives-with-all-acls-outside-of-your-domain)
- [Clean up scammed Shared Drives](#clean-up-scammed-shared-drives)
## API documentation
* https://developers.google.com/drive/api/v3/reference/files
* https://developers.google.com/drive/api/v3/reference/teamdrives/list
* https://support.google.com/a/answer/7374057
* https://workspaceupdates.googleblog.com/2022/05/shared-drives-in-organizational-units-open-beta.html
## Query documentation
* https://developers.google.com/drive/api/v3/search-shareddrives
## Definitions
```
<ColorHex> ::= "#<Hex><Hex><Hex><Hex><Hex><Hex>"
<ColorNameGoogle> ::=
asparagus|bluevelvet|bubblegum|cardinal|chocolateicecream|denim|desertsand|
earthworm|macaroni|marsorange|mountaingray|mountaingrey|mouse|oldbrickred|
pool|purpledino|purplerain|rainysky|seafoam|slimegreen|spearmint|
toyeggplant|vernfern|wildstrawberries|yellowcab
<ColorNameWeb> ::=
aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|
blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|
cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|
darkgrey|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|
darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|
darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|
firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|
gray|grey|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|
lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|
lightgoldenrodyellow|lightgray|lightgrey|lightgreen|lightpink|lightsalmon|
lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|
lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|
mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|
mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|
navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|
palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|
peru|pink|plum|powderblue|purple|red|rosybrown|royalblue|saddlebrown|salmon|
sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|
slategrey|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|
wheat|white|whitesmoke|yellow|yellowgreen
<ColorName> ::= <ColorNameGoogle>|<ColorNameWeb>
<ColorValue> ::= <ColorName>|<ColorHex>
```
```
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<DriveFileACLRole> ::=
manager|organizer|owner|
contentmanager|fileorganizer|
contributor|writer|editor|
commenter|
viewer|reader
<DriveFileACLType> ::= anyone|domain|group|user
<DriveFilePermission> ::=
anyone|anyonewithlink|
user:<EmailAddress>|group:<EmailAddress>|
domain:<DomainName>|domainwithlink:<DomainName>;<DriveFileACLRole>
<DriveFilePermissionID> ::=
anyone|anyonewithlink|id:<String>
<DriveFilePermissionIDorEmail> ::=
<DriveFilePermissionID>|<EmailAddress>
<DriveFilePermissionList> ::=
"<DriveFilePermission>(,<DriveFilePermission)*"
<DriveFilePermissionIDList> ::=
"<DriveFilePermissionID>(,<DriveFilePermissionID>)*"
<DriveFilePermissionEntity> ::=
<DriveFilePermissionList> |
<JSONData> |
<FileSelector> |
<CSVFileSelector> |
<CSVkmdSelector> |
<CSVDataSelector>
<DriveFilePermissionIDEntity> ::=
<DriveFilePermissionIDList> |
<JSONData> |
<FileSelector> |
<CSVFileSelector> |
<CSVkmdSelector> |
<CSVDataSelector>
<DrivePermissionsFieldName> ::=
additionalroles|
allowfilediscovery|
deleted|
displayname|name
domain|
emailaddress|
expirationdate|
expirationtime|
id|
permissiondetails|
photolink|
role|
teamdrivepermissiondetails|
type|
withlink
<DrivePermissionsFieldNameList> ::= "<DrivePermissionsFieldName>(,<DrivePermissionsFieldName>)*"
<QueryTeamDrive> ::= <String> See: https://developers.google.com/drive/api/v3/search-parameters
<SharedDriveACLRole> ::=
manager|organizer|owner|
contentmanager|fileorganizer|
contributor|writer|editor|
commenter|
viewer|reader
<SharedDriveACLRoleList> ::= "<SharedDriveACLRole>(,<SharedDriveACLRole>)*"
<SharedDriveID> ::= <String>
<SharedDriveName> ::= <String>
<SharedDriveEntity> ::=
<SharedDriveID>|
(teamdriveid <SharedDriveID>)|(teamdriveid:<SharedDriveID>)|
(teamdrive <SharedDriveName>)|(teamdrive:<SharedDriveName>)
<SharedDriveFieldName> ::=
backgroundimagefile|
backgroundimagelink|
capabilities|
colorrgb|
createdtime|
id|
name|
themeid
<SharedDriveFieldNameList> ::= "<SharedDriveFieldName>(,<SharedDriveFieldName>)*"
<SharedDriveIDEntity> ::=
<DriveFileItem>|(teamdriveid <DriveFileItem>)|(teamdriveid:<DriveFileItem>)
<SharedDriveNameEntity> ::=
(teamdrive <SharedDriveName>)|(teamdrive:<SharedDriveName>)
<SharedDriveAdminQueryEntity> ::=
(teamdriveadminquery <QueryTeamDrive>)|(teamdriveadminquery:<QueryTeamDrive>)
<SharedDriveEntityAdmin> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity> |
<SharedDriveAdminQueryEntity>
<SharedDriveRestrictionsSubfieldName> ::=
adminmanagedrestrictions|
allowcontentmanagerstosharefolders|
copyrequireswriterpermission|
domainusersonly|
drivemembersonly|teammembersonly|
sharingfoldersrequiresorganizerpermission
Each pair of restrictions below are equivalent:
allowcontentmanagerstosharefolders true
sharingfoldersrequiresorganizerpermission false
allowcontentmanagerstosharefolders false
sharingfoldersrequiresorganizerpermission true
```
## Introduction
A domain administrator with the Drive and Docs administrator privilege can search for Shared Drives or update permissions for Shared Drives
owned by their organization, regardless of the admin's membership in any given Shared Drive.
Three forms of the commands are available:
* `gam action ...` - The administrator named in oauth2.txt is used, domain administrator access implied
* `gam <UserTypeEntity> action ... adminaccess` - The user named in `<UserTypeEntty>` is used, adminaccess indicates that the user is a domain administrator
* `gam <UserTypeEntity> action ...` - The user named in `<UserTypeEntty>` is used, access is limited to drives for which they are an organizer
## GUI API permission name mapping
| GUI setting | API setting |
|------------|------------|
| Manager | organizer |
| Content manager | fileOrganizer |
| Contributor | writer |
| Commenter | commenter |
| Viewer | reader |
## Display Shared Drive themes
```
gam show teamdrivethemes
```
## Manage Shared Drives
## Create a Shared Drive
The user that creates a Shared Drive is given the permission role organizer for the Shared Drive,
```
gam [<UserTypeEntity>] create teamdrive <Name>
[(theme|themeid <String>)|
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide <Boolean>] [ou|org|orgunit <OrgUnitItem>]
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) | returnidonly]
[adminaccess|asadmin]
```
* `themeid` - a Shared Drive themeId obtained from `show teamdrivethemes`
* `customtheme` - set the backgroundImageFile property described here: https://developers.google.com/drive/v3/reference/teamdrives
* `<Float>` - X coordinate, typically 0.0
* `<Float>` - Y coordinate, typically 0.0
* `<Float>` - width, typically 1.0
* `color` - set the Shared Drive color
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `hide <Boolean>` - Set Shared Drive visibility
This option is only available when the command is run as an administrator.
* `ou|org|orgunit <OrgUnitItem>` - See: https://workspaceupdates.googleblog.com/2022/05/shared-drives-in-organizational-units-open-beta.html
If any attributes other than `themeid` are specified, GAM must create the Drive and then update the Drive attributes.
Even though the Create API returns success, the Update API fails and reports that the Drive does not exist.
For this reason, GAM waits 30 seconds after the create before attempting the update. GAM repeats the update
with waits of 15, 30, and 45 seconds if the Update API continues to fail. This is acceptable when creating
a single Shared Drive, for bulk Shared Drive creation see [Bulk Create Shared Drives](#bulk-create-shared-drives).
By default, the Google Administrator and Shared Drive name and ID values are displayed on stdout.
* `csv [todrive <ToDriveAttribute>*]` - Write Google Administrator, Shared Drive name and ID values to a CSV file.
* `addcsvdata <FieldName> <String>` - Add additional columns of data from the command line to the output
* `returnidonly` - Display just the ID of the created Shared Drive as output
When either of these options is chosen, no infomation about Shared Drive restrictions or hiding will be displayed.
To retrieve the Shared Drive ID with `returnidonly`:
```
Linux/MacOS
teamDriveId=`gam create teamdrive ... returnidonly`
Windows PowerShell
$teamDriveId = & gam create teamdrive ... returnidonly`
```
## Bulk Create Shared Drives
Most Shared Drive attributes can't be applied as part of the create, the Drive must be created and then updated with the desired attributes.
As a newly created Drive can't be updated for 30+ seconds; split the operation into two commands: create and update.
Make a CSV file SharedDriveNames.csv with at least one column, name.
```
gam redirect csv ./SharedDrivesCreated.csv multiprocess csv SharedDriveNames.csv gam create teamdrive "~name" csv
```
This will create a three column CSV file SharedDrivesCreated.csv with columns: User,name,id
* There will be a row for each Shared Drive.
* User will be the Google Administrator.
Use the SharedDrivesCreated.csv file to apply the desired options/attributes.
```
gam redirect stdout ./SharedDrivesUpdated.txt multiprocess redirect stderr stdout csv ./SharedDrivesCreated.csv gam update shareddrive "~id" [options/attributes as desired]
```
Make Shared Drives for students
```
StudentSharedDrives.csv
primaryEmail,Name
bob@domain.com,Bob Jones
mary@domain.com,Mary Smith
...
# Create the student Shared Drives
gam redirect stdout ./StudentSharedDrivesCreated.txt multiprocess redirect stderr stdout redirect csv ./StudentSharedDrivesCreated.csv multiprocess csv StudentSharedDrives.csv gam create shareddrive "~Name" csv addcsvdata primaryEmail "~primaryEmail"
# Update attributes/options
gam redirect stdout ./StudentSharedDrivesUpdated.txt multiprocess redirect stderr stdout csv ./StudentSharedDrivesCreated.csv gam update shareddrive "~id" [options/attributes as desired]
# Add ACLs granting the students organizer access to their Shared Drives.
gam redirect stdout ./StudentSharedDrivesAccess.txt multiprocess redirect stderr stdout csv StudentSharedDrivesCreated.csv gam add drivefileacl "~id" user "~primaryEmail" role organizer
```
## Update Shared Drive settings
These commands are used to set basic Shared Drive settings.
```
gam [<UserTypeEntity>] update teamdrive <SharedDriveEntity> [name <Name>]
[adminaccess|asadmin]
[(theme|themeid <String>)|
([customtheme <DriveFileID> <Float> <Float> <Float>] [color <ColorValue>])]
(<SharedDriveRestrictionsSubfieldName> <Boolean>)*
[hide|hidden <Boolean>] [ou|org|orgunit <OrgUnitItem>]
```
* `themeid` - a Shared Drive themeId obtained from `show teamdrivethemes`
* `customtheme` - set the backgroundImageFile property described here: https://developers.google.com/drive/v3/reference/teamdrives
* `color` - set the Shared Drive color
* `<SharedDriveRestrictionsSubfieldName> <Boolean>` - Set Shared Drive Restrictions
* `hidden <Boolean>` - Set Shared Drive visibility
* `ou|org|orgunit <OrgUnitItem>` - See: https://workspaceupdates.googleblog.com/2022/05/shared-drives-in-organizational-units-open-beta.html
This option is only available when the command is run as an administrator.
## Delete a Shared Drive
```
gam [<UserTypeEntity>] delete teamdrive <SharedDriveEntity>
[adminaccess|asadmin] [allowitemdeletion]
```
By default, deleting a Shared Drive that contains any files/folders will fail.
The `allowitemdeletion` option allows a Super Admin to delete a non-empty Shared Drive.
This is not reversible, proceed with caution.
## Change Shared Drive visibility
```
gam [<UserTypeEntity>] hide teamdrive <SharedDriveEntity>
gam [<UserTypeEntity>] unhide teamdrive <SharedDriveEntity>
```
## Display Shared Drives
These commands are used to get information about Shared Drives themselves, not the files/folders on the Shared Drives.
```
gam [<UserTypeEntity>] info teamdrive <SharedDriveEntity>
[adminaccess|asadmin]
[fields <SharedDriveFieldNameList>] [formatjson]
gam [<UserTypeEntity>] show teamdriveinfo <SharedDriveEntity>
[adminaccess|asadmin]
[fields <SharedDriveFieldNameList>] [formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam [<UserTypeEntity>] show teamdrives
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[matchname <RegularExpression>] [orgunit|org|ou <OrgUnitPath>]
[fields <SharedDriveFieldNameList>] [formatjson]
```
By default, all Shared Drives are displayed; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `matchname <RegularExpression>` - Retrieve Shared Drives with names that match a pattern.
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam [<UserTypeEntity>] print teamdrives [todrive <ToDriveAttribute>*]
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[matchname <RegularExpression>] [orgunit|org|ou <OrgUnitPath>]
[fields <SharedDriveFieldNameList>] [formatjson [quotechar <Character>]]
```
By default, all Shared Drives are displayed; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `matchname <RegularExpression>` - Retrieve Shared Drives with names that match a pattern.
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
### Examples
Print information about all Shared Drives in the organization.
```
gam print teamdrives
gam user admin@domain.com print teamdrives adminaccess
```
Print information about all Shared Drives in the organization with no organizers.
```
gam print teamdrives query "organizerCount = 0"
gam user admin@domain.com print teamdrives adminaccess teamdriveadminquery "organizerCount = 0"
```
Print information about Shared Drives that have admin@domain.com as a member.
```
gam user admin@domain.com print teamdrives
```
## Display List of Shared Drives in an Organizational Unit
To use this command you must add the `Cloud Identity API` to your project and authorize
the appropriate scope: `Cloud Identity OrgUnits API`.
You'll have to do `gam update project` and `gam oauth create` to enable this command.
```
gam show oushareddrives
[ou|org|orgunit <OrgUnitPath>]
[formatjson]
```
If `ou|org|orgunit <OrgUnitPath>` is not specified, `/` is used.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print oushareddrives [todrive <ToDriveAttribute>*]
[ou|org|orgunit <OrgUnitPath>]
[formatjson [quotechar <Character>]]
```
If `ou|org|orgunit <OrgUnitPath>` is not specified, `/` is used.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Manage Shared Drive access
These commands are used to manage the ACLs on Shared Drives themselves, not the files/folders on the Shared Drives.
### Process single ACLs.
```
gam [<UserTypeEntity>] add drivefileacl <SharedDriveEntityAdmin>
anyone|(user <UserItem>)|(group <GroupItem>)|(domain <DomainName>)
(role <DriveFileACLRole>) [withlink|(allowfilediscovery|discoverable [<Boolean>])]
[expires|expiration <Time>] [sendemail] [emailmessage <String>]
[showtitles] [nodetails]
[adminaccess|asadmin]
gam [<UserTypeEntity>] update drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail>
(role <DriveFileACLRole>) [expires|expiration <Time>] [removeexpiration [<Boolean>]]
[adminaccess|asadmin]
[showtitles] [nodetails]
gam [<UserTypeEntity>] delete drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail>
[showtitles]
[adminaccess|asadmin]
```
By default, when an ACL is added/updated, GAM outputs details of the ACL. The `nodetails` option
suppresses this output.
By default, the file ID is displayed in the output; to see the file name, use the `showtitles`
option; this requires an additional API call per file.
### Process multiple ACLs.
```
gam [<UserTypeEntity>] add permissions <SharedDriveEntityAdmin> <DriveFilePermissionEntity>
[expires|expiration <Time>] [sendemail] [emailmessage <String>]
<PermissionMatch>* [<PermissionMatchAction>]
[adminaccess|asadmin]
gam [<UserTypeEntity>] delete permissions <SharedDriveEntityAdmin> <DriveFilePermissionIDEntity>
<PermissionMatch>* [<PermissionMatchAction>]
[adminaccess|asadmin]
```
Permission matching only applies when the `<JSONData>`
variant of `<DriveFilePermissionEntity>` and `<DriveFilePermissionIDEntity>` is used.
When adding permissions from JSON data, there is a default match: `pm not role owner em` that disables ownership changes.
If you want to process all permissions, enter `pm em` to clear the default match.
When adding permissions from JSON data, permissions with `deleted` true are never processed.
When deleting permissions from JSON data, permissions with role `owner` true are never processed.
## Transfer Shared Drive access
These commands are used to transfer ACLs from one Shared Drive to another.
* `copy` - Copy all ACLs from the source Shared Drive to the target Shared Drive. The role of an existing ACL in the target Shared Drive will never be reduced.
* `sync` - Add/delete/update ACLs in the target Shared Drive to match those in the source Shared Drive.
```
gam [<UserTypeEntity>] copy teamdriveacls <SharedDriveEntity> to <SharedDriveEntity>
[showpermissionsmessages [<Boolean>]]
[excludepermissionsfromdomains|includepermissionsfromdomains <DomainNameList>]
(mappermissionsdomain <DomainName> <DomainName>)*
[adminaccess|asadmin]
gam [<UserTypeEntity>] sync teamdriveacls <SharedDriveEntity> with <SharedDriveEntity>
[showpermissionsmessages [<Boolean>]]
[excludepermissionsfromdomains|includepermissionsfromdomains <DomainNameList>]
(mappermissionsdomain <DomainName> <DomainName>)*
[adminaccess|asadmin]
```
When `excludepermissionsfromdomains <DomainNameList>` is specified, any ACL that references a domain in `<DomainNameList>` will not be copied.
When `includepermissionsfromdomains <DomainNameList>` is specified, only ACLs that reference a domain in `<DomainNameList>` will be copied.
When `mappermissionsdomain <DomainName> <DomainName>` is specifed, any ACL that references the first `<DomainName>` will be modified
to reference the second `<DonainName>` when copied; the original ACL is not modified. The option can be repeated if multiple domain names are to me mapped.
## Display Shared Drive access
These commands are used to display the ACLs on Shared Drives themselves, not the files/folders on the Shared Drives.
## Display Shared Drive access for specific Shared Drives
```
gam [<UserTypeEntity>] info drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail>
[showtitles] [formatjson]
[adminaccess|asadmin]
gam [<UserTypeEntity>] show drivefileacls <SharedDriveEntityAdmin>
<PermissionMatch>* [<PermissionMatchAction>] [pmselect]
[oneitemperrow] [showtitles] [<DrivePermissionsFieldName>*|(fields <DrivePermissionsFieldNameList>)]
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
[formatjson]
[adminaccess|asadmin]
gam [<UserTypeEntity>] print drivefileacls <SharedDriveEntityAdmin> [todrive <ToDriveAttribute>*]
<PermissionMatch>* [<PermissionMatchAction>] [pmselect]
[oneitemperrow] [showtitles] [<DrivePermissionsFieldName>*|(fields <DrivePermissionsFieldNameList>)]
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
[formatjson [quotechar <Character>]]
[adminaccess|asadmin]
```
### Examples:
Find all the organizers and file organizers on the Golgafrincham shared drive in CSV form.
```
gam print drivefileacls teamdrive "Golgafrincham" pm role organizer em pm role fileorganizer em oneitemperrow
```
By default, all Shared Drives specified are displayed; use the following option to select a subset of those Shared Drives.
* `<PermissionMatch>* [<PermissionMatchAction>] pmselect` - Use permission matching to select Shared Drives
By default, all ACLS are displayed; use the following option to select a subset of the ACLS to display.
* `<PermissionMatch>* [<PermissionMatchAction>]` - Use permission matching to display a subset of the ACLs for each Shared Drive; this only applies when `pmselect` is not specified
With `print drivefileacls` or `show drivefileacls formatjson`, the ACLs selected for display are all output on one row/line as a repeating item with the matching Shared Drive id.
When `oneitemperrow` is specified, each ACL is output on a separate row/line with the matching Shared Drive id. This simplifies processing the CSV file with subsequent Gam commands.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Shared Drive access for selected Shared Drives
```
gam [<UserTypeEntity>] show teamdriveacls
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[matchname <RegularExpression>] [orgunit|org|ou <OrgUnitPath>]
[user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)*
<PermissionMatch>* [<PermissionMatchAction>] [pmselect]
[oneitemperrow] [<DrivePermissionsFieldName>*|(fields <DrivePermissionsFieldNameList>)]
[shownopermissionsdrives false|true|only]
[formatjson]
gam [<UserTypeEntity>] print teamdriveacls [todrive <ToDriveAttribute>*]
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[matchname <RegularExpression>] [orgunit|org|ou <OrgUnitPath>]
[user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)*
<PermissionMatch>* [<PermissionMatchAction>] [pmselect]
[oneitemperrow] [<DrivePermissionsFieldName>*|(fields <DrivePermissionsFieldNameList>)]
[shownopermissionsdrives false|true|only]
[formatjson [quotechar <Character>]]
```
By default, all Shared Drives are displayed; use the following options to select a subset of Shared Drives:
* `teamdriveadminquery|query <QueryTeamDrive>` - Use a query to select Shared Drives
* `matchname <RegularExpression>` - Retrieve Shared Drives with names that match a pattern.
* `orgunit|org|ou <OrgUnitPath>` - Only Shared Drives in the specified Org Unit are selected
* `<PermissionMatch>* [<PermissionMatchAction>] pmselect` - Use permission matching to select Shared Drives
By default, Shared Drives with no permissions are not displayed; use the `shownopermissionsdrives` to control whether
Shared Drives with no permissions are displayed.
* `false` - Do not display Shared Drives with no permissions; this is the default
* `true` - Display Shared Drives with no permissions in addition to Shared Drives with permissions
* `only` - Display only Shared Drives with no permissions
By default, all ACLS are displayed; use the following options to select a subset of the ACLS to display.
* `user|group <EmailAddress> [checkgroups]` - Display ACLs for the specified `<EmailAddress>` only; if there is no ACL for `<EmailAddress>` and `checkgroups` is specified, display any ACLs for groups that have `<EmailAddress>` as a member.
* `role|roles <SharedDriveACLRoleList>` - Display ACLs for the specified roles only.
* `<PermissionMatch>* [<PermissionMatchAction>]` - Use permission matching to display a subset of the ACLs for each Shared Drive; this only applies when `pmselect` is not specified
With `print teamdriveacls` or `show teamdrivecls formatjson`, the ACLs selected for display are all output on one row/line as a repeating item with the matching Shared Drive id.
When `oneitemperrow` is specified, each ACL is output on a separate row/line with the matching Shared Drive id and name. This simplifies processing the CSV file with subsequent Gam commands.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
### Examples
Find all organizers and viewers on the shared drive Heart of Gold in CSV form.
```
gam print teamdriveacls matchname "Heart of Gold" role organizer,reader oneitemperrow
```
Print ACLs for all Shared Drives in the organization created after November 1, 2017.
```
gam print teamdriveacls teamdriveadminquery "createdTime > '2017-11-01T00:00:00'"
```
Print ACLs for all Shared Drives in the organization with foo@bar.com as an organizer.
```
gam print teamdriveacls user foo@bar.com role organizer
```
Print ACLs for all Shared Drives in the organization with foo@bar.com or groups that contain foo@bar.com as a reader.
```
gam print teamdriveacls user foo@bar.com role reader checkgroups
```
## Display ACLs for Shared Drives with no organizers
### For all Shared Drives
```
One row per Shared Drive, all ACLs on the same row
gam redirect csv ./SharedDriveACLsNoOrganizers.csv print teamdriveacls fields id,domain,emailaddress,role,type,deleted query "organizerCount = 0"
A row per Shared Drive/ACL combination
gam redirect csv ./SharedDriveACLsNoOrganizers.csv print teamdriveacls fields id,domain,emailaddress,role,type,deleted query "organizerCount = 0" oneitemperrow
```
### For selected Shared Drives
Create a CSV file TeamDrives.csv with at least two columns (id, name) for the selected Shared Drives.
```
One row per Shared Drive, all ACLs on the same row
gam redirect csv ./SharedDriveACLsNoOrganizers.csv multiprocess csv ./SharedDrives.csv gam print drivefileacls "~id" addtitle "~name" fields id,domain,emailaddress,role,type,deleted pm role organizer em pma skip pmselect
A row per Shared Drive/ACL combination
gam redirect csv ./SharedDriveACLsNoOrganizersOIPR.csv multiprocess csv ./SharedDrives.csv gam print drivefileacls "~id" addtitle "~name" fields id,domain,emailaddress,role,type,deleted pm role organizer em pma skip pmselect oneitemperrow
```
## Display ACLs for Shared Drives with all organizers outside of your domain
### For all Shared Drives
```
One row per Shared Drive, all ACLs on the same row
gam redirect csv ./SharedDriveACLsAllExternalOrganizers.csv print teamdriveacls fields id,domain,emailaddress,role,type,deleted role organizer pm role organizer domainlist domain.com,... em pma skip pmselect
A row per Shared Drive/ACL combination
gam redirect csv ./SharedDriveACLsAllExternalOrganizers.csv print teamdriveacls fields id,domain,emailaddress,role,type,deleted role organizer pm role organizer domainlist domain.com,... em pma skip pmselect
```
### For selected Shared Drives
Create a CSV file TeamDrives.csv with at least two columns (id, name) for the selected Shared Drives.
```
One row per Shared Drive, all ACLs on the same row
gam redirect csv ./SharedDriveACLsAllExternalOrganizers.csv multiprocess csv ./SharedDrives.csv gam print drivefileacls "~id" addtitle "~name" fields id,domain,emailaddress,role,type,deleted pm role organizer domainlist domain.com,... em pma skip pmselect
A row per Shared Drive/ACL combination
gam redirect csv ./SharedDriveACLsAllExternalOrganizersOIPR.csv multiprocess csv ./SharedDrives.csv gam print drivefileacls "~id" addtitle "~name" fields id,domain,emailaddress,role,type,deleted pm role organizer domainlist domain.com,... em pma skip pmselect
```
## Display ACLs for Shared Drives with all ACLs outside of your domain
### For all Shared Drives
Include a permission match `pm domainlist domain.com,... em` that lists your internal domain(s).
```
One row per Shared Drive, all ACLs on the same row
gam redirect csv ./SharedDriveACLsAllExternal.csv print teamdriveacls fields id,domain,emailaddress,role,type,deleted pm domainlist domain.com,... em pma skip pmselect
A row per Shared Drive/ACL combination
gam redirect csv ./SharedDriveACLsAllExternalOIPR.csv print teamdriveacls fields id,domain,emailaddress,role,type,deleted pm domainlist domain.com,... em pma skip pmselect oneitemperrow
```
### For selected Shared Drives
Create a CSV file TeamDrives.csv with at least two columns (id, name) for the selected Shared Drives.
Include a permission match `pm domainlist domain.com,... em` that lists your internal domain(s).
```
One row per Shared Drive, all ACLs on the same row
gam redirect csv ./SharedDriveACLsAllExternal.csv multiprocess csv ./SharedDrives.csv gam print drivefileacls "~id" addtitle "~name" fields id,domain,emailaddress,role,type,deleted pm domainlist domain.com,... em pma skip pmselect
A row per Shared Drive/ACL combination
gam redirect csv ./SharedDriveACLsAllExternalOIPR.csv multiprocess csv ./SharedDrives.csv gam print drivefileacls "~id" addtitle "~name" fields id,domain,emailaddress,role,type,deleted pm domainlist domain.com,... em pma skip pmselect oneitemperrow
```
## Clean up scammed Shared Drives
There is a scam where people are offered "Free Google Drive Space"; someone from your domain signed up for "Free Google Drive Space" and gave their domain credentials.
The scammers build a Shared Drive under those credentials, give themseleves access and then delete the original domain users credentials.
You are now hosting "Free Google Drive Space" for multiple non-domain users on this Shared Drive.
### Get scammed Shared Drive ACLs
Use the commands in [Display ACLs for Shared Drives with all ACLs outside of your domain](#display-acls-for-shared-drives-with-all-acls-outside-of-your-domain)
to get the Shared Drive ACLs for the scammed Shared Drives.
```
One row per Shared Drive, all ACLs on the same row
gam redirect csv ./SharedDriveACLsAllExternal.csv print teamdriveacls fields id,domain,emailaddress,role,type,deleted pm domainlist domain.com,... em pma skip pmselect
A row per Shared Drive/ACL combination
gam redirect csv ./SharedDriveACLsAllExternalOIPR.csv print teamdriveacls fields id,domain,emailaddress,role,type,deleted pm domainlist domain.com,... em pma skip pmselect oneitemperrow
```
### Add an organizer from your domain
Sustitute an appropriate value for `admin@domain.com`.
```
gam redirect stdout ./AddOrganizer.txt multiprocess redirect stderr stdout csv ./SharedDriveACLsAllExternal.csv gam add drivefileacl teamdriveid "~id" user admin@domain.com role organizer
```
### Delete non domain ACLs
Inspect `SharedDriveACLsAllExternal.csv` and verify that the list makes sense; delete any rows that could potentially be legitimate. If you delete a row,
you must delete all rows in `SharedDriveACLsAllExternalOIPR.csv` that have the same Shared Drive id value.
This will disable all non-domain users access to the Shared Drive.
```
gam redirect stdout ./DeleteExternalACLs.txt multiprocess redirect stderr stdout csv ./SharedDriveACLsAllExternalOIPR.csv gam delete drivefileacl teamdriveid "~id" "id:~~permission.id~~"
```
### Get all top-level files and folders from the Shared Drives; GAM versions before 6.21.00
Sustitute an appropriate value for `admin@domain.com`.
```
gam redirect csv ./TopLevelFilesFolders.csv multiprocess csv ./SharedDriveACLsAllExternal.csv gam user admin@domain.com print filelist select teamdriveid "~id" depth 0 fields id,name,driveid
```
### Purge all top-level files and folders from the Shared Drives; GAM versions before 6.21.00
This is not reversible, proceed with caution.
Sustitute an appropriate value for `admin@domain.com`.
```
gam redirect stdout ./DeleteTopLevelFilesFolders.txt multiprocess redirect stderr stdout csv ./TopLevelFilesFolders.csv gam user admin@domain.com purge drivefile "~id"
```
### Delete the Shared Drives; GAM versions before 6.21.00
This is not reversible, proceed with caution.
```
gam redirect stdout ./DeleteSharedDrives.txt multiprocess redirect stderr stdout csv ./SharedDriveACLsAllExternal.csv gam delete teamdrive "~id"
```
### Delete the Shared Drives; GAM versions 6.21.00 and later
The `allowitemdeletion` option allows deletion of non-empty Shared Drives. This option requires a Super Admin user.
This is not reversible, proceed with caution.
```
gam redirect stdout ./DeleteSharedDrives.txt multiprocess redirect stderr stdout csv ./SharedDriveACLsAllExternal.csv gam delete teamdrive "~id" allowitemdeletion
```

78
docs/Sites.md Normal file
View File

@ -0,0 +1,78 @@
# Sites
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Manage classic sites](#manage-classic-sites)
- [Display classic sites](#display-classic-sites)
- [Manage classic sites access](#manage-classic-sites-access)
- [Display classic sites access](#display-classic-sites-access)
## API documentation
* https://developers.google.com/google-apps/sites/docs/1.0/developers_guide_python
## Definitions
```
<Date> ::=
<Year>-<Month>-<Day> |
(+|-)<Number>(d|w|y) |
never|
today
<DomainName> ::= <String>(.<String>)+
<DomainNameList> ::= "<DomainName>(,<DomainName>)*"
<DomainNameEntity> ::=
<DomainNameList>|<FileSelector>|<CSVkmdSelector>| <CSVDataSelector>
<SiteName> ::= [a-z,0-9,-]+
<SiteItem> ::= [<DomainName>/]<SiteName>
<SiteList> ::= "<SiteItem>(,<SiteItem>)*"
<SiteEntity> ::=
<SiteList>|<FileSelector>|<CSVkmdSelector>|<CSVDataSelector>
<SiteACLRole> ::= editor|owner|reader|writer
<SiteACLRoleList> ::= "<SiteACLRole>(,<SiteACLRole>)*"
<SiteAttribute> ::=
(categories <String>)|
(name <String>)|
(sourcelink <URI>])|
(summary <String>)|
(theme <String>)
<SiteACLScope> ::=
<EmailAddress>|user:<EmailAdress>|group:<EmailAddress>|
domain:<DomainName>|domain|default
<SiteACLScopeList> ::= "<SiteACLScope>(,<SiteACLScope>)*"
<SiteACLScopeEntity> ::=
<SiteACLScopeList>|<FileSelector>|<CSVkmdSelector>|<CSVDataSelector>
```
## Manage classic sites
```
gam [<UserTypeEntity>] create site <SiteItem> <SiteAttribute>*
gam [<UserTypeEntity>] update sites <SiteEntity> <SiteAttribute>+
```
## Display classic sites
```
gam [<UserTypeEntity>] info sites <SiteEntity>
[withmappings] [role|roles all|<SiteACLRoleList>]
gam [<UserTypeEntity>] show sites [domain|domains <DomainNameEntity>] [includeallsites]
[withmappings] [role|roles all|<SiteACLRoleList>] [maxresults <Number>]
gam [<UserTypeEntity>] print sites [todrive <ToDriveAttribute>*]
[domain|domains <DomainNameEntity>] [includeallsites]
[withmappings] [role|roles all|<SiteACLRoleList>] [maxresults <Number>]
[convertcrnl] [delimiter <Character>]
gam [<UserTypeEntity>] print siteactivity <SiteEntity> [todrive <ToDriveAttribute>*]
[maxresults <Number>] [updated_min <Date>] [updated_max <Date>]
```
## Manage classic sites access
```
gam [<UserTypeEntity>] add siteacls <SiteEntity> <SiteACLRole> <SiteACLScopeEntity>
gam [<UserTypeEntity>] update siteacls <SiteEntity> <SiteACLRole> <SiteACLScopeEntity>
gam [<UserTypeEntity>] delete siteacls <SiteEntity> <SiteACLScopeEntity>
```
## Display classic sites access
```
gam [<UserTypeEntity>] info siteacls <SiteEntity> <SiteACLScopeEntity>
gam [<UserTypeEntity>] show siteacls <SiteEntity>
gam [<UserTypeEntity>] print siteacls <SiteEntity> [todrive <ToDriveAttribute>*]
```

269
docs/Tag-Replace.md Normal file
View File

@ -0,0 +1,269 @@
# Tag Replace
- [Python Regular Expressions](Python-Regular-Expressions) Sub function
- [Definitions](#definitions)
- [Introduction](#introduction)
- [Simple `replace <Tag> <String>` processing](#simple-replace-tag-string-processing)
- [User attribute `replace <Tag> <UserReplacement>` processing](#user-attribute-replace-tag-userreplacement-processing)
- [Example](#example)
## Definitions
```
<AddressSubfieldName> ::=
country|
countrycode|
customtype|
extendedaddress|
formatted|
locality|
pobox|
postalcode|
primary|
region|
streetaddress|
type
<EmailSubfieldName> ::=
domain|
primaryemail|
username
<ExternalIdSubfieldName> ::=
customtype|
type|
value
<GenderSubfieldName> ::=
addressmeas|
customgender|
type
<IMSubfieldName> ::=
customtype|
type|
value
<KeywordSubfieldName> ::=
customtype|
type|
value
<LocationSubfieldName> ::=
area|
buildingid|
buildingname|
customtype|
deskcode|
floorname|
floorsection|
type
<NameSubfieldName> ::=
familyname|
fullname|
givenname
<OrganizationSubfieldName> ::=
costcenter|
customtype|
department|
description|
domain|
fulltimeequivalent|
location|
name|
primary|
symbol|
title|
type
<OtherEmailSubfieldName> ::=
address|
customtype|
primary|
type
<PhoneSubfieldName> ::=
customtype|
primary|
type|
value
<PosixSubfieldName> ::=
accountid|
gecos|
gid|
homedirectory|
operatingsystemtype|
primary|
shell|
systemid|
uid|
username
<RelationSubfieldName> ::=
customtype|
type|
value
<SSHkeysSubfieldName> ::=
expirationtimeusec|
fingerprint|
key
<WebsiteSubfieldName> ::=
customtype|
primary|
type|
value
<UserReplacementFieldSubfield> ::=
address.<AddressSubfieldName>|
email.<EmailSubfieldName>|
externalid.<ExternalIdSubfieldName>|
gender.<GenderSubfieldName>|
im.<IMSubfieldName>|
keyword.<KeywordSubfieldName>|
location.<LocationSubfieldName>|
name.<NameSubfieldName>|
organization.<OrganizationSubfieldName>|
otheremail.<OtherEmailSubfieldName>|
phone.<PhoneSubfieldName>|
posix.<PosixSubfieldName>|
relation.<RelationSubfieldName>|
sshkeys.<SSHkeysSubfieldName>|
website.<WebsiteSubfieldName>|
<UserReplacementFieldSubfieldMatchSubfield> ::=
address.<AddressSubfieldName>.<AddressSubfieldName>.<String>|
externalid.<ExternalIdSubfieldName>.<ExternalIdSubfieldName>.<String>|
im.<IMSubfieldName>.<IMSubfieldName>.<String>|
keyword.<KeywordSubfieldName>.<KeywordSubfieldName>.<String>|
location.<LocationSubfieldName>.<LocationSubfieldName>.<String>|
organization.<OrganizationSubfieldName>.<OrganizationSubfieldName>.<String>|
otheremail.<OtherEmailSubfieldName>.<OtherEmailSubfieldName>.<String>|
phone.<PhoneSubfieldName>.<PhoneSubfieldName>.<String>|
posix.<PosixSubfieldName>.<PosixSubfieldName>.<String>|
relation.<RelationSubfieldName>.<RelationSubfieldName>.<String>|
sshkeys.<SSHkeysSubfieldName>.<SSHkeysSubfieldName>.<String>|
website.<WebsiteSubfieldName>.<WebsiteSubfieldName>.<String>
<Tag> ::= <String>
<UserReplacement> ::=
(field:<UserReplacementFieldSubfield>)|
(field:<UserReplacementFieldSubfieldMatchSubfield>)|
(schema:<SchemaName>.<FieldName>)|
<String>
```
## Introduction
Several commands use template files for messages and signatures; Gam has the ability to replace tags in the template with data from the command line or from user attributes.
## Simple `replace <Tag> <String>` processing
This command allows simple text replacement in the message.
```
gam sendemail <EmailAddressEntity> [from <UserItem>] [replyto <EmailAddress>]
[cc <EmailAddressEntity>] [bcc <EmailAddressEntity>] [singlemessage [<Boolean>]]
[subject <String>] [message <String>|(file <FileName> [charset <CharSet>])]
(replace <Tag> <String>)* [html [<Boolean>]] (attach <FileName>)*
```
* Every instance of `{Tag}` in the message will be replaced by `<String>`.
* Instances of the form `{RT}...{Tag1}...{Tag2}...{/RT}` will be eliminated if there are no `<String>` values for all `TagN` or if the `<String>` values are all empty strings.
* Instances of the form `{RTL}...{RT}...{Tag1}...{/RT}{RT}...{Tag2}...{/RT}{/RTL}` will be eliminated if none of the embedded `{RT}...{Tag}...{/RT}` have values.
You can control the case of the letters in `replace <Tag> <String>`:
* `{PC}...{Tag1}...{Tag2}...{/PC}` - For all sequences of letters between `{PC}` and `{/PC}`, the first letter is converted to uppercase, subsequent letters to lowercase.
* `{UC}...{Tag1}...{Tag2}...{/UC}` - All letters between `{UC}` and `{/UC}` will be converted to uppercase
* `{LC}...{Tag1}...{Tag2}...{/LC}` - All letters between `{LC}` and `{/LC}` will be converted to lowercase
## User attribute `replace <Tag> <UserReplacement>` processing
These commands allow simple text replacement in the message/signature as well as substitution of select user attributes.
```
gam create user <EmailAddress> <UserAttribute>*
[notify <EmailAddress>] [subject <String>]
[message <String>|(file <FileName> [charset <CharSet>])] [html [<Boolean>]]
(replace <Tag> <UserReplacement>)*
gam update user <UserItem> <UserAttribute>
[updateprimaryemail <RegularExpression> <EmailReplacement>]
[updateoufromgroup <FileName> [charset <CharSet>]
[columndelimiter <Character>] [quotechar <Character>]
[fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]]
[clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>]
[createifnotfound] [notify <EmailAddress>] [subject <String>]
[message <String>|(file <FileName> [charset <CharSet>])] [html [<Boolean>]]
(replace <Tag> <UserReplacement>)*
gam <UserTypeEntity> draft message (<SMTPDateHeader> <Time>)*
(<SMTPHeader> <String>)* (header <String> <String>)*
(addlabel <LabelName>)* [labels <LabelNameList>]
(textmessage|message <String>)|(textfile|file <FileName> [charset <CharSet>])
(htmlmessage <String>)|(htmlfile <FileName> [charset <CharSet>])
(replace <Tag> <UserReplacement>)* (attach <FileName> [charset <CharSet>])*
gam <UserTypeEntity> import message (<SMTPDateHeader> <Time>)*
(<SMTPHeader> <String>)*
(header <String> <String>)*
(addlabel <LabelName>)*
(textmessage <String>)|(textfile <FileName> [charset <CharSet>])
(htmlmessage <String>)|(htmlfile <FileName> [charset <CharSet>])
(replace <Tag> <UserReplacement>)* (attach <FileName>)*
[deleted [<Boolean>]] [nevermarkspam [<Boolean>]]
[processforcalendar [<Boolean>]]
gam <UserTypeEntity> insert message
(<SMTPDateHeader> <Time>)*
(<SMTPHeader> <String>)*
(header <String> <String>)*
(addlabel <LabelName>)*
(textmessage <String>)|(textfile <FileName> [charset <CharSet>])
(htmlmessage <String>)|(htmlfile <FileName> [charset <CharSet>])
(replace <Tag> <UserReplacement>)* (attach <FileName>)*
[deleted [<Boolean>]]
gam <UserTypeEntity> [create|add] sendas <EmailAddress> <String>
[signature|sig <String>|(file <FileName> [charset <CharSet>])
(replace <Tag> <UserReplacement>)*]
[html [<Boolean>]] [replyto <EmailAddress>]
[default] [treatasalias <Boolean>]
gam <UserTypeEntity> update sendas <EmailAddress>
[name <String>] [signature|sig <String>|(file <FileName> [charset <CharSet>])
(replace <Tag> <UserReplacement>)*]
[html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
gam <UserTypeEntity> signature|sig <String>|(file <FileName> [charset <Charset>])
(replace <Tag> <UserReplacement>)*
[html [<Boolean>]] [name <String>] [replyto <EmailAddress>]
[default] [primary] [treatasalias <Boolean>]
gam <UserTypeEntity> vacation <TrueValues> subject <String>
[message <String>|(file <FileName> [charset <CharSet>])]
(replace <Tag> <UserReplacement>)*
[html [<Boolean>]] [contactsonly [<Boolean>]] [domainonly [<Boolean>]]
[startdate <Date>|Started] [enddate <Date>|NotSpecified]
```
* Every instance of `{Tag}` in the message/signature will be replaced by `<UserReplacement>`.
* Instances of the form `{RT}...{Tag1}...{Tag2}...{/RT}` will be eliminated if there are no `<UserReplacement>` values for all `TagN` or if the `<UserReplacement>` values are all empty strings.
* Instances of the form `{RTL}...{RT}...{Tag1}...{/RT}{RT}...{Tag2}...{/RT}{/RTL}` will be eliminated if none of the embedded `{RT}...{Tag}...{/RT}` have values.
You can control the case of the letters in `replace <Tag> <UserReplacement>`:
* `{PC}...{Tag1}...{Tag2}...{/PC}` - For all sequences of letters between `{PC}` and `{/PC}`, the first letter is converted to uppercase, subsequent letters to lowercase.
* `{UC}...{Tag1}...{Tag2}...{/UC}` - All letters between `{UC}` and `{/UC}` will be converted to uppercase
* `{LC}...{Tag1}...{Tag2}...{/LC}` - All letters between `{LC}` and `{/LC}` will be converted to lowercase
`<UserReplacement>` specifies the data that replaces `{Tag}` in the message/signature.
* `field:<UserReplacementFieldSubfield>` - A subfield value from a user attribute
* For attributes `address`, `organization`, `otheremails` and `phone`, the attribute instance marked `primary` will be used. If there is no attribute instance marked `primary`, the first attribute instance will be used.
* For attribute `location`, the first attribute instance will be used.
* If `<UserReplacementFieldSubfield>` is empty or does not exist, an empty string will be used
* `field:<UserReplacementFieldSubfieldMatchSubfield>` - A subfield value from a user attribute where a second subfield value is used to select the attribute
* Select based on type: `phone.value.type.work`
* Select primary instance: `otheremails.address.primary.true`
* `schema:<SchemaName>.<FieldName>` - A custom schema value from the user's profile.
* `<String>` - A literal string in which the following substitutions will be made:
* `#email#` and `#user#` will be replaced by the user's primary email address
* `#username#` will be replaced by the local part of the user's primary email address
## Example
The file SigTemplate.txt contains:
```
<div dir='ltr' style='color:rgb(0,0,0);font-family:Helvetica;font-size:12px'>
<p>Name: {first} {last}<br />
{RT}Address: {address}<br />{/RT}
{RT}Department: {department}, Title: {title}<br />{/RT}
{RT}Location: Building: {building}, Floor: {floor}, Section: {section}, Desk: {desk}<br />{/RT}
{RTL}{RT}Office: {officephone} {/RT}{RT}Mobile: {mobilephone}{/RT}<br />{/RTL}
Email: {email}</p>
</div>
```
This command will update the signatures of the specified users.
* The `replace` arguments can appear in any order.
```
gam <UserTypeEntity> signature file SigTemplate.txt html
replace first field:name.givenname replace last field:name.familyname
replace officephone field:phone.value.type.work replace mobilephone field:phone.value.type.mobile
replace email field:email.primaryemail
replace address field:address.formatted
replace department field:organization.department replace title field:organization.title
replace building field:location.buildingname replace floor field:location.floorname
replace section field:location.floorsection replace desk field:location.deskcode
```

339
docs/Todrive.md Normal file
View File

@ -0,0 +1,339 @@
# Todrive
- [Introduction](#introduction)
- [Definitions](#definitions)
- [Config file options](#config-file-options)
- [Command line options](#command-line-options)
- [Option details](#option-details)
- [Upload user](#upload-user)
- [Create new file](#create-new-file)
- [File name, file description and sheet name](#file-name-file-description-and-sheet-name)
- [Spreadsheet settings](#spreadsheet-settings)
- [Open browser and send email](#open-browser-and-send-email)
- [Local copy](#local-copy)
- [Update existing file with a new sheet](#update-existing-file-with-a-new-sheet)
- [Add a new sheet to an existing file](#add-a-new-sheet-to-an-existing-file)
- [Update an existing sheet within an existing file](#update-an-existing-sheet-within-an-existing-file)
- [Handle CSV files with no data rows](#handle-csv-files-with-no-data-rows)
- [Redirect CSV](#redirect-csv)
- [Limited Service Account Access](#limited-service-account-access)
- [No Service Account Access](#no-service-account-access)
* [Authorization](Authorization)
## Introduction
Gam print commands allow the results to be uploaded to Google Drive instead of being saved locally.
By default, Gam titles the uploaded file: "Domain Name - Data Type"; Data Type describes the data being uploaded, e.g. Groups, Orgs, Users. It is uploaded to the root folder of the admin user named in `oauth2.txt`.
You can modify the default todrive behavior with options in `gam.cfg` or on the command line.
## Definitions
```
<DriveFileID> ::= <String>
<DriveFolderID> ::= <String>
<TimeZone> ::= <String>
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
<Locale> ::=
''| #Not defined
ar-eg| #Arabic, Egypt
az-az| #Azerbaijani, Azerbaijan
be-by| #Belarusian, Belarus
bg-bg| #Bulgarian, Bulgaria
bn-in| #Bengali, India
ca-es| #Catalan, Spain
cs-cz| #Czech, Czech Republic
cy-gb| #Welsh, United Kingdom
da-dk| #Danish, Denmark
de-ch| #German, Switzerland
de-de| #German, Germany
el-gr| #Greek, Greece
en-au| #English, Australia
en-ca| #English, Canada
en-gb| #English, United Kingdom
en-ie| #English, Ireland
en-us| #English, U.S.A.
es-ar| #Spanish, Argentina
es-bo| #Spanish, Bolivia
es-cl| #Spanish, Chile
es-co| #Spanish, Colombia
es-ec| #Spanish, Ecuador
es-es| #Spanish, Spain
es-mx| #Spanish, Mexico
es-py| #Spanish, Paraguay
es-uy| #Spanish, Uruguay
es-ve| #Spanish, Venezuela
fi-fi| #Finnish, Finland
fil-ph| #Filipino, Philippines
fr-ca| #French, Canada
fr-fr| #French, France
gu-in| #Gujarati, India
hi-in| #Hindi, India
hr-hr| #Croatian, Croatia
hu-hu| #Hungarian, Hungary
hy-am| #Armenian, Armenia
in-id| #Indonesian, Indonesia
it-it| #Italian, Italy
iw-il| #Hebrew, Israel
ja-jp| #Japanese, Japan
ka-ge| #Georgian, Georgia
kk-kz| #Kazakh, Kazakhstan
kn-in| #Kannada, India
ko-kr| #Korean, Korea
lt-lt| #Lithuanian, Lithuania
lv-lv| #Latvian, Latvia
ml-in| #Malayalam, India
mn-mn| #Mongolian, Mongolia
mr-in| #Marathi, India
my-mn| #Burmese, Myanmar
nl-nl| #Dutch, Netherlands
nn-no| #Nynorsk, Norway
no-no| #Bokmal, Norway
pa-in| #Punjabi, India
pl-pl| #Polish, Poland
pt-br| #Portuguese, Brazil
pt-pt| #Portuguese, Portugal
ro-ro| #Romanian, Romania
ru-ru| #Russian, Russia
sk-sk| #Slovak, Slovakia
sl-si| #Slovenian, Slovenia
sr-rs| #Serbian, Serbia
sv-se| #Swedish, Sweden
ta-in| #Tamil, India
te-in| #Telugu, India
th-th| #Thai, Thailand
tr-tr| #Turkish, Turkey
uk-ua| #Ukrainian, Ukraine
vi-vn| #Vietnamese, Vietnam
zh-cn| #Simplified Chinese, China
zh-hk| #Traditional Chinese, Hong Kong SAR China
zh-tw #Traditional Chinese, Taiwan
```
## Config file options
You can specify many `todrive` options in `gam.cfg`.
```
todrive_clearfilter
Enable/disable clearing the spreadsheet basic filter when uploading data to an existing sheet in an existing file.
Default: False
todrive_clientaccess
Enable/disable use of client access rather than service account access when uploading files with todrive
Default: False
todrive_conversion
Enable/disable conversion of CSV files to Google Sheets when todrive is specified
Default: True
todrive_localcopy
Enable/disable saving a local copy of CSV files when todrive is specified
Default: False
todrive_locale
The Spreadsheet settings Locale value.
See <Locale>
Default: ''
todrive_nobrowser
Enable/disable opening a browser when todrive is specified
Default: False
todrive_noemail
Enable/disable sending an email when todrive is specified
Default: True
todrive_parent
Parent folder for CSV files when todrive is specified;
can be id:<DriveFolderID> or <DriveFolderName>
Default: root
todrive_sheet_timestamp
Enable/disable adding a timestamp to the sheet (tab) title of CSV files when todrive is specified
Default: False
todrive_sheet_timeformat
Format of the timestamp added to the sheet (tab) title of CSV files
See: https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior
Default: '' which selects an ISO format timestamp
Example: %Y-%m-%dT%H:%M:%S will display as 2020-07-06T17:48:54
todrive_timestamp
Enable/disable adding a timestamp to the title of CSV files when todrive is specified
Default: False
todrive_timeformat
Format of the timestamp added to the title of CSV files
See: https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior
Default: '' which selects an ISO format timestamp
Example: %Y-%m-%dT%H:%M:%S will display as 2020-07-06T17:48:54
todrive_timezone
The Spreadsheet settings Timezone value.
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
Default: ''
todrive_upload_nodata
Enable/disable uploading CSV files with no data rows
Default: True
todrive_user
Email address of user to receive CSV files when todrive is specified
Default: '' which becomes admin user in admin_email or address from oauth2.txt
```
## Command line options
Anywhere you can specify `todrive`, there are additional subarguments following the `todrive` argument that let you title the file, add a description, specify the sheet name,
direct the uploaded file to a particular user and location and add a timestamp to the file title.
```
<ToDriveAttribute> ::=
(tdaddsheet [<Boolean>])|
(tdbackupsheet (id:<Number>)|<String>)|
(tdclearfilter [<Boolean>])|
(tdcopysheet (id:<Number>)|<String>)|
(tddescription <String>)|
(tdfileid <DriveFileID>)|
(tdlocalcopy [<Boolean>])|
(tdlocale <Locale>)|
(tdnobrowser [<Boolean>])|
(tdnoemail [<Boolean>])|
(tdparent (id:<DriveFolderID>)|<DriveFolderName>)|
(tdretaintitle [<Boolean>])|
(tdshare <EmailAddress> commenter|reader|writer)|
(tdsheet (id:<Number>)|<String>)|
(tdsheettimestamp [<Boolean>] [tdsheettimeformat <String>])
(tdsheettitle <String>)|
([tdsheetdaysoffset <Number>] [tdsheethoursoffset <Number])|
(tdtimestamp [<Boolean>] [tdtimeformat <String>])|
([tddaysoffset <Number>] [tdhoursoffset <Number])|
(tdtimezone <TimeZone>)|
(tdtitle <String>)|
(tdcellwrap clip|overflow|wrap)|
(tdcellnumberformat text|plain)|
(tdupdatesheet [<Boolean>])|
(tduploadnodata [<Boolean>])|
(tduser <EmailAddress>)
```
## Option details
By default, a new Google spreadsheet will be created.
Gam titles the uploaded file: "Domain Name - Data Type"; Data Type describes the data being uploaded, e.g. Groups, Orgs, Users.
It is uploaded to the root folder of the admin user named in `oauth2.txt`.
## Upload user
* `tduser` - The user to receive the uploaded file; if not specified, the `todrive_user` value from gam.cfg is used; that value defaults to the user named in oauth2.txt.
## Create new file
If `tdfileid <DriveFileID>` is not specified, a new file is created.
* `tdparent` - An existing/writable parent folder for the uploaded file; if not specified, the `todrive_parent` value from gam.cfg is used; that value defaults to the root folder.
* `tdshare <EmailAddress> commenter|reader|writer` - Share the new file with `<EmailAddress>` with the specified role. `<EmailAddress>` must be valid within your Google Workspace.
## File name, file description and sheet name
* `tdtitle` - The title for the uploaded file, if not specified, the Gam default title is used.
* `tddescription` - The description for the uploaded file, if not specified, the command line that created the file is used.
* `tdsheettitle <String>` - The sheet name in the uploaded file if it is uploaded as a Google Sheet, if not specified, the `tdtitle` is used.
* `tdsheettimestamp` - Should a timestamp (of the time the file is uploaded to Google) be added to the sheet (tab) title of the uploaded file; if not specified, the `todrive_sheet_timestamp` value from gam.cfg is used, that value defaults to False.
* `tdsheettimeformat` - Format of the timestamp added to the sheet (tab) title of the uploaded file; if not specified, the `todrive_sheet_timeformat` value from gam.cfg is used, that value defaults to '' which selects an ISO format timestamp.
* `tdsheetdaysoffset` and `tdsheethoursoffset` - Values that subtract time from the sheet (tab) timestamp. If neither value is specified, the `tddaysoffset` and `tdhoursoffset` values are used. To use a file timestamp offset, but not a sheet (tab) timestamp offset, specify `tdsheetdaysoffset 0`. A possible use for these values is as documentation to reflect the end of the time period that the uploaded report covers.
* `tdtimestamp` - Should a timestamp (of the time the file is uploaded to Google) be added to the title of the uploaded file; if not specified, the `todrive_timestamp` value from gam.cfg is used, that value defaults to False.
* `tdtimeformat` - Format of the timestamp added to the title of the uploaded file; if not specified, the `todrive_timeformat` value from gam.cfg is used, that value defaults to '' which selects an ISO format timestamp.
* See: https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior
* `tddaysoffset` and `tdhoursoffset` - Values that subtract time from the timestamp, they default to 0. A possible use for these values is as documentation to reflect the end of the time period that the uploaded report covers.
## Spreadsheet settings
* `tdlocale <Locale>` - The Spreadsheet settings Locale value.
* `tdtimezone <TimeZone>` - The Spreadsheet settings Timezone value.
* `tdcellwrap clip|overflow|wrap` - The Spreadsheet cell wrapping strategy.
* `tdcellnumberformat text|number` - The Spreadsheet number format.
## Open browser and send email
* `tdnobrowser` - If False, a browser is opened to view the file uploaded to Google Drive; if not specified, the `todrive_nobrowser` value from gam.cfg is used.
* `tdnoemail` - If False, an email is sent to `tduser` informing them of name and URL of the uploaded file; if not specified, the `todrive_noemail` value from gam.cfg is used.
## Local copy
* `tdlocalcopy` - Should a local copy of the CSV file be saved in addition to the file uploaded to Google Drive; if not specified, the `todrive_localcopy` value from gam.cfg is used.
## Update existing file with a new sheet
* `tdfileid <DriveFileID>` - An existing/writable file for the uploaded file.
* `tdretaintitle`or `tdretaintitle true` - Do not update the existing file name.
* `tdsheettitle <String>` - A new sheet with name `<String>` will be created and assigned a new sheet ID. All other sheets will be deleted.
## Add a new sheet to an existing file
* `tdfileid <DriveFileID>` - An existing/writable file for the uploaded file.
* `tdretaintitle`or `tdretaintitle true` - Do not update the existing file name.
* `tdsheet <String>` - The title of the new sheet; if not specified, this will be the same value as `tdtitle`.
* `tdaddsheet` - In conjunction with `tdfileid <DriveFileID>` and `tdsheet <String>`, a new sheet will be added to an existing/writeable file. All other sheets are unaffected.
## Update an existing sheet within an existing file
* `tdfileid <DriveFileID>` - An existing/writable file for the uploaded file.
* `tdretaintitle`or `tdretaintitle true` - Do not update the existing file name.
* `tdsheet (id:<Number>)|<String>` - An existing sheet with ID `<Number>` or name `<String>` will be updated. All other sheets are unaffected.
* `tdupdatesheet` - In conjunction with `tdfileid <DriveFileID>` and `tdsheet id:<Number>`, an existing sheet in an existing/writeable file is updated.
* `tdsheettitle` - In conjunction with `tdfileid <DriveFileID>` and `tdsheet id:<Number>` and `tdupdatesheet`, an existing sheet in an existing/writeable file is updated and renamed.
* `tdupdatesheet` - In conjunction with `tdfileid <DriveFileID>` and `tdsheet <String>`, an existing sheet in an existing/writeable file is updated; it will be created if necessary.
* `tdbackupsheet (id:<Number>)|<String>` - An existing sheet will be updated with the contents of `tdsheet (id:<Number>)|<String>)` before that sheet is updated.
* `tdcopysheet (id:<Number>|<String>` - An existing sheet will be updated with the contents of `tdsheet (id:<Number>)|<String>)` after that sheet is updated.
* `tdclearfilter [<Boolean>]` - Should the spreadsheet basic filter be cleared; if not specified, the `todrive_clearfilter` value from gam.cfg is used, that value defaults to False. When False, the current/default behavior, the data suppressed by an existing filter is not replaced by the uploaded data. This might be desirable if you wanted to compare the previous and current data, but in general you probably want a value of True so that the uploaded data completely replaces the existing data.
## Handle CSV files with no data rows
* `tduploadnodata` - Enable/disable uploading CSV files with no data rows; if not specified, the `todrive_upload_nodata` value from gam.cfg is used; that value defaults to true
## Redirect CSV
You can specify `todrive` options in conjunction with `redirect csv`.
```
redirect csv <FileName> [multiprocess] [append] [noheader] [charset <Charset>]
[columndelimiter <Character>] [quotechar <Character>]
[todrive <ToDriveAttribute>*]
```
If you are doing `redirect csv <FileName> multiprocess`, it is more efficient to specify `todrive <ToDriveAttribute>*` as part of
the redirect as verification of the `todrive` settings, which can invole several API calls, is done once rather than in each of the subprocesses.
`columndelimiter <Character>` and `quotechar <Character>` will not generally be used with `todrive` as
Google Sheets only recognizes `,` as the column delimiter and `"` as the quote character.
## Examples
Generate a list of user IDs and names, title the file "User IDs and Names", upload it to the "GAM Reports" folder of usermgr@domain.com, add a timestamp to the title.
```
gam print users fields id,name todrive tdtitle "User IDs and Names" tdtimestamp true tduser usermgr@domain.com tdparent "GAM Reports"
```
Generate a list of CrOS devices and update an existing sheet in a Google spreadsheet. The sheet ID is preserved so other appplications can access the data using the file ID and sheet ID.
By setting 'tdtimestamp true`, the file name will the updated to reflect the time of execution, but the file ID will not change.
```
gam redirect csv - todrive tdtitle "CrOS" tdtimestamp true tdfileid 12345-mizZ6Q2vP1rcHQH3tAZQt_NVB2EOxmS2SU3yM tdsheet id:0 tdupdatesheet true print cros fields deviceId,notes,orgUnitPath,serialNumber,osversion
```
For a collection of users, generate a list of files shared with anyone; combine the output for all users into a single file.
```
gam redirect csv - multiprocess todrive tdtitle AnyoneShares-All csv Users.csv gam user ~primaryEmail print filelist fields id,name,permissions pm type anyone em
```
For a collection of users, generate a list of files shared with anyone; generate a separate file for each user.
The two forms of the command are equivalent.
```
gam csv Users.csv gam redirect csv - todrive tdtitle "AnyoneShares-~~primaryEmail~~" user ~primaryEmail print filelist fields id,name,permissions pm type anyone em
gam csv Users.csv gam user ~primaryEmail print filelist fields id,name,permissions pm type anyone em todrive tdtitle "AnyoneShares-~~primaryEmail~~"
```
Suppose you have a spreadsheet with sheets `Monday` ... `Friday`, `Backup Monday` ... `Backup Friday` and `Latest`.
Each day you run a report to update the current day sheet (`Tuesday`), you want to backup the data first (`Backup Tuesday`) and
you want the updated data copied to `Latest` so you don't have to remember what the day of the week is.
```
gam redirect csv - todrive tdfileid <DriveFileID> tdupdatesheet tdsheet Tuesday tdbackupsheet "Backup Tuesday" tdcopysheet "Latest" ...
```
## Limited Service Account Access
If you want to limit a user's service account access but still allow `todrive',
issue the following command and authorize the additional service account APIs:
```
gam user user@domain.com update serviceaccount`
Authorize these APIs:
Drive API - todrive
Gmail API - Send Messages - including todrive
Sheets API - todrive
```
## No Service Account Access
By default, `todrive` uses service account access to upload files, set sheet names and send email notifications.
If it is not possible to allow the user any service account access (this is not common),
perform the following command so that the user can upload files with `todrive` using client access.
```
gam config todrive_clientaccess true save
```
Issue the following command and authorize the additional client access APIs:
```
gam oauth create
Authorize these APIs:
Drive API - todrive_clientaccess
Gmail API - todrive_clientaccess
Sheets API - todrive_clientaccess
```
When `todrive_clientaccess` is true, `todrive_user\tduser` is ignored, all actions are performed as the user specified in `oauth2.txt`.

113
docs/Unmanaged-Accounts.md Normal file
View File

@ -0,0 +1,113 @@
# Unmanaged Accounts
- [API documentation](#api-documentation)
- [Notes](#notes)
- [Collections of Users](Collections-of-Users)
- [Definitions](#definitions)
- [Send an invitation](#send-an-invitation)
- [Cancel an invitation](#cancel-an-invitation)
- [Check status of an invitation](#check-status-of-an-invitation)
- [Display invitations status](#display-invitations-status)
- [Verify eligibility for invitation](#verify-eligibility-for-invitation)
- [Bulk verify eligibility for invitation](#bulk-verify-eligibility-for-invitation)
## API documentation
* https://support.google.com/a/answer/6178640
* https://cloud.google.com/identity/docs/how-to/manage-user-invitations
* https://cloud.google.com/identity/docs/reference/rest/v1beta1/customers.userinvitations
## Notes
Unmanaged accounts occur when a user registers for a personal Google account using an email address that matches your domain.
These accounts generally exist because a user has previously signed up for a personal Google Account using their work or educational email address.
If your attempts to provision a managed account with the same primary email address, the conflict needs to be resolved.
You can send an invitation to an unmanaged account asking them to join and be managed by your domain.
To use these features you must add the `Cloud Identity API` to your project and authorize
the appropriate scope: `Cloud Identity User Invitations API`.
```
gam update project
gam oauth create
```
## Definitions
```
<UserInvitationOrderByFieldName> ::=
email|
updatetime
```
## Send an invitation
```
gam send userinvitation <EmailAddress>
```
## Cancel an invitation
```
gam cancel userinvitation <EmailAddress>
```
## Check status of an invitation
```
gam info userinvitation <EmailAddress> [formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
## Display invitations status
This is the same list as found at: Admin Console/Users/More (top right)/Transfer tool for unmanaged users
```
gam show userinvitations
[state notyetsent|invited|accepted|declined]
[orderby email|updatetime [ascending|descending]]
[formatjson]
```
By default, all invitations are shown; you can filter the invitations based on state.
* `state notyetsent` - The UserInvitation has been created and is ready for sending as an email
* `state invited` - The user has been invited by email
* `state accepted` - The user has accepted the invitation and is part of the organization
* `state declined` - The user declined the invitation
By default, invitations are show in ascending order by email address, use `orderby` to change the ordering.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam print userinvitations [todrive <ToDriveAttribute>*]
[state notyetsent|invited|accepted|declined]
[orderby email|updatetime [ascending|descending]]
[[formatjson [quotechar <Character>]]
```
By default, all invitations are shown; you can filter the invitations based on state.
* `state notyetsent` - The UserInvitation has been created and is ready for sending as an email
* `state invited` - The user has been invited by email
* `state accepted` - The user has accepted the invitation and is part of the organization
* `state declined` - The user declined the invitation
By default, invitations are show in ascending order by email address, use `orderby` to change the ordering.
By default, Gam displays the information as columns of fields.
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Verify eligibility for invitation
Verify whether a user account is eligible to receive an invitation (is an unmanaged account).
Eligibility is based on the following criteria:
* the email address is a consumer account and it's the primary email address of the account, and
* the domain of the email address matches an existing verified Google Workspace or Cloud Identity domain
If both conditions are met, the user is eligible/invitable.
```
gam check isinvitable <EmailAddress>
```
Gam displays the information as an indented list of keys and values.
## Bulk verify eligibility for invitation
```
gam <UserTypeEntity> check isinvitable [todrive <ToDriveAttribute>*]
```
Gam displays the invitable users in CSV format with the header `invitableUsers`.

262
docs/Upgrade-Benefits.md Normal file
View File

@ -0,0 +1,262 @@
# Upgrade Benefits
- [Configuration](#Configuration)
- [Syntax Checking](#syntax-checking)
- [API error checking](#api-error-checking)
- [Batch files](#batch-files)
- [CSV processing redirects](#csv-processing-redirects)
- [Data selection](#data-selection)
- [Specifying Google Drive files](#specifying-google-drive-files)
- [Uploading CSV files from gam print commands to Google Drive](#uploading-csv-files-from-gam-print-commands-to-google-drive)
- [Calendars](#calendars)
- [Contacts](#contacts)
- [Courses](#courses)
- [Data Studio](#data-studio)
- [Drive File Copy and Move](#drive-file-copy-and-move)
- [Drive File Orphans](#drive-file-orphans)
- [Drive File Ownership](#drive-file-ownership)
- [Drive File Revisions](#drive-file-revisions)
- [Drive File Transfer](#drive-file-transfer)
- [Send email messages](#send-email-messages)
- [Forms](#forms)
- [Gmail](#gmail)
- [Groups](#groups)
- [Keep](#keep)
- [Organizational Units](#organizational-units)
- [Resource Calendars](#resource-calendars)
- [Shared Drives](#shared-drives)
- [Spreadsheets](#Spreadsheets)
- [Tasks](#tasks)
## Configuration
GAMADV-XTD3 uses a configuration file, gam.cfg, to store the values of the various environment variables
and signal files used by earlier versions of GAM. Configuration files client_secrets.json, oauth2.txt, oauth2service.json and extra_args.txt
are moved to a version independent location. This should simplify upgrading GAM versions in the future.
Additionally, if you support multiple clients/domains or have multiple users running GAM,
gam.cfg lets you easily manage your configuration.
See: [gam.cfg](gam.cfg)
## Syntax Checking
GAMADV-XTD3 produces better error messages when syntax errors are found on the command line.
## API error checking
In GAM, most API calls are made without error handling; if an API call fails for a particular item and the command
was an operation on multiple items, the items after the failing item are not processed. The GAM solution is to have
you produce a CSV file containing the items you want to process; as each item is an independent excution, API failures for some items
do not affect other items. Capturing meaningful output from the CSV execution is hard and you have to create the CSV file as a separate step.
In GAMADV-XTD3, every API call is made with error handling; if an API call fails, a message is output and execution continues with additional items if possible.
## Batch files
GAM uses multiprocessing for processing batch files and CSV files; this offers better performance than using threads. Unfortunately, one
multiprocess subprocess can not create another subprocess; this prevents using gam csv commands inside GAM batch files.
GAMADV-XTD3 supports two commands for processing batch files, batch and tbatch. gam batch uses multiprocessing and gam tbatch uses threads.
If you have a batch file that contains gam csv commands, gam tbatch can successfuly process the batch file.
See: [Bulk Processing](Bulk-Processing)
## CSV processing redirects
With GAM, if you want to process a CSV file and capture the output, you do one of the following:
```
gam csv File.csv gam <Command> > File.out 2> File.err
gam csv File.csv gam <Command> > File.out 2>&1
```
Multiple processes are writing to File.out(.err) simultaneously resulting in interleaved output that can be hard to read.
With GAMADV-XTD3, you can capture the output from the multiple processes such that all of the output from each process is contiguous.
```
gam redirect stdout ./File.out multiprocess redirect stderr ./File.err multiprocess csv File.csv gam <Command>
gam redirect stdout ./File.out multiprocess redirect stderr stderr csv File.csv gam <Command>
```
You can choose to have GAMADV-XTD3 bracket the output from each process with lines that show the command being executed.
```
gam config show_multiprocess_info true redirect stdout ./File.out multiprocess redirect stderr ./File.err multiprocess csv File.csv gam <Command>
gam config show_multiprocess_info true redirect stdout ./File.out multiprocess redirect stderr stderr csv File.csv gam <Command>
```
See: [Meta Commands and File Redirection](Meta-Commands-and-File-Redirection)
## Data selection
GAMADV-XTD3 has many more ways to specify collections of ChromeOS devices, Users and other items.
See: [Collections of ChromeOS Devices](Collections-of-ChromeOS-Devices)
See: [Collections of Users](Collections-of-Users)
See: [Collections of Items](Collections-of-Items)
## Specifying Google Drive files
GAM specifies drive files in different ways based on the command.
GAMADV-XTD3 has a consistent way of specifying Google Drive files for all commands.
See: [Drive File Selection](Drive-File-Selection)
## Uploading CSV files from gam print commands to Google Drive
GAM allows no options when you use the todrive option with a gam print command; the file is always uploaded with a fixed name to the root folder of
Google Drive for the Google Admin user named in oauth2.txt.
GAMADV-XTD3 allows you to specify the name, location and user for files uploaded with todrive; you can also save a local copy of the file.
See: [Todrive](Todrive)
## Calendars
GAM can manage the list of calendars a user can view; GAMADV-XTD3 can also create, modify and remove calendars.
GAM can add and delete events; GAMADV-XTD3 can also update, move, show and print events.
GAM can add, update, delete and show calendar ACLs; GAMADV-XTD3 can also get ACLs for a single calendar and print a CSV file of calendar ACLs.
See: [Calendars - Access](Calendars-Access), [Calendars - Events](Calendars-Events)
See: [Users - Calendars - List](Users-Calendars-List)
See: [Users - Calendars](Users-Calendars)
See: [Users - Calendars - Events](Users-Calendars-Events)
See: [Users - Calendars - Transfer](Users-Calendars-Transfer)
## Contacts
GAMADV-XTD3 supports domain shared contacts and user contacts.
See: [Domain Shared Contacts](Contacts)
See: [Users - People - Contacts & Profiles](Users-People-Contacts-Profiles)
## Courses
When updating a course, GAM can only add/delete a single alias; GAMADV-XTD3 can add/delete multiple aliases.
When updating a course's membership, GAM can only add/delete a single student/teacher; GAMADV-XTD3 can
add/delete multiple students/teachers.
When creating/updating courses, GAMADV-XTD3 can copy settings from another course.
See: [Courses](Courses)
## Data Studio
GAMADV-XTD3 supports commands to display Data Studio assets and display/manage Data Studio permissions
See: [Users - Data Studio](Users-DataStudio)
## Drive File Copy and Move
GAMADV-XTD3 supports advanced file/folder copying/moving
See: [Users - Drive - Copy/Move](Users-Drive-Copy-Move)
## Drive File Orphans
GAMADV-XTD3 allows collecting a user's orphaned files.
See: [Users - Drive - Orphans](Users-Drive-Orphans)
## Drive File Ownership
GAMADV-XTD3 allows transferring ownership of selected folders of a source user to a target user.
GAMADV-XTD3 allows claiming ownership of of selected folders to which the user has access.
See: [Users - Drive - Ownership](Users-Drive-Ownership)
## Drive File Revisions
GAMADV-XTD3 can manage drive file revisions.
## Drive File Transfer
GAMADV-XTD3 has more capabilites for transferring the Google Drive of a source user to a target user.
See: [Users - Drive - Transfer](Users-Drive-Transfer)
See: [Users - Drive - Revisions](Users-Drive-Revisions)
## Send email messages
GAMADV-XTD3 can send email messages.
See: [Send Email](Send-Email)
## Forms
GAMADV-XTD3 supports commands to manage and display Google Forms.
See: [Users - Forms](Users-Forms)
## Gmail
GAMADV-XTD3 has commands for displaying Gmail messages.
GAMADV-XTD3 has commands for forwarding Gmail messages.
See: [Users - Gmail - Messages/Threads](Users-Gmail-Messages-Threads)
## Groups
GAMADV-XTD3 allows selecting fields with `info group`. The output is much easier to read.
When creating/updating groups, GAMADV-XTD3 can copy settings from another group.
See: [Groups](Groups)
GAMADV-XTD3 has a more powerful `print group-members` command.
GAMADV-XTD3 has a more powerful ways of specifying changes to group membership.
See: [Groups Membership](Groups-Membership)
GAMADV-XTD3 has commands to display/manage a user's group membership.
See: [Users - Group Membership](Users-Group-Membership)
## Keep
GAMADV-XTD3 supports commands to manage and display Google Keep notes.
See: [Users - Keep](Users-Keep)
## Organizational Units
GAMADV-XTD3 supports updating multiple org units in a single command.
See: [Organizational Units](Organizational-Units)
## Resource Calendars
GAMADV-XTD3 supports managing resource calendar ACLs.
See: [Resource Calendars](Resource-Calendars)
## Shared Drives
GAMADV-XTD3 has more powerful commands for managing Shared Drives.
See: [Shared Drives](Shared-Drives)
See: [Users - Shared Drives](Users-Shared-Drives)
## Spreadsheets
GAMADV-XTD3 can manipulate Google Sheets.
See: [Users - Spreadsheets](Users-Spreadsheets)
## Tasks
GAMADV-XTD3 supports commands to manage and display Google Tasks.
See: [Users - Tasks](Users-Tasks)

View File

@ -0,0 +1,193 @@
# Users - Analytics Admin
- [API documentation](#api-documentation)
- [Notes](#notes)
- [Collections of Users](Collections-of-Users)
- [Display Analytic Accounts](#display-analytic-accounts)
- [Display Analytic Account Summaries](#display-analytic-account-summaries)
- [Display Analytic Properties](#display-analytic-properties)
- [Display Analytic Datastreams](#display-analytic-datastreams)
- [Display Analytic UA Properties](#display-analytic-ua-properties)
- [Examples](#examples)
## API documentation
* https://developers.google.com/analytics/devguides/config/admin/v1/rest
## Notes
To use these commands you must add 'Analytics API' and 'Analytics Admin API' to your project and update your service account authorization.
```
gam update project
gam user user@domain.com check serviceaccount
```
## Display Analytic Accounts
```
gam <UserTypeEntity> show analyticaccounts
[maxresults <Number>] [showdeleted [<Boolean>]]
[formatjson]
```
By default, deleted accounts are not displayed, use `showdeleted` to display them.
By default, GAM asks the API for 50 accounts per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print analyticaccounts [todrive <ToDriveAttribute>*]
[maxresults <Number>] [showdeleted [<Boolean>]]
[formatjson [quotechar <Character>]]
```
By default, deleted accounts are not displayed, use `showdeleted` to display them.
By default, GAM asks the API for 50 accounts per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Analytic Account Summaries
```
gam <UserTypeEntity> show analyticaccountsummaries
[maxresults <Number>]
[formatjson]
```
By default, GAM asks the API for 50 account summaries per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print analyticaccountsummaries [todrive <ToDriveAttribute>*]
[maxresults <Number>]
[formatjson [quotechar <Character>]]
```
By default, GAM asks the API for 50 account summaries per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Analytic Properties
```
gam <UserTypeEntity> show analyticproperties
filter <String>
[maxresults <Number>] [showdeleted [<Boolean>]]
[formatjson]
```
The required `filter <String>` must be in the format: 'parent:accounts/123', 'parent:properties/123', 'ancestor:accounts/123' or 'firebase_project:123'
By default, deleted properties are not displayed, use `showdeleted` to display them.
By default, GAM asks the API for 50 properties per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print analyticproperties [todrive <ToDriveAttribute>*]
filter <String>
[maxresults <Number>] [showdeleted [<Boolean>]]
[formatjson [quotechar <Character>]]
```
The required `filter <String>` must be in the format: 'parent:accounts/123', 'parent:properties/123', 'ancestor:accounts/123' or 'firebase_project:123'
By default, deleted properties are not displayed, use `showdeleted` to display them.
By default, GAM asks the API for 50 properties per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Analytic Datastreams
```
gam <UserTypeEntity> show analyticdatastreams
parent <String>
[maxresults <Number>]
[formatjson]
```
The required `parent <String>` must be in the format: 'properties/123'.
By default, GAM asks the API for 50 datastreams per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print analyticdatastreams [todrive <ToDriveAttribute>*]
parent <String>
[maxresults <Number>]
[formatjson [quotechar <Character>]]
```
The required `parent <String>` must be in the format: 'properties/123'.
By default, GAM asks the API for 50 datastreams per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Display Analytic UA Properties
```
gam <UserTypeEntity> show analyticuaproperties
accountid [accounts/]<String>
[maxresults <Integer>]
[formatjson]
```
The required `accountid <String>` can be in the format: 'accounts/123' or '123'.
By default, GAM asks the API for 50 properties per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print analyticuaproperties [todrive <ToDriveAttribute>*]
accountid [accounts/]<String>
[maxresults <Integer>]
[formatjson [quotechar <Character>]]
```
The required `accountid <String>` can be in the format: 'accounts/123' or '123'.
By default, GAM asks the API for 50 properties per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Examples
Get all analytic accounts
```
gam config auto_batch_min 1 redirect csv ./AnalyticAccounts.csv multiprocess all users print analyticaccounts
```
Get all analytic account summaries
```
gam config auto_batch_min 1 redirect stdout - multiprocess redirect stderr stdout redirect csv ./AnalyticAccountSummaries.csv multiprocess all users print analyticaccountsummaries
```
Get all analytic account properties (GA4)
```
gam redirect stdout - multiprocess redirect stderr stdout redirect csv ./GA4AnalyticAccountProperties.csv multiprocess csv AnalyticAccounts.csv gam user "~User" print analyticproperties filter "parent:~~name~~"
```
Get all analytic account properties (UA)
```
gam redirect stdout - multiprocess redirect stderr stdout redirect csv ./UAAnalyticAccountProperties.csv multiprocess csv AnalyticAccounts.csv gam user "~User" print analyticuaproperties accountid "~~name~~"
```

View File

@ -0,0 +1,37 @@
# Users - Application Specific Passwords
- [API documentation](#api-documentation)
- [Collections of Users](Collections-of-Users)
- [Definitions](#definitions)
- [Manage application specific passwords](#manage-application-specific-passwords)
- [Display application specific passwords](#display-application-specific-passwords)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/asps
## Definitions
* [`<UserTypeEntity>`](Collections-of-Users)
```
<ASPID> ::= <String>
<ASPIDList> ::= "<ASPID>(,<ASPID>)*"
```
## Manage Application Specific Passwords
```
gam <UserTypeEntity> delete asps|applicationspecificpasswords all|<ASPIDList>
```
## Display application specific passwords
```
gam <UserTypeEntity> show asps|applicationspecificpasswords
```
Gam displays the information as an indented list of keys and values.
Exit Status of 0 indicates no errors, and ASPs are sent to stdout.
Exit status of 60 indicates no errors, and that no ASPs are available for this user.
```
gam <UserTypeEntity> print asps|applicationspecificpasswords [todrive <ToDriveAttribute>*]
[oneitemperrow]
```
Gam displays the information in CSV form.
All ASPs for a user are shown on the same row unless `oneitemperrow` is specified.

View File

@ -0,0 +1,39 @@
# Users - Backup Verification Codes
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Collections of Users](Collections-of-Users)
- [Manage backup verification codes](#manage-backup-verification-codes)
- [Display backup verification codes](#display-backup-verification-codes)
## API documentation
* https://developers.google.com/admin-sdk/directory/reference/rest/v1/verificationCodes
## Definitions
* [`<UserTypeEntity>`](Collections-of-Users)
## Manage backup verification codes
```
gam <UserTypeEntity> update backupcodes|verificationcodes
gam <UserTypeEntity> delete|del backupcodes|verificationcodes
```
You will get the following error message for any user that is suspended:
```
User: user@domain.com, Backup Verification Codes Not Updated: User is suspended. You must unsuspend to process backupcodes
User: user@domain.com, Backup Verification Codes Not Deleted: User is suspended. You must unsuspend to process backupcodes
```
## Display backup verification codes
```
gam <UserTypeEntity> show backupcodes|backupcode|verificationcodes
```
Gam displays the information as an indented list of keys and values.
Exit Status of 0 indicates no errors, and backup codes are sent to stdout.
Exit status of 60 indicates no errors, and that no backup codes are available for this user.
```
gam <UserTypeEntity> print backupcodes|verificationcodes [todrive <ToDriveAttributes>*] [delimiter <Character>]
```
Gam displays the information in CSV form.
* `delimiter <Character>` - Separate `verificationCodes` entries with `<Character>`; the default value is `csv_output_field_delimiter` from `gam.cfg`.

View File

@ -0,0 +1,159 @@
# Users - Calendars - Access
- [Notes](#Notes)
- [API documentation](#api-documentation)
- [Collections of Users](Collections-of-Users)
- [Definitions](#definitions)
- [Calendar selection](#calendar-selection)
- [Manage calendar access](#manage-calendar-access)
- [Display calendar access](#display-calendar-access)
- [Transfer calendar ownership](#transfer-calendar-ownership)
## Notes
Calendar ACL roles (as seen in Calendar GUI):
* `reader` - See all event details
* `writer` & `editor` Make changes to events
* `owner` - Make changes to events and manage sharing
* `freebusy` & `freebusyreader` - See only free/busy (hide details)
## API documentation
* https://developers.google.com/google-apps/calendar/v3/reference/calendars
## Definitions
* [`<UserTypeEntity>`](Collections-of-Users)
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<CalendarItem> ::= <EmailAddress>
<CalendarList> ::= "<CalendarItem>(,<CalendarItem>)*"
<CourseAlias> ::= <String>
<CourseID> ::= <Number>|d:<CourseAlias>
<CourseIDList> ::= "<CourseID>(,<CourseID>)*"
<CourseState> ::= active|archived|provisioned|declined
<CourseStateList> ::= all|"<CourseState>(,<CourseState>)*"
<ResourceID> ::= <String>
<ResourceIDList> ::= "<ResourceID>(,<ResourceID>)*"
<TimeZone> ::= <String>
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
<UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
<CalendarSettings> ::=
(description <String>)|
(location <String>)|
(summary <String>)|
(timezone <TimeZone>)
<CalendarACLRole> ::=
editor|freebusy|freebusyreader|owner|reader|writer
<CalendarACLScope> ::=
<EmailAddress>|user:<EmailAdress>|group:<EmailAddress>|
domain:<DomainName>|domain|default
<CalendarACLScopeList> ::=
"<CalendarACLScope>(,<CalendarACLScope>)*"
<CalendarACLScopeEntity>::=
<CalendarACLScopeList> | <FileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<CalendarSelectProperty> ::=
minaccessrole <CalendarACLRole>|
showdeleted|
showhidden
<UserCalendarEntity> ::=
allcalendars|
primary|
<EmailAddress>|
<UniqueUD>|
(courses <CourseIDList>)|
((courses_with_teacher <UserItem>)|my_courses_as_teacher
[coursestates <CourseStateList>])|
((courses_with_student <UserItem>)|my_courses_as_student
[coursestates <CourseStateList>])|
(resource <ResourceID>)|
(resources <ResourceIDList>)|
((calendars <CalendarList>) | <FileSelector> | <CSVFileSelector> |
<CSVkmdSelector> | <CSVDataSelector>)|
<CalendarSelectProperty>+
```
## Calendar selection
* `allcalendars` - All calendars in a user's calendar list
* `primary` - The user's primary calendar
* `<EmailAddress>` - The address of a calendar in a user's calendar list
* `<UniqueID>` - The uniqueid of a calendar in a user's calendar list
* `courses <CourseIDList>`- The calendars associated with a list of courses
* `courses_with_teacher <UserItem>` - The calendars associated with courses with `<UserItem>` as a teacher
* `my_courses_as_teacher` - The calendars associated with the User from `<UserTypeEntity>` as a teacher
* `courses_with_student <UserItem>` - The calendars associated with courses with `<UserItem>` as a student
* `my_courses_as_student` - The calendars associated with the User from `<UserTypeEntity>` as a student
* `coursestates <CourseStateList>` - Used with the previous four options to select courses in a particular state; the default is all
* `resource <ResourceID>` - The calendar associated with a resource ID
* `resources <ResourceIDList>` - The calendars associated with a list of resource IDs
* `calendars (<CalendarList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>)` - A collection of calendars: [Collections of Items](Collections-of-Items)
* `<CalendarSelectProperty>+` - The calendars in a user's calendar list with the specified properites
## Manage calendar access
```
gam <UserTypeEntity> add calendaracls <UserCalendarEntity>
<CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
gam <UserTypeEntity> update calendaracls <UserCalendarEntity>
<CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
gam <UserTypeEntity> delete calendaracls <UserCalendarEntity>
<CalendarACLRole>] <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.
## Display calendar access
```
gam <UserTypeEntity> info calendaracls <UserCalendarEntity>
<CalendarACLScopeEntity> [formatjson]
gam <UserTypeEntity> show calendaracls <UserCalendarEntity>
[noselfowner]
[formatjson]
```
Option `noselfowner` suppresses the display of ACLs that reference the calendar itself as its owner.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print calendaracls <UserCalendarEntity> [todrive <ToDriveAttribute>*]
[noselfowner]
[formatjson [quotechar <Character>]]
```
Option `noselfowner` suppresses the display of ACLs that reference the calendar itself as its owner.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## 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.
You can update calendar settings as part of the transfer. In description, location and summary, #email#, #user# and #username# will be replaced
by the original owner's full email address or just the name portion; #timestamp# will be replaced by the current date and time.
```
gam <UserTypeEntity> transfer calendars <UserItem> <UserCalendarEntity>
[keepuser | (retainrole <CalendarACLRole>)] [sendnotifications <Boolean>]
[noretentionmessages]
[<CalendarSettings>] [append description|location|summary] [noupdatemessages]
gam <UserTypeEntity> transfer seccals <UserItem> [keepuser] [sendnotifications <Boolean>]
```
By default, the users in `<UserTypeEntity>` retain no role in the transferred calendars.
* `keepuser` - The users in `<UserTypeEntity>` retain their ownership.
* `retainrole <CalendarACLRole>` - The users in `<UserTypeEntity>` retain the specified role.
* `noretentionmessages` - Suppress the original owner role retention messages.
By default, when you add or update a calendar ACL, a notification is sent to the affected users; use `sendnotifications false` to suppress sending the notifications.
* `<CalendarSettings>` - The value specified will replace the existing value.
* `append description|location|summary` - The specified <CalendarSettings> value will be appended to the existing value.
* `noupdatemessages` - Suppress the settings update messages.
### Example
Transfer ownership of all non-primary calendars from oldowner to newowner; append a message to the calendar description noting the old owner and the time of transfer.
```
gam user oldowner@domain.com transfer calendars newowner@domain.com minaccessrole owner description "(Transferred from #user# on #timestamp#)" append description
```

View File

@ -0,0 +1,684 @@
# Users - Calendars - Events
- [API documentation](#api-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Search function
- [Collections of Users](Collections-of-Users)
- [Definitions](#definitions)
- [Recurrence rules](#recurrence-rules)
- [Event colors](#event-colors)
- [Calendar selection](#calendar-selection)
- [Event selection](#event-selection)
- [Add and import calendar events](#add-and-import-calendar-events)
- [Update calendar events](#update-calendar-events)
- [Add calendar attendees](#add-calendar-attendees)
- [Update calendar attendees](#update-calendar-attendees)
- [Specify calendar attendees with JSON data](#specify-calendar-attendees-with-JSON-data)
- [Delete selected calendar events](#delete-selected-calendar-events)
- [Delete all calendar events](#delete-all-calendar-events)
- [Move calendar events to another calendar](#move-calendar-events-to-another-calendar)
- [Empty calendar trash](#empty-calendar-trash)
- [Display calendar events](#display-calendar-events)
- [Update calendar event attendees](#update-calendar-event-attendees)
## API documentation
* https://developers.google.com/calendar/v3/reference/events
* https://developers.google.com/calendar/v3/reference/events/import
## Definitions
* [`<UserTypeEntity>`](Collections-of-Users)
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
```
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
<UserGoogleDoc> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
<CSVFileInput> ::=
((<FileName> [charset <Charset>] )|
(gsheet <UserGoogleSheet>)|
(gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
<CSVFileSelector> ::=
csvfile ((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>]
```
```
<Year> ::= <Digit><Digit><Digit><Digit>
<Month> ::= <Digit><Digit>
<Day> ::= <Digit><Digit>
<Hour> ::= <Digit><Digit>
<Minute> ::= <Digit><Digit>
<Second> ::= <Digit><Digit>
<MilliSeconds> ::= <Digit><Digit><Digit>
<Date> ::=
<Year>-<Month>-<Day> |
(+|-)<Number>(d|w|y) |
never|
today
<DateTime> ::=
<Year>-<Month>-<Day>(<Space>|T)<Hour>:<Minute> |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
<Time> ::=
<Year>-<Month>-<Day>(<Space>|T)<Hour>:<Minute>:<Second>[.<MilliSeconds>](Z|(+|-(<Hour>:<Minute>))) |
(+|-)<Number>(m|h|d|w|y) |
never|
now|today
<TimeZone> ::= <String>
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<EmailAddressList> ::= "<EmailAddress>(,<EmailAddress>)*"
<EmailAddressEntity> ::=
<EmailAddressList>|<FileSelector>|<CSVFileSelector>|
<CSVkmdSelector>|<CSVDataSelector>
<CalendarItem> ::= <EmailAddress>
<CalendarList> ::= "<CalendarItem>(,<CalendarItem>)*"
<CourseAlias> ::= <String>
<CourseID> ::= <Number>|d:<CourseAlias>
<CourseIDList> ::= "<CourseID>(,<CourseID>)*"
<CourseState> ::= active|archived|provisioned|declined
<CourseStateList> ::= all|"<CourseState>(,<CourseState>)*"
<ResourceID> ::= <String>
<ResourceIDList> ::= "<ResourceID>(,<ResourceID>)*"
<UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
<CalendarACLRole> ::=
editor|freebusy|freebusyreader|owner|reader|writer
<CalendarSelectProperty> ::=
minaccessrole <CalendarACLRole>|
showdeleted|
showhidden
<UserCalendarEntity> ::=
allcalendars|
primary|
<EmailAddress>|
<UniqueUD>|
(courses <CourseIDList>)|
((courses_with_teacher <UserItem>)|my_courses_as_teacher
[coursestates <CourseStateList>])|
((courses_with_student <UserItem>)|my_courses_as_student
[coursestates <CourseStateList>])|
(resource <ResourceID>)|
(resources <ResourceIDList>)|
((calendars <CalendarList>)|<FileSelector>|<CSVFileSelector>|
<CSVkmdSelector>|<CSVDataSelector>)|
<CalendarSelectProperty>+
```
```
<EventAttachmentsSubfieldName> ::=
attachments.fileid|
attachments.fileurl|
attachments.iconlink|
attachments.mimetype|
attachments.title
<EventAttendeesSubfieldName> ::=
attendees.additionalguests|
attendees.comment|
attendees.displayname|
attendees.email|
attendees.id|
attendees.optional|
attendees.organizer|
attendees.resource|
attendees.responseStatus|
attendees.self
<EventConferenceDataSubfieldName> ::=
conferencedata.conferenceid|
conferencedata.conferencesolution|
conferencedata.createrequest|
conferencedata.entrypoints|
conferencedata.notes|
conferencedata.signature
<EventCreatorSubfieldName> ::=
creator.displayname|
creator.email|
creator.id|
creator.self
<EventOrganizerSubfieldName> ::=
organizer.displayname|
organizer.email|
organizer.id|
organizer.self
<EventWorkingLocationPropertiesSubfieldName> ::=
workinglocationproperties.homeoffice|
workinglocationproperties.customlocation|
workinglocationproperties.officelocation
<EventFieldName> ::=
anyonecanaddself|
attachments|
<EventAttachmentsSubfieldName>|
attendees|
<EventAttendeesSubfieldName>|
attendeesomitted|
colorid|
conferencedata|
<EventConferenceDataSubfieldName>|
created|
creator|
<EventCreatorSubfieldName>|
description|
end|endtime|
endtimeunspecified|
extendedproperties|
eventtype|
gadget|
guestscaninviteothers|
guestscanmodify|
guestscanseeotherguests|
hangoutlink|
htmllink|
icaluid|
id|
location|
locked|
organizer|
<EventOrganizerSubfieldName>|
originalstart|originalstarttime|
privatecopy|
recurrence|
recurringeventid|
reminders|
sequence|
source|
start|starttime|
status|
summary|
transparency|
updated|
visibility|
workinglocationproperties|
<EventWorkingLocationPropertiesSubfieldName>
<EventFieldNameList> ::= "<EventFieldName>(,<EventFieldName>)*"
<AttendeeAttendance> ::= optional|required
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
```
```
<EventSelectProperty> ::=
(after|starttime|timemin <Time>)|
(before|endtime|timemax <Time>)|
(query <QueryCalendar>)|
(privateextendedproperty <String>)|
(sharedextendedproperty <String>)|
showdeletedevents|
showhiddeninvitations|
singleevents|
(updatedmin <Time>)
<EventMatchProperty> ::=
(matchfield attendees <EmailAddressEntity>)|
(matchfield attendeespattern <RegularExpression>)|
(matchfield attendeesstatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddressEntity>)|
(matchfield creatoremail <RegularExpression>)|
(matchfield creatorname <RegularExpression>)|
(matchfield description <RegularExpression>)|
(matchfield hangoutlink <RegularExpression>)|
(matchfield location <RegularExpression>)|
(matchfield organizeremail <RegularExpression>)|
(matchfield organizername <RegularExpression>)|
(matchfield status <RegularExpression>)|
(matchfield summary <RegularExpression>)|
(matchfield transparency <RegularExpression>)|
(matchfield visibility <RegularExpression>)
<EventIDEntity> ::=
(id|eventid <EventId>) |
(event|events <EventIdList> |
<FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector> | <CSVDataSelector>)
<EventSelectEntity> ::=
(<EventSelectProperty>+ <EventMatchProperty>*)
<EventEntity> ::=
<EventIDEntity> | <EventSelectEntity>
<EventColorIndex> ::= <Number in range 1-11>
<EventColorName> ::=
banana|basil|blueberry|flamingo|graphite|grape|
lavender|peacock|sage|tangerine|tomato
<PropertyKey> ::= <String>
<PropertyValue> ::= <String>
<TimeZone> ::= <String>
<EventAttribute> ::=
(anyonecanaddself [<Boolean>])|
(attachment <String> <URL>)|
(attendee <EmailAddress>)|
(attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>)|
available|
(color <EventColorName>)|
(colorindex|colorid <EventColorIndex>)|
(description <String>)|
(end (allday <Date>)|<Time>)|
(guestscaninviteothers <Boolean>)|
guestscantinviteothers|
(guestscanmodify <Boolean>)|
(guestscanseeotherguests <Boolean>)|
guestscantseeotherguests|
hangoutsmeet|
<JSONData>|
(jsonattendees [charset <Charset>] <String>)|
(jsonattendees file <FileName> [charset <Charset>])|
(location <String>)|
(noreminders|(reminder email|popup <Number>))|
(optionalattendee <EmailAddress>)|
(originalstart|originalstarttime (allday <Date>)|<Time>)|
(privateproperty <PropertyKey> <PropertyValue>)|
(recurrence <RRULE, EXRULE, RDATE and EXDATE line>)|
(reminder <Number> email|popup))|
(selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>)|
(sequence <Integer>)|
(sharedproperty <PropertyKey> <PropertyValue>)|
(source <String> <URL>)|
(start (allday <Date>)|<Time>)|
(status confirmed|tentative|cancelled)|
(summary <String>)|
tentative|
(timezone <TimeZone>)|
(transparency opaque|transparent)|
(visibility default|public|private)
The following attributes are equivalent:
available - transparency transparent
guestscantinviteothers - guestscaninviteothers False
guestscantseeothers - guestscanseeotherguests False
tentative - status tentative
<EventImportAttribute> ::=
<EventAttribute>|
(organizername <String>)|
(organizeremail <EmailAddress>)
<EventUpdateAttribute> ::=
<EventAttribute>|
clearattendees|
clearattachments|
clearhangoutsmeet|
(clearprivateproperty <PropertyKey>)|
(clearsharedproperty <PropertyKey>)|
(removeattendee <EmailAddress>)|
(replacedescription <RegularExpression> <String>)|
(selectremoveattendees <UserTypeEntity>)
<EventNotificationAttribute> ::=
notifyattendees|(sendnotifications <Boolean>)|(sendupdates all|enternalonly|none)
The following attributes are equivalent:
notifyattendees - sendupdates all
sendnotifications false - sendupdates none
sendnotifications true - sendupdates all
<EventDisplayProperty> ::=
(alwaysincludeemail)|
(icaluid <String>)|
(maxattendees <Integer>)|
(orderby starttime|updated)|
(timezone <TimeZone>)
```
## Recurrence rules
Recurring events require a rule: `recurrence <RRULE, EXRULE, RDATE and EXDATE line>`
* https://tools.ietf.org/html/rfc5545#section-3.8.5
This is dense reading; a simpler approach is to define a test event in Google Calendar with
the recurrence rule that you want, then use `gam calendar <EmailAddress> info events eventid <EventId>` to get the recurrence rule and use it in subsequent commands.
```
RRULE:FREQ=DAILY
RRULE:FREQ=DAILY;COUNT=30
RRULE:FREQ=WEEKLY;BYDAY=WE
RRULE:FREQ=WEEKLY;WKST=SU;COUNT=13;BYDAY=WE
```
## Event colors
The event color grid presented in calendar.google.com and `<EventColorIndex>` are related like this:
```
11:tomato 4:flamingo
6:tangerine 5:banana
2:sage 10:basil
7:peacock 9:blueberry
1:lavender 3:grape
8:graphite
```
## Calendar selection
These are the possible values for `<UserCalendarEntity>`.
* `allcalendars` - All calendars in a user's calendar list
* `primary` - The user's primary calendar
* `<EmailAddress>` - The address of a calendar in a user's calendar list
* `<UniqueID>` - The uniqueid of a calendar in a user's calendar list
* `courses <CourseIDList>`- The calendars associated with a list of courses
* `courses_with_teacher <UserItem>` - The calendars associated with courses with `<UserItem>` as a teacher
* `my_courses_as_teacher` - The calendars associated with the User from `<UserTypeEntity>` as a teacher
* `courses_with_student <UserItem>` - The calendars associated with courses with `<UserItem>` as a student
* `my_courses_as_student` - The calendars associated with the User from `<UserTypeEntity>` as a student
* `coursestates <CourseStateList>` - Used with the previous four options to select courses in a particular state; the default is all
* `resource <ResourceID>` - The calendar associated with a resource ID
* `resources <ResourceIDList>` - The calendars associated with a list of resource IDs
* `calendars (<CalendarList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>)` - A collection of calendars: [Collections of Items](Collections-of-Items)
* `<CalendarSelectProperty>+` - The calendars in a user's calendar list with the specified properites
## Event selection
These are the possible values for `<EventEntity>`; you either specify event IDs or properties used to select events.
If none of the following options are selected, all events are selected.
* `id|eventid <EventId>` - A single event ID
* `event|events <EventIdList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVSubkeySelector> | <CSVDataSelector>)` - A collection of event IDs: [Collections of Items](Collections-of-Items)
* `<EventSelectProperty>* <EventMatchProperty>*` - Properties used to select events
The Google Calendar API processes `<EventSelectProperty>*`; you may specify none or multiple properties.
* `after|starttime|timemin <Time>` - Lower bound (inclusive) for an event's end time to filter by. If timeMax is set, timeMin must be smaller than timeMax.
* `before|endtime|timemax <Time>` - Upper bound (exclusive) for an event's start time to filter by. If timeMin is set, timeMax must be greater than timeMin.
* `query <QueryCalendar>` - Free text search terms to find events that match these terms in any field, except for extended properties
* `privateextendedproperty <String>` - A required private property; `<String>` must be of the form `propertyName=value`
* `sharedextendedproperty <String>` - A required shared property; `<String>` must be of the form `propertyName=value`
* `showdeletedevents` - Whether to include deleted events (with status equals "cancelled") in the result
* `showhiddeninvitations` - Whether to include hidden invitations in the result
* `singleevents` - Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves
* `updatedmin <Time>` - Lower bound for an event's last modification time (as a RFC3339 timestamp) to filter by. When specified, entries deleted since this time will always be included regardless of showdeletedevents
GAM processes `<EventMatchProperty>*`; you may specify none or multiple properties.
* `matchfield attendees <EmailAddressEntity>` - All of the attendees in `<EmailAddressEntity>` must be present
* `matchfield attendeespattern <RegularExpression>` - Some attendee must match `<RegularExpression>`
* `matchfield attendeesstatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddressEntity>` - All of the attendees in `<EmailAddressEntity>` must be present
and must have the specified values.
* `<AttendeeAttendance>` - Default is `required`
* `<AttendanceStatus>` - Default is`needsaction`
* `matchfield creatoremail <RegularExpression>` - The creator email address must match `<RegularExpression>`
* `matchfield creatorname <RegularExpression>` - The creator name must match `<RegularExpression>`
* `matchfield description <RegularExpression>` - The description (summary) must match `<RegularExpression>`
* `matchfield location <RegularExpression>` - The location must match `<RegularExpression>`
* `matchfield organizeremail <RegularExpression>` - The organizer email address must match `<RegularExpression>`
* `matchfield organizername <RegularExpression>` - The orgainzer name must match `<RegularExpression>`
* `matchfield status <RegularExpression>` - The summary must match `<RegularExpression>`. The API documented values are:
* `confirmed`
* `tentative`
* `cancelled`
* `matchfield summary <RegularExpression>` - The summary must match `<RegularExpression>`
* `matchfield transparency <RegularExpression>` - The summary must match `<RegularExpression>`. The API documented values are:
* `opaque` - Busy. The API does not seem to return this value; use `"(^$)|opaque"` to match no value or `opaque`.
* `transparent` - Free/Available
* `matchfield visibility <RegularExpression>` - The summary must match `<RegularExpression>`. The API documented values are:
* `default` - The API does not seem to return this value; use `"(^$)|default"` to match no value or `default`.
* `public` - The API does not seem to return this value if it is the default; use `"(^$)|public"` to match no value or `public`.
* `private` - The API does not seem to return this value if it is the default; use `"(^$)|private"` to match no value or `private`.
* `confidential`
## Add and import calendar events
```
gam <UserTypeEntity> add event <UserCalendarEntity> [id <String>] <EventAttribute>+ [<EventNotificationAttribute>]
[showdayofweek]
[csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
gam <UserTypeEntity> import event <UserCalendarEntity> icaluid <iCalUID> <EventImportAttribute>+
[showdayofweek]
[csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
```
By default, when an event is created|imported, GAM outputs the calendar name and event ID.
* `csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]` - Output the event details in CSV format.
You can specify multiple attachments; `<String>` is the title of the attachment and `<URL>` is a sharable link from Google Drive.
You must specify all attachments in each command, you can not incrementally add attachments.
Importing events is similar to adding events; the principal difference
is that you must specify an `iCalUID`. All instances of recurring events will have the same
`iCalUID` but different `EventIDs`. The import command supports two new attributes to set the
event organizer, but the API doesn't seem to honor the values; the organizer is set to
the calendar owner.
## Update calendar events
```
gam <UserTypeEntity> update events <UserCalendarEntity> [<EventEntity>] <EventUpdateAttribute>+ [<EventNotificationAttribute>]
[showdayofweek]
[csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
```
If `<EventEntity>` is not specified, all events in `<UserCalendarEntity>` are selected. This is not typically used
unless you're trying to change a basic `<EventAttribute>`, e.g., `color`, on all events.
By default, when an event is updated, GAM outputs the calendar name and event ID.
* `csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]` - Output the event details in CSV format.
You can clear/modify existing attributes:
* `clearattachments` - Delete all attachments
* `clearhangoutsmeet` - Clear Hangouts/Meet link
* `clearprivateproperty <PropertyKey>` - Clear private properties
* `clearsharedproperty <PropertyKey>` - Clear shared properties
* `replacedescription <RegularExpression> <String>` - Modify the description
## Add calendar attendees
You can specify attendees in the following ways:
* `attendee <EmailAddress>` - The attendee attendance is required with status `needsaction'
* `optionalattendee <EmailAddress>` - The attendee attendance is optional with status `needsaction'
* `attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>` - One attendee
* If `<AttendeeAttendance>` is not specified, the attendee is required to attend
* If `<AttendeeStatus>` is not specified, `needsaction` is chosen
* `jsonattendees [charset <Charset>] <String>`
* `jsonattendees file <FileName> [charset <Charset>]`
* `selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>` - Multiple attendees
* If `<AttendeeAttendance>` is not specified, all attendees are required to attend
* If `<AttendeeStatus>` is not specified, `needsaction` is chosen
For `<UserTypeEntity>` See: [Collections of Users](Collections-of-Users)
## Update calendar attendees
The default behavior of `gam calendar <CalendarEntity> update events` has been changed regarding attendees.
In versions of GAM before `5.02.00`, updating attendees in calendar events was complicated because you had to
supply the complete attendee list even if you just wanted incremental changes.
The default behavior now is to allow incremental changes to the attendees list;
the current attendee list is downloaded and the specified changes are applied.
The `replacemode` option invokes the previous behavior from versions before `5.02.00`; the current attendee list is replaced.
You can add attendees in the following ways:
* `attendee <EmailAddress>` - The attendee attendance is required with status `needsaction'
* `optionalattendee <EmailAddress>` - The attendee attendance is optional with status `needsaction'
* `attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>` - One attendee
* If `<AttendeeAttendance>` is not specified, the attendee is required to attend
* If `<AttendeeStatus>` is not specified, `needsaction` is chosen
* `jsonattendees [charset <Charset>] <String>`
* `jsonattendees file <FileName> [charset <Charset>]`
* `selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>` - Multiple attendees
* If `<AttendeeAttendance>` is not specified, all attendees are required to attend
* If `<AttendeeStatus>` is not specified, `needsaction` is chosen
You can remove attendees in the following ways:
* `clearattendees` - Clear all current attendees from the attendee list
* `removeattendee <EmailAddress>` - Remove a single attendee from the attendee list
* `selectremoveattendees <UserTypeEntity>` - Remove a selected collection of attendees from the attendee list
For `<UserTypeEntity>` See: [Collections of Users](Collections-of-Users)
## Specify calendar attendees with JSON data
You can predefine lists of attendees and use them when creating/updating events. If you set `responseStatus` to `accepted`, no notifications are sent.
```
$ more attendees.json
{"attendees": [{"email": "testuser2@domain.com", "responseStatus": "needsAction", "optional": "True"}, {"email": "testuser3@domain.com", "responseStatus": "accepted"}, {"email": "testuser4@domain.com", "responseStatus": "accepted"}]}
```
You can use output the attendee information for an event in a calendar and use that data when defining other events.
```
$ gam redirect stdout ./attendees.json calendar testuser1@domain.com info event id 0000h8kk7c9o2tonk73hu2zzzz fields attendees formatjson
$ more attendees.json
{"calendarId": "testuser1@domain.com", "event": {"attendees": [{"email": "testuser3@domain.com", "responseStatus": "accepted"}, {"email": "testuser4@domain.com", "responseStatus": "accepted"}], "id": "0000h8kk7c9o2tonk73hu2zzzz"}}
```
Use `jsonattendees file ./attendees.json` in `create/update event`.
## Delete selected calendar events
```
gam <UserTypeEntity> delete events <UserCalendarEntity> [<EventEntity>] [doit] [<EventNotificationAttribute>]
gam <UserTypeEntity> purge events <UserCalendarEntity> [<EventEntity>] [doit] [<EventNotificationAttribute>]
```
If `<EventEntity>` is not specified, all events in `<UserCalendarEntity>` are selected. This is not typically used.
No events are deleted unless you specify the `doit` option; omit `doit` to verify that you properly selected the events to delete.
When events are deleted from a calendar, they are moved to the calendar's trash and are only permanently deleted (purged) after 30 days.
Following a suggestion here (https://stackoverflow.com/questions/41043053/how-to-empty-calendar-trash-via-google-services) you can permanently delete
calendar events. This is achieved by creating a temporary calendar, deleting the events, moving the deleted events to the temporary calendar
and then deleting the temporary calendar.
## Delete all calendar events
For a user's primary calendar:
```
gam <UserTypeEntity> wipe events primary
```
For non-primary calendars:
```
gam <UserTypeEntity> delete events <UserCalendarEntity> [doit] [<EventNotificationAttribute>]
```
No events are deleted unless you specify the `doit` option; omit `doit` to verify that you properly selected the events to delete.
## Move calendar events to another calendar
Generally you won't move all events from one calendar to another; typically, you'll move events created by the event creator
using `matchfield creatoremail <RegularExpression>` in conjunction with other `<EventSelectProperty>` and `<EventMatchProperty>` options.
```
gam <UserTypeEntity> move events <UserCalendarEntity> [<EventEntity>] destination|to <CalendarItem> [<EventNotificationAttribute>]
```
## Empty calendar trash
A user signed in to Google Calendar can empty the calendar trash but there is no direct API support for this operation.
To empty the calendar trash a temporary calendar is created, the deleted events are moved to the temporary calendar and then the temporary calendar is deleted.
```
gam <UserTypeEntity> empty calendartrash <UserCalendarEntity>
```
## Display calendar events
```
gam <UserTypeEntity> info events <UserCalendarEntity> [<EventEntity>] [maxinstances <Number>]
[fields <EventFieldNameList>] [showdayofweek]
[formatjson]
```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
* `maxinstances -1` - Default, display base event
* `maxinstances 0` - Display all instances of a recurring event
* `maxinstances N` - Display first N instances of a recurring event
`showdayofweek` displays `dayOfWeek` when event start and end times are displayed.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> show events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsonly] [formatjson]
```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
By default, only the base event of a recurring event is displayed. Use the `<EventSelectProperty>`
option `singleevents` to display all instances of a recurring event.
`<EventDisplayProperty> orderby starttime` is only valid with `<EventSelectProperty> singleevents`.
`showdayofweek` displays `dayOfWeek` when event start and end times are displayed.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
By default, Gam displays event details, use `countsonly` to display only the number of events. `formatjson` does not apply in this case.
```
gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsonly] [formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
By default, only the base event of a recurring event is displayed. Use the `<EventSelectProperty>`
option `singleevents` to display all instances of a recurring event.
`<EventDisplayProperty> orderby starttime` is only valid with `<EventSelectProperty> singleevents`.
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, Gam displays event details, use `countsonly` to display only the number of events. `formatjson` does not apply in this case.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Update calendar event attendees
```
gam <UserTypeEntity> update calattendees <UserCalendarEntity> <EventEntity> [anyorganizer]
[<EventNotificationAttribute>] [splitupdate] [dryrun|doit]
(csv|csvfile <CSVFileInput>)
(delete <EmailAddress>)*
(deleteentity <EmailAddressEntity>)*
(add <EmailAddress>)*
(addentity <EmailAddressEntity>)*
(addstatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>)*
(addentitystatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddressEntity>)*
(replace <EmailAddress> <EmailAddress>)*
(replacestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress> <EmailAddress>)*
(updatestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>)*
(updateentitystatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddressEntity>)*
```
By default, only events in `<EventEntity>` organized by the user are selected.
* `anyorganizer|allevents` - All events in `<EventEntity>` are selected.
* `csv <FileName>` - A CSV file with no header row and two to four columns; the last two columns are optional
* `<EmailAddress>,add,<AttendeeAttendance>,<AttendeeStatus>` - Add an attendee
* `<EmailAddress>,delete` - Delete an attendee
* `<EmailAddress>,<EmailAddress>,<AttendeeAttendance>,<AttendeeStatus>` - Replace the attendee in the first `<EmailAddress>` with the attendee in the second `<EmailAddress>`
* `<EmailAddress>,update,<AttendeeAttendance>,<AttendeeStatus>` - Update an attendee
* `gsheet <UserGoogleSheet>` - A Google Sheet with no header row and two columns
* `<EmailAddress>,add,<AttendeeAttendance>,<AttendeeStatus>` - Add an attendee
* `<EmailAddress>,delete` - Delete an attendee
* `<EmailAddress>,<EmailAddress>,<AttendeeAttendance>,<AttendeeStatus>` - Replace the attendee in the first `<EmailAddress>` with the attendee in the second `<EmailAddress>`
* `<EmailAddress>,update,<AttendeeAttendance>,<AttendeeStatus>` - Update an attendee
* `delete <EmailAddress>` - Delete an attendee
* `deleteentity <EmailAddressEntity>` - Delete multiple attendees
* `add <EmailAddress>` - Add an attendee
* `addentity <EmailAddressEntity>` - Add multiple attendees
* `addstatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>` - Add an attendee
* `addentitystatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddressEntity>` - Add multiple attendees
* `replace <EmailAddress> <EmailAddress>` - Replace the attendee in the first `<EmailAddress>` with the attendee in the second `<EmailAddress>`
* `replacestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress> <EmailAddress>` - Replace the attendee in the first `<EmailAddress>` with the attendee in the second `<EmailAddress>`
* `updatestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>` - Update an attendee
* `updateentitystatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddressEntity>` - Update multiple attendees
For `add`, `addstatus` and `addentitystatus`:
* `<AttendeeAttendance>` - Default is `required`
* `<AttendanceStatus>` - Default is `needsaction`
For `replace`, `replacestatus`, `updatestatus` and `updateentitystatus`:
* `<AttendeeAttendance>` - Default is no change from current value
* `<AttendanceStatus>` - Default is no change from current value
By default, when you try to replace an email alias with its primary email, the Google Calendar API
detects that the underlying user ID is the same and doesn't change the address. The `splitupdate`
option causes GAM to make two updates to the attendee list; the first removes the alias and
the second adds the primary email.
The attendee changes are displayed but not processed unless `doit` is specified.

287
docs/Users-Calendars.md Normal file
View File

@ -0,0 +1,287 @@
# Users - Calendars
- [API documentation](#api-documentation)
- [Collections of Users](Collections-of-Users)
- [Definitions](#definitions)
- [Calendar colors](#calendar-colors)
- [Calendar selection](#calendar-selection)
- [Display calendar UI settings](#display-calendar-ui-settings)
- [Manage calendars](#manage-calendars)
- [Create and remove calendars](#create-and-remove-calendars)
- [Display calendar settings](#display-calendar-settings)
- [Modify calendar settings](#modify-calendar-settings)
- [Manage calendar lists](#manage-calendar-lists)
- [Display specific calendars from list](#display-specific-calendars-from-list)
- [Display calendar lists](#display-calendar-lists)
## API documentation
* https://developers.google.com/google-apps/calendar/v3/reference/calendars
## Definitions
* [`<UserTypeEntity>`](Collections-of-Users)
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<CalendarItem> ::= <EmailAddress>
<CalendarList> ::= "<CalendarItem>(,<CalendarItem>)*"
<CourseAlias> ::= <String>
<CourseID> ::= <Number>|d:<CourseAlias>
<CourseIDList> ::= "<CourseID>(,<CourseID>)*"
<CourseState> ::= active|archived|provisioned|declined
<CourseStateList> ::= all|"<CourseState>(,<CourseState>)*"
<ResourceID> ::= <String>
<ResourceIDList> ::= "<ResourceID>(,<ResourceID>)*"
<TimeZone> ::= <String>
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
<UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
<CalendarACLRole> ::=
editor|freebusy|freebusyreader|owner|reader|writer
<CalendarSelectProperty> ::=
minaccessrole <CalendarACLRole>|
showdeleted|
showhidden
<UserCalendarAddEntity> ::=
<EmailAddress>|
<UniqueUD>|
(courses <CourseIDList>)|
((courses_with_teacher <UserItem>)|my_courses_as_teacher
[coursestates <CourseStateList>])|
((courses_with_student <UserItem>)|my_courses_as_student
[coursestates <CourseStateList>])|
(resource <ResourceID>)|
(resources <ResourceIDList>)|
((calendars <CalendarList>) | <FileSelector> | <CSVFileSelector> |
<CSVkmdSelector> | <CSVDataSelector>)
<UserCalendarEntity> ::=
allcalendars|
primary|
<EmailAddress>|
<UniqueID>|
(courses <CourseIDList>)|
((courses_with_teacher <UserItem>)|my_courses_as_teacher
[coursestates <CourseStateList>])|
((courses_with_student <UserItem>)|my_courses_as_student
[coursestates <CourseStateList>])|
(resource <ResourceID>)|
(resources <ResourceIDList>)|
((calendars <CalendarList>) | <FileSelector> | <CSVFileSelector> |
<CSVkmdSelector> | <CSVDataSelector>)|
<CalendarSelectProperty>*
<UserCalendarSettingsField> ::=
autoaddhangouts|
datefieldorder|
defaulteventlength|
format24hourtime|
hideinvitations|
hideweekends|
locale|
remindonrespondedeventsonly|
showdeclinedevents|
timezone|
usekeyboardshortcuts|
weekstart
<UserCalendarSettingsFieldList> ::= "<UserCalendarSettingsField>(,<UserCalendarSettingsField>)*"
<CalendarColorIndex> ::= <Number in range 1-24>
<CalendarColorName> ::=
amethyst|avocado|banana|basil|birch|blueberry|
cherryblossom|citron|cobalt|cocoa|eucalyptus|flamingo|
grape|graphite|lavender|mango|peacock|pistachio|
pumpkin|radicchio|sage|tangerine|tomato|wisteria|
<CalendarEmailNotificatonEventType> ::=
eventcreation|eventchange|eventcancellation|eventresponse|agenda
<CalendarEmailNotificatonEventTypeList> ::=
<CalendarEmailNotificatonEventType>(,<CalendarEmailNotificatonEventType>)*"
<CalendarAttribute> ::=
(backgroundcolor <ColorValue>)|
(colorindex|colorid <CalendarColorIndex>)|
(foregroundcolor <ColorValue>)|
(hidden <Boolean>)|
(notification clear|(email <CalendarEmailNotificatonEventTypeList>))|
(reminder clear|(email|popup <Number>)|(<Number> email|popup))|
(selected <Boolean>)|
(summary <String>)
<CalendarSettings> ::=
(description <String>)|
(location <String>)|
(summary <String>)|
(timezone <TimeZone>)
<CalendarListField> ::=
accessrole|
backgroundcolor|
colorid|
conferenceproperties|
defaultreminders|
deleted|
description|
foregroundcolor|
hidden|
id|
location|
notificationsettings|
primary|
selected|
summary|
summaryoverride|
timezone
<CalendarListFieldList> ::= "<CalendarListField>(,<CalendarListField>)*"
```
## Calendar colors
The calendar color grid presented in calendar.google.com and `<CalendarColorIndex>` are related like this:
```
21:radicchio 4:tangerine 11:citron 8:basil 16:blueberry 23:grape
22:cherryblossom 5:pumpkin 10:avacado 7:eucalyptus 17:lavender 1:cocoa
3:tomato 6:mango 9:pistachio 14:peacock 18:wisteria 19:graphite
2:flamingo 12:banana 13:sage 15:cobalt 24:amethyst 20:birch
```
## Calendar selection
* `allcalendars` - All calendars in a user's calendar list
* `primary` - The user's primary calendar
* `<EmailAddress>` - The address of a calendar in a user's calendar list
* `<UniqueID>` - The uniqueid of a calendar in a user's calendar list
* `courses <CourseIDList>`- The calendars associated with a list of courses
* `courses_with_teacher <UserItem>` - The calendars associated with courses with `<UserItem>` as a teacher
* `my_courses_as_teacher` - The calendars associated with the User from `<UserTypeEntity>` as a teacher
* `courses_with_student <UserItem>` - The calendars associated with courses with `<UserItem>` as a student
* `my_courses_as_student` - The calendars associated with the User from `<UserTypeEntity>` as a student
* `coursestates <CourseStateList>` - Used with the previous four options to select courses in a particular state; the default is all
* `resource <ResourceID>` - The calendar associated with a resource ID
* `resources <ResourceIDList>` - The calendars associated with a list of resource IDs
* `calendars (<CalendarList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>)` - A collection of calendars: [Collections of Items](Collections-of-Items)
* `<CalendarSelectProperty>+` - The calendars in a user's calendar list with the specified properites
## Display calendar UI settings
```
gam <UserTypeEntity> show calsettings
[fields <UserCalendarSettingsFieldList>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print calsettings [todrive <ToDriveAttribute>*]
[fields <UserCalendarSettingsFieldList>]
[formatjson [quotechar <Character>]]
```
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Manage calendars
### Create and remove calendars
```
gam <UserTypeEntity> create calendar <CalendarSettings>
gam <UserTypeEntity> remove calendars <UserCalendarEntity>
```
### Display calendar settings
```
gam <UserTypeEntity> info calendars <UserCalendarEntity> [formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Modify calendar settings
```
gam <UserTypeEntity> modify calendars <UserCalendarEntity> <CalendarSettings>
```
## Manage calendar lists
These commands manage a user's list of calendars.
```
gam <UserTypeEntity> add calendars <UserCalendarAddEntity> <CalendarAttribute>*
gam <UserTypeEntity> update calendars <UserCalendarEntity> <CalendarAttribute>+
gam <UserTypeEntity> delete calendars <UserCalendarEntity>
```
### Examples
A student accidentally removed his course calendars and needs them back.
```
gam user student@domain.com add calendars my_courses_as_student
```
An advisor wants to monitor the course calendars for a student.
```
gam user advisor@domain.com add calendars courses_with_student student@domain.com
```
## Display specific calendars from list
### Display as an indented list of keys and values.
```
gam <UserTypeEntity> info calendars <UserCalendarEntity>
[fields <CalendarListFieldList>] [permissions]
[formatjson]
```
* `permissions` adds permission information for user owned calendars to the output.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
## Display calendar lists
### Display as an indented list of keys and values.
```
gam <UserTypeEntity> show calendars
[primary] <CalendarSelectProperty>*
[noprimary] [nogroups] [noresources] [nosystem] [nousers]
[fields <CalendarListFieldList>] [permissions]
[formatjson]
```
By default, information for all visible, non-deleted calendars is shown.
* `primary` - Limits the selection to the user's primary calendar
* `<CalendarSelectProperty>`
* `minaccessrole <CalendarACLRole>`- Limits the selection to those calendars where the user's role is at least `<CalendarACLRole>`
* `showdeleted` - Adds deleted calendars to the selection
* `showhidden` - Adds hidden calendars to the selection
* `noprimary` - Do not display the users's primary calendar
* `nogroups` - Do not display group calendars, email address ends in "@group.calendar.google.com"
* `noresources` - Do not display resource calendars, email address ends in "@resource.calendar.google.com"
* `nosystem` - Do not display system calendars, email address ends in "@group.v.calendar.google.com"
* `nousers` - Do not display users calendars, email address ends in `domain` value from `gam.cfg`.
* `permissions` adds permission information for user owned calendars to the output.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Display as a CSV file.
```
gam <UserTypeEntity> print calendars [todrive <ToDriveAttribute>*]
[primary] <CalendarSelectProperty>*
[noprimary] [nogroups] [noresources] [nosystem] [nousers]
[fields <CalendarListFieldList>] [permissions]
[formatjson] [delimiter <Character>] [quotechar <Character>]
```
By default, information for all visible, non-deleted calendars is shown.
* `permissions` adds permission information for user owned calendars to the output.
* `primary` - Limits the selection to the user's primary calendar
* `<CalendarSelectProperty>`
* `minaccessrole <CalendarACLRole>`- Limits the selection to those calendars where the user's role is at least `<CalendarACLRole>`
* `showdeleted` - Adds deleted calendars to the selection
* `showhidden` - Adds hidden calendars to the selection
* `noprimary` - Do not display the users's primary calendar
* `nogroups` - Do not display group calendars, email address ends in "@group.calendar.google.com"
* `noresources` - Do not display resource calendars, email address ends in "@resource.calendar.google.com"
* `nosystem` - Do not display system calendars, email address ends in "@group.v.calendar.google.com"
* `nousers` - Do not display users calendars, email address ends in `domain` value from `gam.cfg`.
By default, list items are separated by the `csv_output_field_delimiter' from `gam.cfg`.
* `delimiter <Character>` - Separate list items with `<Character>`
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.

433
docs/Users-Chat.md Normal file
View File

@ -0,0 +1,433 @@
# Users - Chat
- [API documentation](#api-documentation)
- [Introduction](#introduction)
- [Set up a Chat Bot](#set-up-a-chat-bot)
- [Definitions](#definitions)
- [Manage Chat Spaces](#manage-chat-spaces)
- [Display Chat Spaces](#display-chat-spaces)
- [Manage Chat Members](#manage-chat-members)
- [Display Chat Members](#display-chat-members)
- [Manage Chat Messages](#manage-chat-messages)
- [Display Chat Messages](#display-chat-messages)
- [Bulk Operations](#bulk-operations)
## API documentation
* https://developers.google.com/chat/concepts
* https://developers.google.com/chat/reference/rest
* https://support.google.com/chat/answer/7655820
## Introduction
These features were added in version 6.60.00.
To use these commands you must update your service account authorization.
```
gam user user@domain.com update serviceaccount
[*] 3) Chat API - Memberships (supports readonly)
[*] 4) Chat API - Messages (supports readonly)
[*] 5) Chat API - Spaces (supports readonly)
[*] 6) Chat API - Spaces Delete
```
Google requires that you have a Chat Bot configured in order to use the Chat API; set up a Chat Bot as described in the next section.
## Set up a Chat Bot
* Run the command `gam setup chat`; it will point you to a URL to configure your Chat Bot; this is required to use the Chat API.
* Enter an App name and Description of your choosing.
* For the Avatar URL you can use `https://dummyimage.com/384x256/4d4d4d/0011ff.png&text=+GAM` or a public URL to an image of your own choosing.
* In Functionality, uncheck both "Receive 1:1 messages" and "Join spaces and group conversations"
* In Connection settings, choose "Cloud Pub/Sub" and enter "no-topic" for the topic name. GAM doesn't yet listen to pub/sub so this option is not used.
* In Visibility, uncheck "Make this Chat app available to specific people and groups in Domain Workspace".
* Click Save.
## Definitions
* [`<UserTypeEntity>`](Collections-of-Users)
* [Drive File Selection](Drive-File-Selection) for symbols not listed here, such as `<DriveFileIDEntity>`
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
```
<StorageBucketName> ::= <String>
<StorageObjectName> ::= <String>
<StorageBucketObjectName> ::=
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
gs://<StorageBucketName>/<StorageObjectName>|
<StorageBucketName>/<StorageObjectName>
<UserGoogleDoc> ::=
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
<ChatContent> ::=
((text <String>)|
(textfile <FileName> [charset <CharSet>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
<ChatMember> ::= spaces/<String>/members/<String>
<ChatMemberList> ::= "<ChatMember>(,<ChatMember>)*"
<ChatMessage> ::= spaces/<String>/messages/<String>
<ChatSpace> ::= spaces/<String> | space <String> | space spaces/<String>
<ChatThread> ::= spaces/<String>/threads/<String>
<ChatSpaceType> ::=
space|
groupchat|
directmessage
<ChatSpaceTypeList> ::= "<ChatSpaceType>(,<ChatSpaceType>)*"
<ChatMessageID> ::= client-<String>
<String> must contain only lowercase letters, numbers, and hyphens up to 56 characters in length.
```
## Manage Chat Spaces
### Create a chat space
```
gam <UserTypeEntity> create chatspace
[type <ChatSpaceType>]
[members <UserTypeEntity>]
[displayname <String>]
[description <String>] [guidelines <String>]
[history <Boolean>]
[<ChatContent>]
[formatjson|returnidonly]
```
For `type space`, the following apply:
* `member <UserTypeEntity>` - Optional, can not specify more that 20 users
* `displayname <String>` - Required
* `description <String>` - Optional
* `guidelines <String>` - Optional
* `history <Boolean>` - Optional
For `type groupchat`, the following apply:
* `member <UserTypeEntity>` - Required, must specify between 2 and 20 users
* `displayname <String>` - Ignored
* `description <String>` - Optional
* `guidelines <String>` - Optional
* `history <Boolean>` - Optional
For `type directmessage`, the following apply:
* `member <UserTypeEntity>` - Required, must specify 1 user
* `displayname <String>` - Ignored
* `description <String>` - Ignored
* `guidelines <String>` - Ignored
* `history <Boolean>` - Optional
By default, Gam displays the information about the created chatspace as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
* `returnidonly` - Display the chatspace name only
Use the `<ChatContent>` option to send an initial message to the created chatspace.
By default, details about the chatmessage are displayed.
* `returnidonly` - Display the chatmessage name only
### Update a chat space
```
gam <UserTypeEntity> update chatspace <ChatSpace>
[type space]
[displayname <String>]
[description <String>] [guidelines <String>]
[history <Boolean>]
[formatjson]
```
A groupchat space can be upgraded to a space by specifying `type space` and `displayname <String>`.
By default, Gam displays the information about the created chatspace as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Delete a chat space
```
gam <UserTypeEntity> delete chatspace <ChatSpace>
```
## Display Chat Spaces
### Display information about a specific chat space for a user
```
gam <UserTypeEntity> info chatspace <ChatSpace>
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Display information about a direct message chat space between two users
```
gam <UserTypeEntity> info chatspacedm <UserItem>
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Display information about all chat spaces for a user
```
gam <UserTypeEntity> show chatspaces
[types <ChatSpaceTypeList>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print chatspaces [todrive <ToDriveAttribute>*]
[types <ChatSpaceTypeList>]
[formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Manage Chat Members
### Add members to a chat space
```
gam <UserTypeEntity> create chatmember <ChatSpace>
[type human|bot]
((user <UserItem>)|(members <UserTypeEntity>))*
[formatjson|returnidonly]
```
By default, Gam displays the information about the chatmember as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
* `returnidonly` - Display the chatmember name only
### Delete members from a chat space
Delete members by specifying a chat space and user email addresses.
```
gam <UserTypeEntity> delete chatmember <ChatSpace>
((user <UserItem>)|(members <UserTypeEntity>))+
```
Delete members by specifying chatmember names.
```
gam <UserTypeEntity> remove chatmember members <ChatMemberList>
```
## Display Chat Members
### Display information about a specific chat members
```
gam <UserTypeEntity> info chatmember members <ChatMemberList>
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Display information about all chat members in a chat space
```
gam <UserTypeEntity> show chatmembers <ChatSpace>
[showinvited [<Boolean>]] [filter <String>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print chatmembers [todrive <ToDriveAttribute>*] <ChatSpace>
[showinvited [<Boolean>]] [filter <String>]
[formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
By default, only `JOINED` members are displayed; use `showinvited` to also display `INVITED` members.
Use `filter <String>` to filter memberships by a member's `role `and `member.type`.
* To filter by role, set role to ROLE_MEMBER or ROLE_MANAGER.
* To filter by type, set member.type to HUMAN or BOT.
* To filter by both role and type, use the AND operator.
* To filter by either role or type, use the OR operator.
For example, the following queries are valid:
```
role = "ROLE_MANAGER" OR role = "ROLE_MEMBER"
member.type = "HUMAN" AND role = "ROLE_MANAGER"
```
The following queries are invalid:
```
member.type = "HUMAN" AND member.type = "BOT"
role = "ROLE_MANAGER" AND role = "ROLE_MEMBER"
```
### Delete a user from their `space` and `groupchat` spaces
There is no way to delete a user from a directmessage space.
```
gam redirect csv ./UserChatSpaces.csv user user@domain.com print chatspaces types space,groupchat
gam redirect stdout ./DeleteUserChatMemberships.txt multiprocess redirect stderr stdout csv ./UserChatSpaces.csv gam user "~User" delete chatmember "~name" user "~User"
```
## Manage Chat Messages
### Create a chat message in a space
Messages are limited to 4,096 characters and will be trimmed to that length.
Chat supports [simple formatting](https://developers.google.com/chat/reference/message-formats/basic#using_formatted_text_in_messages) allowing you to bold, underline, italics and strikethrough your text.
```
gam <UserTypeEntity> create chatmessage <ChatSpace>
<ChatContent>
[messageId <ChatMessageID>]
[(thread <ChatThread>)|(threadkey <String>) [replyoption fail|fallbacktonew]]
[returnidonly]
```
Specify the text of the message: `<ChatContent>`
* `text <String>` - The message is `<String>`
* `textfile <FileName> [charset <CharSet>]` - The message is read from a local file
* `gdoc <UserGoogleDoc>` - The message is read from a Google Doc.
* `gcsdoc <StorageBucketObjectName>` - The message is read from a Google Cloud Storage file.
By default, a new message thread is created; use `thread <ChatThread>` or `threadkey <String>` to create the message as a reply to an existing thread.
Use `replyoption` to specify what happens if the specified thread does not exist:
* `fail` - If the thread soes not exiat, a `Not Found` error is generated
* `fallbacktonew` - If the thread does not exist, start a new thread
The first time you reply to a thread you must use `thread <ChatThread>`; if you also specify `threadkey <String>`
then you can use just `threadkey <String>` in subsequent replies.
If you specify `thread` or `threadkey` but not `replyoption`, the default is `fail'.
By default, details about the chatmessage are displayed.
* `returnidonly` - Display the chatmessage name only
### Examples
This example creates a new chat message in the given room.
```
gam user user@domain.com create chatmessage space spaces/iEMj8AAAAAE text "Hello Chat"
```
This example creates a formatted message and posts it to an existing thread
```
gam user user@domain.com create chatmessage space spaces/AAAADi-pvqc thread spaces/AAAADi-pvqc/threads/FMNw-iE9jN4 text "*Bold* _Italics_ ~Strikethrough~"
```
This example reads the MotD.txt file and posts its contents to Chat.
```
gam user user@domain.com create chatmessage spaces spaces/AAAADi-pvqc textfile MotD.txt
```
This example reads the Google Doc MotD and posts its contents to Chat.
```
gam user user@domain.com create chatmessage spaces spaces/AAAADi-pvqc gdoc announcements@domain.com name "MotD"
```
### Update a Chat Message
Updates and rewrites an existing Chat message. Message will show as edited and no notification will be sent to members.
```
gam <UserTypeEntity> update chatmessage name <ChatMessage>
<ChatContent>
```
Specify the text of the message: `<ChatContent>`
* `text <String>` - The message is `<String>`
* `textfile <FileName> [charset <CharSet>]` - The message is read from a local file
* `gdoc <UserGoogleDoc>` - The message is read from a Google Doc.
* `gcsdoc <StorageBucketObjectName>` - The message is read from a Google Cloud Storage file.
### Example
This example updates an existing chat message with new text.
```
gam user user@domain.com update chatmessage name spaces/AAAADi-pvqc/messages/PKJrx90ooIU.PKJrx90ooIU text "HELLO CHAT?"
```
### Delete a Chat Message
Deletes the given Chat message. Members will no longer see the message.
```
gam <UserTypeEntity> delete chatmessage name <ChatMessage>
```
### Example
```
gam user user@domain.com delete chatmessage name spaces/AAAADi-pvqc/messages/PKJrx90ooIU.PKJrx90ooIU
```
## Display Chat Messages
Display a specific Chat message.
```
gam <UserTypeEntity> info chatmessage name <ChatMessage>
[filter <String>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Example
```
gam user user@domain.com info chatmessage name spaces/AAAADi-pvqc/messages/PKJrx90ooIU.PKJrx90ooIU
```
### Display information about all chat messages in a chat space
```
gam <UserTypeEntity> show chatmessages <ChatSpace>
[showdeleted [<Boolean>]] [filter <String>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print chatmessages [todrive <ToDriveAttribute>*] <ChatSpace>
[showdeleted [<Boolean>]] [filter <String>]
[formatjson [quotechar <Character>]]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
By default, deleted messages are not displayed; use `showdeleted` to also display deleted messages.
Use `filter <String>` to filter messages by `createTime` and `thread.name`.
To filter messages by the date they were created, specify the createTime with a timestamp in RFC-3339 format and double quotation marks. For example, "2023-04-21T11:30:00-04:00".
* Use the greater than operator `>` to list messages that were created after a timestamp.
* Use the less than operator `<` to list messages that were created before a timestamp.
* To filter messages within a time interval, use the AND operator between two timestamps.
* To filter by thread, specify the thread.name, formatted as spaces/{space}/threads/{thread}. You can only specify one thread.name per query.
* To filter by both thread and date, use the AND operator in your query.
For example, the following queries are valid on Linux/MacOS:
```
filter 'createTime > "2012-04-21T11:30:00-04:00"'
filter 'createTime > "2012-04-21T11:30:00-04:00" AND thread.name = spaces/AAAAAAAAAAA/threads/123'
filter 'createTime > "2012-04-21T11:30:00+00:00" AND createTime < "2013-01-01T00:00:00+00:00" AND thread.name = spaces/AAAAAAAAAAA/threads/123'
filter 'thread.name = spaces/AAAAAAAAAAA/threads/123'
```
For example, the following queries are valid on Windows Command Prompt:
```
filter "createTime > \"2012-04-21T11:30:00-04:00\""
filter "createTime > \"2012-04-21T11:30:00-04:00\" AND thread.name = spaces/AAAAAAAAAAA/threads/123"
filter "createTime > \"2012-04-21T11:30:00+00:00\" AND createTime < \"2013-01-01T00:00:00+00:00\" AND thread.name = spaces/AAAAAAAAAAA/threads/123"
filter "thread.name = spaces/AAAAAAAAAAA/threads/123"
```
For example, the following queries are valid on Windows PowerShell:
```
filter 'createTime > \"2012-04-21T11:30:00-04:00\"'
filter 'createTime > \"2012-04-21T11:30:00-04:00\" AND thread.name = spaces/AAAAAAAAAAA/threads/123"'
filter 'createTime > \"2012-04-21T11:30:00+00:00\" AND createTime < \"2013-01-01T00:00:00+00:00\" AND thread.name = spaces/AAAAAAAAAAA/threads/123'
filter 'thread.name = spaces/AAAAAAAAAAA/threads/123'
```
## Bulk Operations
### Display information about all chat spaces for a collection of users
```
gam config auto_batch_min 1 redirect csv ./ChatSpaces.csv multiprocess [todrive <ToDriveAttribute>*] redirect stdout - multiprocess redirect stderr <UserTypeEntity> print chatspaces
[types <ChatSpaceTypeList>]
[formatjson [quotechar <Character>]]
```
### Display information about all chat space members of the chat spaces for a collection of users
```
gam config auto_batch_min 1 redirect csv ./ChatSpaces.csv multiprocess [todrive <ToDriveAttribute>*] redirect stdout - multiprocess redirect stderr <UserTypeEntity> print chatspaces
[types <ChatSpaceTypeList>]
gam redirect csv ./ChatSpaceMembers.csv multiprocess [todrive <ToDriveAttribute>*] redirect stdout - multiprocess redirect stderr stdout csv ./ChatSpaces.csv gam user "~User" print chatmembers "~name"
[showinvited [<Boolean>]] [filter <String>]
```

View File

@ -0,0 +1,16 @@
# Users - Classroom - Profile
- [API documentation](#api-documentation)
- [Definitions](#definitions)
- [Display Classroom profile](#display-classroom-profile)
## API documentation
* https://developers.google.com/classroom/reference/rest/v1/userProfiles/get
## Definitions
* [`<UserTypeEntity>`](Collections-of-Users)
## Display Classroom profile
```
gam <UserTypeEntity> show classroomprofile
gam <UserTypeEntity> print classroomprofile [todrive <ToDriveAttribute>*]
```

Some files were not shown because too many files have changed in this diff Show More