コード例 #1
0
def modifySettings():
    calendarId, cal = buildCalendarDataGAPIObject(sys.argv[2])
    if not cal:
        return
    body = {}
    i = 4
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'description':
            body['description'] = sys.argv[i+1]
            i += 2
        elif myarg == 'location':
            body['location'] = sys.argv[i+1]
            i += 2
        elif myarg == 'summary':
            body['summary'] = sys.argv[i+1]
            i += 2
        elif myarg == 'timezone':
            body['timeZone'] = sys.argv[i+1]
            i += 2
        else:
            controlflow.invalid_argument_exit(
                sys.argv[i], "gam calendar <email> modify")
    gapi.call(cal.calendars(), 'patch', calendarId=calendarId, body=body)
コード例 #2
0
def infoCalendar(users):
    calendarId = normalizeCalendarId(sys.argv[5], checkPrimary=True)
    i = 0
    count = len(users)
    for user in users:
        i += 1
        user, cal = buildCalendarGAPIObject(user)
        if not cal:
            continue
        result = gapi.call(cal.calendarList(), 'get',
                           soft_errors=True,
                           calendarId=calendarId)
        if result:
            print(f'User: {user}, Calendar:{display.current_count(i, count)}')
            _showCalendar(result, 1, 1)
コード例 #3
0
  def test_call_retries_with_soft_errors(self, mock_error_detail):
    mock_error_detail.return_value = (-1, 'aReason', 'some message')

    # Make the request fail first, then return the proper response on the retry.
    fake_http_error = create_http_error(403, 'aReason', 'unused message')
    fake_200_response = MagicMock()
    self.mock_method.return_value.execute.side_effect = [
        fake_http_error, fake_200_response
    ]

    response = gapi.call(
        self.mock_service, self.mock_method_name, soft_errors=True)
    self.assertEqual(response, fake_200_response)
    self.assertEqual(
        self.mock_service._http.request.credentials.refresh.call_count, 1)
    self.assertEqual(self.mock_method.return_value.execute.call_count, 2)
コード例 #4
0
  def test_call_retries_requests_with_backoff_on_servernotfounderror(
      self, mock_wait_on_failure):
    fake_servernotfounderror = gapi.httplib2.ServerNotFoundError()
    fake_200_response = MagicMock()
    # Fail once, then succeed on retry
    self.mock_method.return_value.execute.side_effect = [
        fake_servernotfounderror, fake_200_response
    ]

    http_connections = self.mock_service._http.connections
    response = gapi.call(self.mock_service, self.mock_method_name)
    self.assertEqual(response, fake_200_response)
    # HTTP cached connections should be cleared on receiving this error
    self.assertNotEqual(http_connections, self.mock_service._http.connections)
    self.assertEqual(self.mock_method.return_value.execute.call_count, 2)
    # Make sure a backoff technique was used for retry.
    self.assertEqual(mock_wait_on_failure.call_count, 1)
コード例 #5
0
  def test_call_retries_request_for_default_retry_reasons(
      self, mock_wait_on_failure):

    # Test using one of the default retry reasons
    default_throw_reason = errors.ErrorReason.BACKEND_ERROR
    self.assertIn(default_throw_reason, errors.DEFAULT_RETRY_REASONS)

    fake_http_error = create_http_error(404, default_throw_reason, 'message')
    fake_200_response = MagicMock()
    # Fail once, then succeed on retry
    self.mock_method.return_value.execute.side_effect = [
        fake_http_error, fake_200_response
    ]

    response = gapi.call(
        self.mock_service, self.mock_method_name, retry_reasons=[])
    self.assertEqual(response, fake_200_response)
    self.assertEqual(self.mock_method.return_value.execute.call_count, 2)
    # Make sure a backoff technique was used for retry.
    self.assertEqual(mock_wait_on_failure.call_count, 1)
コード例 #6
0
ファイル: __init___test.py プロジェクト: webreact/GAM
 def test_call_returns_basic_200_response(self):
     response = gapi.call(self.mock_service, self.mock_method_name)
     self.assertEqual(response, self.mock_method().execute.return_value)
コード例 #7
0
ファイル: __init___test.py プロジェクト: webreact/GAM
    def test_call_exits_on_request_valueerror(self):
        self.mock_method.return_value.execute.side_effect = ValueError()

        with self.assertRaises(SystemExit):
            gapi.call(self.mock_service, self.mock_method_name)
コード例 #8
0
def doUpdateCros():
    cd = gapi.directory.buildGAPIObject()
    i, devices = getCrOSDeviceEntity(3, cd)
    update_body = {}
    action_body = {}
    orgUnitPath = None
    ack_wipe = False
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'user':
            update_body['annotatedUser'] = sys.argv[i+1]
            i += 2
        elif myarg == 'location':
            update_body['annotatedLocation'] = sys.argv[i+1]
            i += 2
        elif myarg == 'notes':
            update_body['notes'] = sys.argv[i+1].replace('\\n', '\n')
            i += 2
        elif myarg in ['tag', 'asset', 'assetid']:
            update_body['annotatedAssetId'] = sys.argv[i+1]
            i += 2
        elif myarg in ['ou', 'org']:
            orgUnitPath = __main__.getOrgUnitItem(sys.argv[i+1])
            i += 2
        elif myarg == 'action':
            action = sys.argv[i+1].lower().replace('_', '').replace('-', '')
            deprovisionReason = None
            if action in ['deprovisionsamemodelreplace',
                          'deprovisionsamemodelreplacement']:
                action = 'deprovision'
                deprovisionReason = 'same_model_replacement'
            elif action in ['deprovisiondifferentmodelreplace',
                            'deprovisiondifferentmodelreplacement']:
                action = 'deprovision'
                deprovisionReason = 'different_model_replacement'
            elif action in ['deprovisionretiringdevice']:
                action = 'deprovision'
                deprovisionReason = 'retiring_device'
            elif action not in ['disable', 'reenable']:
                controlflow.system_error_exit(2, f'expected action of ' \
                    f'deprovision_same_model_replace, ' \
                    f'deprovision_different_model_replace, ' \
                    f'deprovision_retiring_device, disable or reenable,'
                    f' got {action}')
            action_body = {'action': action}
            if deprovisionReason:
                action_body['deprovisionReason'] = deprovisionReason
            i += 2
        elif myarg == 'acknowledgedevicetouchrequirement':
            ack_wipe = True
            i += 1
        else:
            controlflow.invalid_argument_exit(sys.argv[i], "gam update cros")
    i = 0
    count = len(devices)
    if action_body:
        if action_body['action'] == 'deprovision' and not ack_wipe:
            print(f'WARNING: Refusing to deprovision {count} devices because '
                  'acknowledge_device_touch_requirement not specified. ' \
                  '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 add ' \
                  '"acknowledge_device_touch_requirement" to the GAM ' \
                  'command if you understand this and wish to proceed ' \
                  'with the deprovision. 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.')
            sys.exit(3)
        for deviceId in devices:
            i += 1
            cur_count = __main__.currentCount(i, count)
            print(f' performing action {action} for {deviceId}{cur_count}')
            gapi.call(cd.chromeosdevices(), function='action',
                      customerId=GC_Values[GC_CUSTOMER_ID],
                      resourceId=deviceId, body=action_body)
    else:
        if update_body:
            for deviceId in devices:
                i += 1
                current_count = __main__.currentCount(i, count)
                print(f' updating {deviceId}{current_count}')
                gapi.call(cd.chromeosdevices(), 'update',
                          customerId=GC_Values[GC_CUSTOMER_ID],
                          deviceId=deviceId, body=update_body)
        if orgUnitPath:
            # split moves into max 50 devices per batch
            for l in range(0, len(devices), 50):
                move_body = {'deviceIds': devices[l:l+50]}
                print(f' moving {len(move_body["deviceIds"])} devices to ' \
                      f'{orgUnitPath}')
                gapi.call(cd.chromeosdevices(), 'moveDevicesToOu',
                          customerId=GC_Values[GC_CUSTOMER_ID],
                          orgUnitPath=orgUnitPath, body=move_body)
コード例 #9
0
def updateMatter(action=None):
    v = buildGAPIObject()
    matterId = getMatterItem(v, sys.argv[3])
    body = {}
    action_kwargs = {'body': {}}
    add_collaborators = []
    remove_collaborators = []
    cd = None
    i = 4
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'action':
            action = sys.argv[i + 1].lower()
            if action not in VAULT_MATTER_ACTIONS:
                controlflow.system_error_exit(3, f'allowed actions are ' \
                    f'{", ".join(VAULT_MATTER_ACTIONS)}, got {action}')
            i += 2
        elif myarg == 'name':
            body['name'] = sys.argv[i + 1]
            i += 2
        elif myarg == 'description':
            body['description'] = sys.argv[i + 1]
            i += 2
        elif myarg in ['addcollaborator', 'addcollaborators']:
            if not cd:
                cd = __main__.buildGAPIObject('directory')
            add_collaborators.extend(validateCollaborators(
                sys.argv[i + 1], cd))
            i += 2
        elif myarg in ['removecollaborator', 'removecollaborators']:
            if not cd:
                cd = __main__.buildGAPIObject('directory')
            remove_collaborators.extend(
                validateCollaborators(sys.argv[i + 1], cd))
            i += 2
        else:
            controlflow.invalid_argument_exit(sys.argv[i], "gam update matter")
    if action == 'delete':
        action_kwargs = {}
    if body:
        print(f'Updating matter {sys.argv[3]}...')
        if 'name' not in body or 'description' not in body:
            # bah, API requires name/description to be sent
            # on update even when it's not changing
            result = gapi.call(v.matters(),
                               'get',
                               matterId=matterId,
                               view='BASIC')
            body.setdefault('name', result['name'])
            body.setdefault('description', result.get('description'))
        gapi.call(v.matters(), 'update', body=body, matterId=matterId)
    if action:
        print(f'Performing {action} on matter {sys.argv[3]}')
        gapi.call(v.matters(), action, matterId=matterId, **action_kwargs)
    for collaborator in add_collaborators:
        print(f' adding collaborator {collaborator["email"]}')
        body = {
            'matterPermission': {
                'role': 'COLLABORATOR',
                'accountId': collaborator['id']
            }
        }
        gapi.call(v.matters(), 'addPermissions', matterId=matterId, body=body)
    for collaborator in remove_collaborators:
        print(f' removing collaborator {collaborator["email"]}')
        gapi.call(v.matters(),
                  'removePermissions',
                  matterId=matterId,
                  body={'accountId': collaborator['id']})
コード例 #10
0
def changeAttendees(users):
    do_it = True
    i = 5
    allevents = False
    start_date = end_date = None
    while len(sys.argv) > i:
        myarg = sys.argv[i].lower()
        if myarg == 'csv':
            csv_file = sys.argv[i + 1]
            i += 2
        elif myarg == 'dryrun':
            do_it = False
            i += 1
        elif myarg == 'start':
            start_date = utils.get_time_or_delta_from_now(sys.argv[i + 1])
            i += 2
        elif myarg == 'end':
            end_date = utils.get_time_or_delta_from_now(sys.argv[i + 1])
            i += 2
        elif myarg == 'allevents':
            allevents = True
            i += 1
        else:
            controlflow.invalid_argument_exit(
                sys.argv[i], "gam <users> update calattendees")
    attendee_map = {}
    f = fileutils.open_file(csv_file)
    csvFile = csv.reader(f)
    for row in csvFile:
        attendee_map[row[0].lower()] = row[1].lower()
    fileutils.close_file(f)
    for user in users:
        sys.stdout.write(f'Checking user {user}\n')
        user, cal = buildCalendarGAPIObject(user)
        if not cal:
            continue
        page_token = None
        while True:
            events_page = gapi.call(cal.events(),
                                    'list',
                                    calendarId=user,
                                    pageToken=page_token,
                                    timeMin=start_date,
                                    timeMax=end_date,
                                    showDeleted=False,
                                    showHiddenInvitations=False)
            print(f'Got {len(events_page.get("items", []))}')
            for event in events_page.get('items', []):
                if event['status'] == 'cancelled':
                    # print u' skipping cancelled event'
                    continue
                try:
                    event_summary = event['summary']
                except (KeyError, UnicodeEncodeError, UnicodeDecodeError):
                    event_summary = event['id']
                try:
                    organizer = event['organizer']['email'].lower()
                    if not allevents and organizer != user:
                        #print(f' skipping not-my-event {event_summary}')
                        continue
                except KeyError:
                    pass  # no email for organizer
                needs_update = False
                try:
                    for attendee in event['attendees']:
                        try:
                            if attendee['email'].lower() in attendee_map:
                                old_email = attendee['email'].lower()
                                new_email = attendee_map[
                                    attendee['email'].lower()]
                                print(f' SWITCHING attendee {old_email} to ' \
                                    f'{new_email} for {event_summary}')
                                event['attendees'].remove(attendee)
                                event['attendees'].append({'email': new_email})
                                needs_update = True
                        except KeyError:  # no email for that attendee
                            pass
                except KeyError:
                    continue  # no attendees
                if needs_update:
                    body = {}
                    body['attendees'] = event['attendees']
                    print(f'UPDATING {event_summary}')
                    if do_it:
                        gapi.call(cal.events(),
                                  'patch',
                                  calendarId=user,
                                  eventId=event['id'],
                                  sendNotifications=False,
                                  body=body)
                    else:
                        print(' not pulling the trigger.')
                # else:
                #  print(f' no update needed for {event_summary}')
            try:
                page_token = events_page['nextPageToken']
            except KeyError:
                break
コード例 #11
0
ファイル: vault.py プロジェクト: rkx-forks/GAM
def createExport():
    v = buildGAPIObject()
    allowed_corpuses = gapi.get_enum_values_minus_unspecified(
        v._rootDesc['schemas']['Query']['properties']['corpus']['enum'])
    allowed_scopes = gapi.get_enum_values_minus_unspecified(
        v._rootDesc['schemas']['Query']['properties']['dataScope']['enum'])
    allowed_formats = gapi.get_enum_values_minus_unspecified(
        v._rootDesc['schemas']['MailExportOptions']['properties']
        ['exportFormat']['enum'])
    export_format = 'MBOX'
    showConfidentialModeContent = None  # default to not even set
    matterId = None
    body = {'query': {'dataScope': 'ALL_DATA'}, 'exportOptions': {}}
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'matter':
            matterId = getMatterItem(v, sys.argv[i+1])
            body['matterId'] = matterId
            i += 2
        elif myarg == 'name':
            body['name'] = sys.argv[i+1]
            i += 2
        elif myarg == 'corpus':
            body['query']['corpus'] = sys.argv[i+1].upper()
            if body['query']['corpus'] not in allowed_corpuses:
                controlflow.expected_argument_exit(
                    "corpus", ", ".join(allowed_corpuses), sys.argv[i+1])
            i += 2
        elif myarg in VAULT_SEARCH_METHODS_MAP:
            if body['query'].get('searchMethod'):
                message = f'Multiple search methods ' \
                          f'({", ".join(VAULT_SEARCH_METHODS_LIST)})' \
                          f'specified, only one is allowed'
                controlflow.system_error_exit(3, message)
            searchMethod = VAULT_SEARCH_METHODS_MAP[myarg]
            body['query']['searchMethod'] = searchMethod
            if searchMethod == 'ACCOUNT':
                body['query']['accountInfo'] = {
                    'emails': sys.argv[i+1].split(',')}
                i += 2
            elif searchMethod == 'ORG_UNIT':
                body['query']['orgUnitInfo'] = {
                    'orgUnitId': __main__.getOrgUnitId(sys.argv[i+1])[1]}
                i += 2
            elif searchMethod == 'SHARED_DRIVE':
                body['query']['sharedDriveInfo'] = {
                    'sharedDriveIds': sys.argv[i+1].split(',')}
                i += 2
            elif searchMethod == 'ROOM':
                body['query']['hangoutsChatInfo'] = {
                    'roomId': sys.argv[i+1].split(',')}
                i += 2
            else:
                i += 1
        elif myarg == 'scope':
            body['query']['dataScope'] = sys.argv[i+1].upper()
            if body['query']['dataScope'] not in allowed_scopes:
                controlflow.expected_argument_exit(
                    "scope", ", ".join(allowed_scopes), sys.argv[i+1])
            i += 2
        elif myarg in ['terms']:
            body['query']['terms'] = sys.argv[i+1]
            i += 2
        elif myarg in ['start', 'starttime']:
            body['query']['startTime'] = utils.get_date_zero_time_or_full_time(
                sys.argv[i+1])
            i += 2
        elif myarg in ['end', 'endtime']:
            body['query']['endTime'] = utils.get_date_zero_time_or_full_time(
                sys.argv[i+1])
            i += 2
        elif myarg in ['timezone']:
            body['query']['timeZone'] = sys.argv[i+1]
            i += 2
        elif myarg in ['excludedrafts']:
            body['query']['mailOptions'] = {
                'excludeDrafts': __main__.getBoolean(sys.argv[i+1], myarg)}
            i += 2
        elif myarg in ['driveversiondate']:
            body['query'].setdefault('driveOptions', {})['versionDate'] = \
                utils.get_date_zero_time_or_full_time(sys.argv[i+1])
            i += 2
        elif myarg in ['includeshareddrives', 'includeteamdrives']:
            body['query'].setdefault('driveOptions', {})[
                'includeSharedDrives'] = __main__.getBoolean(sys.argv[i+1], myarg)
            i += 2
        elif myarg in ['includerooms']:
            body['query']['hangoutsChatOptions'] = {
                'includeRooms': __main__.getBoolean(sys.argv[i+1], myarg)}
            i += 2
        elif myarg in ['format']:
            export_format = sys.argv[i+1].upper()
            if export_format not in allowed_formats:
                controlflow.expected_argument_exit(
                    "export format", ", ".join(allowed_formats), export_format)
            i += 2
        elif myarg in ['showconfidentialmodecontent']:
            showConfidentialModeContent = __main__.getBoolean(sys.argv[i+1], myarg)
            i += 2
        elif myarg in ['region']:
            allowed_regions = gapi.get_enum_values_minus_unspecified(
                v._rootDesc['schemas']['ExportOptions']['properties'][
                    'region']['enum'])
            body['exportOptions']['region'] = sys.argv[i+1].upper()
            if body['exportOptions']['region'] not in allowed_regions:
                controlflow.expected_argument_exit("region", ", ".join(
                    allowed_regions), body['exportOptions']['region'])
            i += 2
        elif myarg in ['includeaccessinfo']:
            body['exportOptions'].setdefault('driveOptions', {})[
                'includeAccessInfo'] = __main__.getBoolean(sys.argv[i+1], myarg)
            i += 2
        else:
            controlflow.invalid_argument_exit(sys.argv[i], "gam create export")
    if not matterId:
        controlflow.system_error_exit(
            3, 'you must specify a matter for the new export.')
    if 'corpus' not in body['query']:
        controlflow.system_error_exit(3, f'you must specify a corpus for the ' \
          f'new export. Choose one of {", ".join(allowed_corpuses)}')
    if 'searchMethod' not in body['query']:
        controlflow.system_error_exit(3, f'you must specify a search method ' \
          'for the new export. Choose one of ' \
          f'{", ".join(VAULT_SEARCH_METHODS_LIST)}')
    if 'name' not in body:
        corpus_name = body["query"]["corpus"]
        corpus_date = datetime.datetime.now()
        body['name'] = f'GAM {corpus_name} export - {corpus_date}'
    options_field = None
    if body['query']['corpus'] == 'MAIL':
        options_field = 'mailOptions'
    elif body['query']['corpus'] == 'GROUPS':
        options_field = 'groupsOptions'
    elif body['query']['corpus'] == 'HANGOUTS_CHAT':
        options_field = 'hangoutsChatOptions'
    if options_field:
        body['exportOptions'].pop('driveOptions', None)
        body['exportOptions'][options_field] = {'exportFormat': export_format}
        if showConfidentialModeContent is not None:
            body['exportOptions'][options_field][
                'showConfidentialModeContent'] = showConfidentialModeContent
    results = gapi.call(v.matters().exports(), 'create',
                        matterId=matterId, body=body)
    print(f'Created export {results["id"]}')
    display.print_json(results)
コード例 #12
0
ファイル: vault.py プロジェクト: rkx-forks/GAM
def updateHold():
    v = buildGAPIObject()
    hold = sys.argv[3]
    matterId = None
    body = {}
    query = None
    add_accounts = []
    del_accounts = []
    start_time = None
    end_time = None
    i = 4
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'matter':
            matterId = getMatterItem(v, sys.argv[i+1])
            holdId = convertHoldNameToID(v, hold, matterId)
            i += 2
        elif myarg == 'query':
            query = sys.argv[i+1]
            i += 2
        elif myarg in ['orgunit', 'ou']:
            body['orgUnit'] = {'orgUnitId': __main__.getOrgUnitId(sys.argv[i+1])[1]}
            i += 2
        elif myarg in ['start', 'starttime']:
            start_time = utils.get_date_zero_time_or_full_time(sys.argv[i+1])
            i += 2
        elif myarg in ['end', 'endtime']:
            end_time = utils.get_date_zero_time_or_full_time(sys.argv[i+1])
            i += 2
        elif myarg in ['addusers', 'addaccounts', 'addgroups']:
            add_accounts = sys.argv[i+1].split(',')
            i += 2
        elif myarg in ['removeusers', 'removeaccounts', 'removegroups']:
            del_accounts = sys.argv[i+1].split(',')
            i += 2
        else:
            controlflow.invalid_argument_exit(myarg, "gam update hold")
    if not matterId:
        controlflow.system_error_exit(
            3, 'you must specify a matter for the hold.')
    if query or start_time or end_time or body.get('orgUnit'):
        fields = 'corpus,query,orgUnit'
        old_body = gapi.call(v.matters().holds(
        ), 'get', matterId=matterId, holdId=holdId, fields=fields)
        body['query'] = old_body['query']
        body['corpus'] = old_body['corpus']
        if 'orgUnit' in old_body and 'orgUnit' not in body:
            # bah, API requires this to be sent
            # on update even when it's not changing
            body['orgUnit'] = old_body['orgUnit']
        query_type = f'{body["corpus"].lower()}Query'
        if body['corpus'] == 'DRIVE':
            if query:
                try:
                    body['query'][query_type] = json.loads(query)
                except ValueError as e:
                    message = f'{str(e)}, query: {query}'
                    controlflow.system_error_exit(3, message)
        elif body['corpus'] in ['GROUPS', 'MAIL']:
            if query:
                body['query'][query_type]['terms'] = query
            if start_time:
                body['query'][query_type]['startTime'] = start_time
            if end_time:
                body['query'][query_type]['endTime'] = end_time
    if body:
        print(f'Updating hold {hold} / {holdId}')
        gapi.call(v.matters().holds(), 'update',
                  matterId=matterId, holdId=holdId, body=body)
    if add_accounts or del_accounts:
        cd = __main__.buildGAPIObject('directory')
        for account in add_accounts:
            print(f'adding {account} to hold.')
            add_body = {'accountId': __main__.convertEmailAddressToUID(account, cd)}
            gapi.call(v.matters().holds().accounts(), 'create',
                      matterId=matterId, holdId=holdId, body=add_body)
        for account in del_accounts:
            print(f'removing {account} from hold.')
            accountId = __main__.convertEmailAddressToUID(account, cd)
            gapi.call(v.matters().holds().accounts(), 'delete',
                      matterId=matterId, holdId=holdId, accountId=accountId)
コード例 #13
0
ファイル: vault.py プロジェクト: rkx-forks/GAM
def createHold():
    v = buildGAPIObject()
    allowed_corpuses = gapi.get_enum_values_minus_unspecified(
        v._rootDesc['schemas']['Hold']['properties']['corpus']['enum'])
    body = {'query': {}}
    i = 3
    query = None
    start_time = None
    end_time = None
    matterId = None
    accounts = []
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'name':
            body['name'] = sys.argv[i+1]
            i += 2
        elif myarg == 'query':
            query = sys.argv[i+1]
            i += 2
        elif myarg == 'corpus':
            body['corpus'] = sys.argv[i+1].upper()
            if body['corpus'] not in allowed_corpuses:
                controlflow.expected_argument_exit(
                    "corpus", ", ".join(allowed_corpuses), sys.argv[i+1])
            i += 2
        elif myarg in ['accounts', 'users', 'groups']:
            accounts = sys.argv[i+1].split(',')
            i += 2
        elif myarg in ['orgunit', 'ou']:
            body['orgUnit'] = {
                'orgUnitId': __main__.getOrgUnitId(sys.argv[i+1])[1]}
            i += 2
        elif myarg in ['start', 'starttime']:
            start_time = utils.get_date_zero_time_or_full_time(sys.argv[i+1])
            i += 2
        elif myarg in ['end', 'endtime']:
            end_time = utils.get_date_zero_time_or_full_time(sys.argv[i+1])
            i += 2
        elif myarg == 'matter':
            matterId = getMatterItem(v, sys.argv[i+1])
            i += 2
        else:
            controlflow.invalid_argument_exit(sys.argv[i], "gam create hold")
    if not matterId:
        controlflow.system_error_exit(
            3, 'you must specify a matter for the new hold.')
    if not body.get('name'):
        controlflow.system_error_exit(
            3, 'you must specify a name for the new hold.')
    if not body.get('corpus'):
        controlflow.system_error_exit(3, f'you must specify a corpus for ' \
          f'the new hold. Choose one of {", ".join(allowed_corpuses)}')
    if body['corpus'] == 'HANGOUTS_CHAT':
        query_type = 'hangoutsChatQuery'
    else:
        query_type = f'{body["corpus"].lower()}Query'
    body['query'][query_type] = {}
    if body['corpus'] == 'DRIVE':
        if query:
            try:
                body['query'][query_type] = json.loads(query)
            except ValueError as e:
                controlflow.system_error_exit(3, f'{str(e)}, query: {query}')
    elif body['corpus'] in ['GROUPS', 'MAIL']:
        if query:
            body['query'][query_type] = {'terms': query}
        if start_time:
            body['query'][query_type]['startTime'] = start_time
        if end_time:
            body['query'][query_type]['endTime'] = end_time
    if accounts:
        body['accounts'] = []
        cd = __main__.buildGAPIObject('directory')
        account_type = 'group' if body['corpus'] == 'GROUPS' else 'user'
        for account in accounts:
            body['accounts'].append(
                {'accountId': __main__.convertEmailAddressToUID(account,
                                                                cd,
                                                                account_type)}
            )
    holdId = gapi.call(v.matters().holds(), 'create',
                       matterId=matterId, body=body, fields='holdId')
    print(f'Created hold {holdId["holdId"]}')
コード例 #14
0
ファイル: reports.py プロジェクト: janatiMed/GAM
def showUsageParameters():
    rep = buildGAPIObject()
    throw_reasons = [
        gapi.errors.ErrorReason.INVALID, gapi.errors.ErrorReason.BAD_REQUEST
    ]
    todrive = False
    if len(sys.argv) == 3:
        controlflow.missing_argument_exit('user or customer',
                                          'report usageparameters')
    report = sys.argv[3].lower()
    titles = ['parameter']
    if report == 'customer':
        endpoint = rep.customerUsageReports()
        kwargs = {}
    elif report == 'user':
        endpoint = rep.userUsageReport()
        kwargs = {'userKey': __main__._getValueFromOAuth('email')}
    else:
        controlflow.expected_argument_exit('usageparameters',
                                           ['user', 'customer'], report)
    customerId = GC_Values[GC_CUSTOMER_ID]
    if customerId == MY_CUSTOMER:
        customerId = None
    tryDate = datetime.date.today().strftime(YYYYMMDD_FORMAT)
    partial_apps = []
    all_parameters = []
    one_day = datetime.timedelta(days=1)
    i = 4
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'todrive':
            todrive = True
            i += 1
        else:
            controlflow.invalid_argument_exit(sys.argv[i],
                                              "gam report usageparameters")
    while True:
        try:
            response = gapi.call(endpoint,
                                 'get',
                                 throw_reasons=throw_reasons,
                                 date=tryDate,
                                 customerId=customerId,
                                 **kwargs)
            partial_on_thisday = []
            for warning in response.get('warnings', []):
                for data in warning.get('data', []):
                    if data.get('key') == 'application':
                        partial_on_thisday.append(data['value'])
            if partial_apps:
                partial_apps = [
                    app for app in partial_apps if app in partial_on_thisday
                ]
            else:
                partial_apps = partial_on_thisday
            for parameter in response['usageReports'][0]['parameters']:
                name = parameter.get('name')
                if name and name not in all_parameters:
                    all_parameters.append(name)
            if not partial_apps:
                break
            tryDate = (utils.get_yyyymmdd(tryDate, returnDateTime=True) - \
                    one_day).strftime(YYYYMMDD_FORMAT)
        except gapi.errors.GapiInvalidError as e:
            tryDate = _adjust_date(str(e))
    all_parameters.sort()
    csvRows = []
    for parameter in all_parameters:
        csvRows.append({'parameter': parameter})
    display.write_csv_file(csvRows, titles,
                           f'{report.capitalize()} Report Usage Parameters',
                           todrive)
コード例 #15
0
def wipeData():
    calendarId, cal = buildCalendarDataGAPIObject(sys.argv[2])
    if not cal:
        return
    gapi.call(cal.calendars(), 'clear', calendarId=calendarId)
コード例 #16
0
def getEventAttributes(i, calendarId, cal, body, action):
    # Default to external only so non-Google
    # calendars are notified of changes
    sendUpdates = 'externalOnly'
    action = 'update' if body else 'add'
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg in ['notifyattendees', 'sendnotifications', 'sendupdates']:
            sendUpdates, i = getSendUpdates(myarg, i, cal)
        elif myarg == 'attendee':
            body.setdefault('attendees', [])
            body['attendees'].append({'email': sys.argv[i + 1]})
            i += 2
        elif myarg == 'removeattendee' and action == 'update':
            remove_email = sys.argv[i + 1].lower()
            if 'attendees' in body:
                body['attendees'] = _remove_attendee(body['attendees'],
                                                     remove_email)
            i += 2
        elif myarg == 'optionalattendee':
            body.setdefault('attendees', [])
            body['attendees'].append({
                'email': sys.argv[i + 1],
                'optional': True
            })
            i += 2
        elif myarg == 'anyonecanaddself':
            body['anyoneCanAddSelf'] = True
            i += 1
        elif myarg == 'description':
            body['description'] = sys.argv[i + 1].replace('\\n', '\n')
            i += 2
        elif myarg == 'replacedescription' and action == 'update':
            search = sys.argv[i + 1]
            replace = sys.argv[i + 2]
            if 'description' in body:
                body['description'] = re.sub(search, replace,
                                             body['description'])
            i += 3
        elif myarg == 'start':
            if sys.argv[i + 1].lower() == 'allday':
                body['start'] = {'date': utils.get_yyyymmdd(sys.argv[i + 2])}
                i += 3
            else:
                start_time = utils.get_time_or_delta_from_now(sys.argv[i + 1])
                body['start'] = {'dateTime': start_time}
                i += 2
        elif myarg == 'end':
            if sys.argv[i + 1].lower() == 'allday':
                body['end'] = {'date': utils.get_yyyymmdd(sys.argv[i + 2])}
                i += 3
            else:
                end_time = utils.get_time_or_delta_from_now(sys.argv[i + 1])
                body['end'] = {'dateTime': end_time}
                i += 2
        elif myarg == 'guestscantinviteothers':
            body['guestsCanInviteOthers'] = False
            i += 1
        elif myarg == 'guestscaninviteothers':
            body['guestsCanInviteTohters'] = __main__.getBoolean(
                sys.argv[i + 1], 'guestscaninviteothers')
            i += 2
        elif myarg == 'guestscantseeothers':
            body['guestsCanSeeOtherGuests'] = False
            i += 1
        elif myarg == 'guestscanseeothers':
            body['guestsCanSeeOtherGuests'] = __main__.getBoolean(
                sys.argv[i + 1], 'guestscanseeothers')
            i += 2
        elif myarg == 'guestscanmodify':
            body['guestsCanModify'] = __main__.getBoolean(
                sys.argv[i + 1], 'guestscanmodify')
            i += 2
        elif myarg == 'id':
            if action == 'update':
                controlflow.invalid_argument_exit(
                    'id', 'gam calendar <calendar> updateevent')
            body['id'] = sys.argv[i + 1]
            i += 2
        elif myarg == 'summary':
            body['summary'] = sys.argv[i + 1]
            i += 2
        elif myarg == 'location':
            body['location'] = sys.argv[i + 1]
            i += 2
        elif myarg == 'available':
            body['transparency'] = 'transparent'
            i += 1
        elif myarg == 'transparency':
            validTransparency = ['opaque', 'transparent']
            if sys.argv[i + 1].lower() in validTransparency:
                body['transparency'] = sys.argv[i + 1].lower()
            else:
                controlflow.expected_argument_exit(
                    'transparency', ", ".join(validTransparency),
                    sys.argv[i + 1])
            i += 2
        elif myarg == 'visibility':
            validVisibility = ['default', 'public', 'private']
            if sys.argv[i + 1].lower() in validVisibility:
                body['visibility'] = sys.argv[i + 1].lower()
            else:
                controlflow.expected_argument_exit("visibility",
                                                   ", ".join(validVisibility),
                                                   sys.argv[i + 1])
            i += 2
        elif myarg == 'tentative':
            body['status'] = 'tentative'
            i += 1
        elif myarg == 'status':
            validStatus = ['confirmed', 'tentative', 'cancelled']
            if sys.argv[i + 1].lower() in validStatus:
                body['status'] = sys.argv[i + 1].lower()
            else:
                controlflow.expected_argument_exit('visibility',
                                                   ', '.join(validStatus),
                                                   sys.argv[i + 1])
            i += 2
        elif myarg == 'source':
            body['source'] = {'title': sys.argv[i + 1], 'url': sys.argv[i + 2]}
            i += 3
        elif myarg == 'noreminders':
            body['reminders'] = {'useDefault': False}
            i += 1
        elif myarg == 'reminder':
            minutes = \
            __main__.getInteger(sys.argv[i+1], myarg, minVal=0,
                                maxVal=CALENDAR_REMINDER_MAX_MINUTES)
            reminder = {'minutes': minutes, 'method': sys.argv[i + 2]}
            body.setdefault('reminders', {
                'overrides': [],
                'useDefault': False
            })
            body['reminders']['overrides'].append(reminder)
            i += 3
        elif myarg == 'recurrence':
            body.setdefault('recurrence', [])
            body['recurrence'].append(sys.argv[i + 1])
            i += 2
        elif myarg == 'timezone':
            timeZone = sys.argv[i + 1]
            i += 2
        elif myarg == 'privateproperty':
            if 'extendedProperties' not in body:
                body['extendedProperties'] = {'private': {}, 'shared': {}}
            body['extendedProperties']['private'][sys.argv[i +
                                                           1]] = sys.argv[i +
                                                                          2]
            i += 3
        elif myarg == 'sharedproperty':
            if 'extendedProperties' not in body:
                body['extendedProperties'] = {'private': {}, 'shared': {}}
            body['extendedProperties']['shared'][sys.argv[i +
                                                          1]] = sys.argv[i + 2]
            i += 3
        elif myarg == 'colorindex':
            body['colorId'] = __main__.getInteger(
                sys.argv[i + 1], myarg, CALENDAR_EVENT_MIN_COLOR_INDEX,
                CALENDAR_EVENT_MAX_COLOR_INDEX)
            i += 2
        elif myarg == 'hangoutsmeet':
            body['conferenceData'] = {
                'createRequest': {
                    'requestId': f'{str(uuid.uuid4())}'
                }
            }
            i += 1
        else:
            controlflow.invalid_argument_exit(
                sys.argv[i], f'gam calendar <email> {action}event')
    if ('recurrence' in body) and (('start' in body) or ('end' in body)):
        if not timeZone:
            timeZone = gapi.call(cal.calendars(),
                                 'get',
                                 calendarId=calendarId,
                                 fields='timeZone')['timeZone']
        if 'start' in body:
            body['start']['timeZone'] = timeZone
        if 'end' in body:
            body['end']['timeZone'] = timeZone
    return (sendUpdates, body)
コード例 #17
0
def doGetCrosInfo():
    cd = gapi.directory.buildGAPIObject()
    i, devices = getCrOSDeviceEntity(3, cd)
    downloadfile = None
    targetFolder = GC_Values[GC_DRIVE_DIR]
    projection = None
    fieldsList = []
    noLists = False
    startDate = endDate = None
    listLimit = 0
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'nolists':
            noLists = True
            i += 1
        elif myarg == 'listlimit':
            listLimit = __main__.getInteger(sys.argv[i+1], myarg, minVal=-1)
            i += 2
        elif myarg in CROS_START_ARGUMENTS:
            startDate = _getFilterDate(sys.argv[i+1])
            i += 2
        elif myarg in CROS_END_ARGUMENTS:
            endDate = _getFilterDate(sys.argv[i+1])
            i += 2
        elif myarg == 'allfields':
            projection = 'FULL'
            fieldsList = []
            i += 1
        elif myarg in PROJECTION_CHOICES_MAP:
            projection = PROJECTION_CHOICES_MAP[myarg]
            if projection == 'FULL':
                fieldsList = []
            else:
                fieldsList = CROS_BASIC_FIELDS_LIST[:]
            i += 1
        elif myarg in CROS_ARGUMENT_TO_PROPERTY_MAP:
            fieldsList.extend(CROS_ARGUMENT_TO_PROPERTY_MAP[myarg])
            i += 1
        elif myarg == 'fields':
            fieldNameList = sys.argv[i+1]
            for field in fieldNameList.lower().replace(',', ' ').split():
                if field in CROS_ARGUMENT_TO_PROPERTY_MAP:
                    fieldsList.extend(CROS_ARGUMENT_TO_PROPERTY_MAP[field])
                    if field in CROS_ACTIVE_TIME_RANGES_ARGUMENTS + \
                                CROS_DEVICE_FILES_ARGUMENTS + \
                                CROS_RECENT_USERS_ARGUMENTS:
                        projection = 'FULL'
                        noLists = False
                else:
                    controlflow.invalid_argument_exit(
                        field, "gam info cros fields")
            i += 2
        elif myarg == 'downloadfile':
            downloadfile = sys.argv[i+1]
            if downloadfile.lower() == 'latest':
                downloadfile = downloadfile.lower()
            i += 2
        elif myarg == 'targetfolder':
            targetFolder = os.path.expanduser(sys.argv[i+1])
            if not os.path.isdir(targetFolder):
                os.makedirs(targetFolder)
            i += 2
        else:
            controlflow.invalid_argument_exit(sys.argv[i], "gam info cros")
    if fieldsList:
        fieldsList.append('deviceId')
        fields = ','.join(set(fieldsList)).replace('.', '/')
    else:
        fields = None
    i = 0
    device_count = len(devices)
    for deviceId in devices:
        i += 1
        cros = gapi.call(cd.chromeosdevices(), 'get',
                         customerId=GC_Values[GC_CUSTOMER_ID],
                         deviceId=deviceId, projection=projection,
                         fields=fields)
        print(f'CrOS Device: {deviceId} ({i} of {device_count})')
        if 'notes' in cros:
            cros['notes'] = cros['notes'].replace('\n', '\\n')
        if 'autoUpdateExpiration' in cros:
            cros['autoUpdateExpiration'] = utils.formatTimestampYMD(
                cros['autoUpdateExpiration'])
        _checkTPMVulnerability(cros)
        for up in CROS_SCALAR_PROPERTY_PRINT_ORDER:
            if up in cros:
                if isinstance(cros[up], str):
                    print(f'  {up}: {cros[up]}')
                else:
                    sys.stdout.write(f'  {up}:')
                    display.print_json(cros[up], '  ')
        if not noLists:
            activeTimeRanges = _filterTimeRanges(
                cros.get('activeTimeRanges', []), startDate, endDate)
            lenATR = len(activeTimeRanges)
            if lenATR:
                print('  activeTimeRanges')
                num_ranges = min(lenATR, listLimit or lenATR)
                for activeTimeRange in activeTimeRanges[:num_ranges]:
                    active_date = activeTimeRange["date"]
                    active_time = activeTimeRange["activeTime"]
                    duration = utils.formatMilliSeconds(active_time)
                    minutes = active_time // 60000
                    print(f'    date: {active_date}')
                    print(f'      activeTime: {active_time}')
                    print(f'      duration: {duration}')
                    print(f'      minutes: {minutes}')
            recentUsers = cros.get('recentUsers', [])
            lenRU = len(recentUsers)
            if lenRU:
                print('  recentUsers')
                num_ranges = min(lenRU, listLimit or lenRU)
                for recentUser in recentUsers[:num_ranges]:
                    useremail = recentUser.get("email")
                    if not useremail:
                        if recentUser["type"] == "USER_TYPE_UNMANAGED":
                            useremail = 'UnmanagedUser'
                        else:
                            useremail = 'Unknown'
                    print(f'    type: {recentUser["type"]}')
                    print(f'      email: {useremail}')
            deviceFiles = _filterCreateReportTime(
                cros.get('deviceFiles', []), 'createTime', startDate, endDate)
            lenDF = len(deviceFiles)
            if lenDF:
                num_ranges = min(lenDF, listLimit or lenDF)
                print('  deviceFiles')
                for deviceFile in deviceFiles[:num_ranges]:
                    device_type = deviceFile['type']
                    create_time = deviceFile['createTime']
                    print(f'    {device_type}: {create_time}')
            if downloadfile:
                deviceFiles = cros.get('deviceFiles', [])
                lenDF = len(deviceFiles)
                if lenDF:
                    if downloadfile == 'latest':
                        deviceFile = deviceFiles[-1]
                    else:
                        for deviceFile in deviceFiles:
                            if deviceFile['createTime'] == downloadfile:
                                break
                        else:
                            print(f'ERROR: file {downloadfile} not ' \
                                  f'available to download.')
                            deviceFile = None
                    if deviceFile:
                        created = deviceFile["createTime"]
                        downloadfile = f'cros-logs-{deviceId}-{created}.zip'
                        downloadfilename = os.path.join(targetFolder,
                                                        downloadfile)
                        dl_url = deviceFile['downloadUrl']
                        _, content = cd._http.request(dl_url)
                        fileutils.write_file(downloadfilename, content,
                                             mode='wb',
                                             continue_on_error=True)
                        print(f'Downloaded: {downloadfilename}')
                elif downloadfile:
                    print('ERROR: no files to download.')
            cpuStatusReports = _filterCreateReportTime(
                cros.get('cpuStatusReports', []),
                'reportTime',
                startDate,
                endDate)
            lenCSR = len(cpuStatusReports)
            if lenCSR:
                print('  cpuStatusReports')
                num_ranges = min(lenCSR, listLimit or lenCSR)
                for cpuStatusReport in cpuStatusReports[:num_ranges]:
                    print(f'    reportTime: {cpuStatusReport["reportTime"]}')
                    print('      cpuTemperatureInfo')
                    tempInfos = cpuStatusReport.get('cpuTemperatureInfo', [])
                    for tempInfo in tempInfos:
                        temp_label = tempInfo['label'].strip()
                        temperature = tempInfo['temperature']
                        print(f'        {temp_label}: {temperature}')
                    pct_info = cpuStatusReport["cpuUtilizationPercentageInfo"]
                    util = ",".join([str(x) for x in pct_info])
                    print(f'      cpuUtilizationPercentageInfo: {util}')
            diskVolumeReports = cros.get('diskVolumeReports', [])
            lenDVR = len(diskVolumeReports)
            if lenDVR:
                print('  diskVolumeReports')
                print('    volumeInfo')
                num_ranges = min(lenDVR, listLimit or lenDVR)
                for diskVolumeReport in diskVolumeReports[:num_ranges]:
                    volumeInfo = diskVolumeReport['volumeInfo']
                    for volume in volumeInfo:
                        vid = volume['volumeId']
                        vstorage_free = volume['storageFree']
                        vstorage_total = volume['storageTotal']
                        print(f'      volumeId: {vid}')
                        print(f'        storageFree: {vstorage_free}')
                        print(f'        storageTotal: {vstorage_total}')
            systemRamFreeReports = _filterCreateReportTime(
                cros.get('systemRamFreeReports', []),
                'reportTime', startDate, endDate)
            lenSRFR = len(systemRamFreeReports)
            if lenSRFR:
                print('  systemRamFreeReports')
                num_ranges = min(lenSRFR, listLimit or lenSRFR)
                for systemRamFreeReport in systemRamFreeReports[:num_ranges]:
                    report_time = systemRamFreeReport["reportTime"]
                    free_info = systemRamFreeReport["systemRamFreeInfo"]
                    free_ram = ",".join(free_info)
                    print(f'    reportTime: {report_time}')
                    print(f'      systemRamFreeInfo: {free_ram}')
コード例 #18
0
def write_csv_file(csvRows, titles, list_type, todrive):
    def rowDateTimeFilterMatch(dateMode, rowDate, op, filterDate):
        if not rowDate or not isinstance(rowDate, str):
            return False
        try:
            rowTime = dateutil.parser.parse(rowDate, ignoretz=True)
            if dateMode:
                rowDate = datetime.datetime(rowTime.year, rowTime.month,
                                            rowTime.day).isoformat() + 'Z'
        except ValueError:
            rowDate = NEVER_TIME
        if op == '<':
            return rowDate < filterDate
        if op == '<=':
            return rowDate <= filterDate
        if op == '>':
            return rowDate > filterDate
        if op == '>=':
            return rowDate >= filterDate
        if op == '!=':
            return rowDate != filterDate
        return rowDate == filterDate

    def rowCountFilterMatch(rowCount, op, filterCount):
        if isinstance(rowCount, str):
            if not rowCount.isdigit():
                return False
            rowCount = int(rowCount)
        elif not isinstance(rowCount, int):
            return False
        if op == '<':
            return rowCount < filterCount
        if op == '<=':
            return rowCount <= filterCount
        if op == '>':
            return rowCount > filterCount
        if op == '>=':
            return rowCount >= filterCount
        if op == '!=':
            return rowCount != filterCount
        return rowCount == filterCount

    def rowBooleanFilterMatch(rowBoolean, filterBoolean):
        if not isinstance(rowBoolean, bool):
            return False
        return rowBoolean == filterBoolean

    def headerFilterMatch(title):
        for filterStr in GC_Values[GC_CSV_HEADER_FILTER]:
            if filterStr.match(title):
                return True
        return False

    if GC_Values[GC_CSV_ROW_FILTER]:
        for column, filterVal in iter(GC_Values[GC_CSV_ROW_FILTER].items()):
            if column not in titles:
                sys.stderr.write(
                    f'WARNING: Row filter column "{column}" is not in output columns\n'
                )
                continue
            if filterVal[0] == 'regex':
                csvRows = [
                    row for row in csvRows
                    if filterVal[1].search(str(row.get(column, '')))
                ]
            elif filterVal[0] == 'notregex':
                csvRows = [
                    row for row in csvRows
                    if not filterVal[1].search(str(row.get(column, '')))
                ]
            elif filterVal[0] in ['date', 'time']:
                csvRows = [
                    row for row in csvRows if rowDateTimeFilterMatch(
                        filterVal[0] == 'date', row.get(column, ''),
                        filterVal[1], filterVal[2])
                ]
            elif filterVal[0] == 'count':
                csvRows = [
                    row for row in csvRows if rowCountFilterMatch(
                        row.get(column, 0), filterVal[1], filterVal[2])
                ]
            else:  #boolean
                csvRows = [
                    row for row in csvRows if rowBooleanFilterMatch(
                        row.get(column, False), filterVal[1])
                ]
    if GC_Values[GC_CSV_HEADER_FILTER]:
        titles = [t for t in titles if headerFilterMatch(t)]
        if not titles:
            controlflow.system_error_exit(
                3, 'No columns selected with GAM_CSV_HEADER_FILTER\n')
            return
    csv.register_dialect('nixstdout', lineterminator='\n')
    if todrive:
        write_to = io.StringIO()
    else:
        write_to = sys.stdout
    writer = csv.DictWriter(write_to,
                            fieldnames=titles,
                            dialect='nixstdout',
                            extrasaction='ignore',
                            quoting=csv.QUOTE_MINIMAL)
    try:
        writer.writerow(dict((item, item) for item in writer.fieldnames))
        writer.writerows(csvRows)
    except IOError as e:
        controlflow.system_error_exit(6, e)
    if todrive:
        admin_email = __main__._getValueFromOAuth('email')
        _, drive = __main__.buildDrive3GAPIObject(admin_email)
        if not drive:
            print(
                f'''\nGAM is not authorized to create Drive files. Please run:
gam user {admin_email} check serviceaccount
and follow recommend steps to authorize GAM for Drive access.''')
            sys.exit(5)
        result = gapi.call(drive.about(), 'get', fields='maxImportSizes')
        columns = len(titles)
        rows = len(csvRows)
        cell_count = rows * columns
        data_size = len(write_to.getvalue())
        max_sheet_bytes = int(
            result['maxImportSizes'][MIMETYPE_GA_SPREADSHEET])
        if cell_count > MAX_GOOGLE_SHEET_CELLS or data_size > max_sheet_bytes:
            print(
                f'{WARNING_PREFIX}{MESSAGE_RESULTS_TOO_LARGE_FOR_GOOGLE_SPREADSHEET}'
            )
            mimeType = 'text/csv'
        else:
            mimeType = MIMETYPE_GA_SPREADSHEET
        body = {
            'description': QuotedArgumentList(sys.argv),
            'name': f'{GC_Values[GC_DOMAIN]} - {list_type}',
            'mimeType': mimeType
        }
        result = gapi.call(drive.files(),
                           'create',
                           fields='webViewLink',
                           body=body,
                           media_body=googleapiclient.http.MediaInMemoryUpload(
                               write_to.getvalue().encode(),
                               mimetype='text/csv'))
        file_url = result['webViewLink']
        if GC_Values[GC_NO_BROWSER]:
            msg_txt = f'Drive file uploaded to:\n {file_url}'
            msg_subj = f'{GC_Values[GC_DOMAIN]} - {list_type}'
            __main__.send_email(msg_subj, msg_txt)
            print(msg_txt)
        else:
            webbrowser.open(file_url)
コード例 #19
0
ファイル: customer.py プロジェクト: rlucian/GAM
def doGetCustomerInfo():
    cd = gapi.directory.buildGAPIObject()
    customer_info = gapi.call(cd.customers(),
                              'get',
                              customerKey=GC_Values[GC_CUSTOMER_ID])
    print(f'Customer ID: {customer_info["id"]}')
    print(f'Primary Domain: {customer_info["customerDomain"]}')
    result = gapi.call(cd.domains(),
                       'get',
                       customer=customer_info['id'],
                       domainName=customer_info['customerDomain'],
                       fields='verified')
    print(f'Primary Domain Verified: {result["verified"]}')
    # If customer has changed primary domain customerCreationTime is date
    # of current primary being added, not customer create date.
    # We should also get all domains and use oldest date
    customer_creation = customer_info['customerCreationTime']
    date_format = '%Y-%m-%dT%H:%M:%S.%fZ'
    oldest = datetime.datetime.strptime(customer_creation, date_format)
    domains = gapi.get_items(cd.domains(),
                             'list',
                             'domains',
                             customer=GC_Values[GC_CUSTOMER_ID],
                             fields='domains(creationTime)')
    for domain in domains:
        creation_timestamp = int(domain['creationTime']) / 1000
        domain_creation = datetime.datetime.fromtimestamp(creation_timestamp)
        if domain_creation < oldest:
            oldest = domain_creation
    print(f'Customer Creation Time: {oldest.strftime(date_format)}')
    customer_language = customer_info.get('language', 'Unset (defaults to en)')
    print(f'Default Language: {customer_language}')
    if 'postalAddress' in customer_info:
        print('Address:')
        for field in ADDRESS_FIELDS_PRINT_ORDER:
            if field in customer_info['postalAddress']:
                print(f' {field}: {customer_info["postalAddress"][field]}')
    if 'phoneNumber' in customer_info:
        print(f'Phone: {customer_info["phoneNumber"]}')
    print(f'Admin Secondary Email: {customer_info["alternateEmail"]}')
    user_counts_map = {
        'accounts:num_users': 'Total Users',
        'accounts:gsuite_basic_total_licenses': 'G Suite Basic Licenses',
        'accounts:gsuite_basic_used_licenses': 'G Suite Basic Users',
        'accounts:gsuite_enterprise_total_licenses': 'G Suite Enterprise ' \
        'Licenses',
        'accounts:gsuite_enterprise_used_licenses': 'G Suite Enterprise ' \
        'Users',
        'accounts:gsuite_unlimited_total_licenses': 'G Suite Business ' \
        'Licenses',
        'accounts:gsuite_unlimited_used_licenses': 'G Suite Business Users'
    }
    parameters = ','.join(list(user_counts_map))
    tryDate = datetime.date.today().strftime(YYYYMMDD_FORMAT)
    customerId = GC_Values[GC_CUSTOMER_ID]
    if customerId == MY_CUSTOMER:
        customerId = None
    rep = gapi.reports.buildGAPIObject()
    usage = None
    throw_reasons = [gapi.errors.ErrorReason.INVALID]
    while True:
        try:
            usage = gapi.get_all_pages(rep.customerUsageReports(),
                                       'get',
                                       'usageReports',
                                       throw_reasons=throw_reasons,
                                       customerId=customerId,
                                       date=tryDate,
                                       parameters=parameters)
            break
        except gapi.errors.GapiInvalidError as e:
            tryDate = gapi.reports._adjust_date(str(e))
    if not usage:
        print('No user count data available.')
        return
    print(f'User counts as of {tryDate}:')
    for item in usage[0]['parameters']:
        api_name = user_counts_map.get(item['name'])
        api_value = int(item.get('intValue', 0))
        if api_name and api_value:
            print(f'  {api_name}: {api_value:,}')