Esempio n. 1
0
def normalizeCalendarId(calname, checkPrimary=False):
    if checkPrimary and calname.lower() == 'primary':
        return calname
    if not GC_Values[GC_DOMAIN]:
        GC_Values[GC_DOMAIN] = gam._getValueFromOAuth('hd')
    return gam.convertUIDtoEmailAddress(calname,
                                        email_types=['user', 'resource'])
Esempio n. 2
0
def buildCalendarDataGAPIObject(calname):
    calendarId = normalizeCalendarId(calname)

    # Try to impersonate the calendar owner. If we fail, fall back to using
    # admin for authentication. Resource calendars cannot be impersonated,
    # so we need to access them as the admin.
    cal = None
    if not calname.endswith('.calendar.google.com'):
        cal = gam.buildGAPIServiceObject('calendar', calendarId, False)
    if cal is None:
        _, cal = buildCalendarGAPIObject(gam._getValueFromOAuth('email'))
    return (calendarId, cal)
Esempio n. 3
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(filters, title):
        for filterStr in filters:
            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] or GC_Values[GC_CSV_HEADER_DROP_FILTER]:
        if GC_Values[GC_CSV_HEADER_DROP_FILTER]:
            titles = [
                t for t in titles if
                not headerFilterMatch(GC_Values[GC_CSV_HEADER_DROP_FILTER], t)
            ]
        if GC_Values[GC_CSV_HEADER_FILTER]:
            titles = [
                t for t in titles
                if headerFilterMatch(GC_Values[GC_CSV_HEADER_FILTER], t)
            ]
        if not titles:
            controlflow.system_error_exit(
                3,
                'No columns selected with GAM_CSV_HEADER_FILTER and GAM_CSV_HEADER_DROP_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 = gam._getValueFromOAuth('email')
        _, drive = gam.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}'
            gam.send_email(msg_subj, msg_txt)
            print(msg_txt)
        else:
            webbrowser.open(file_url)
Esempio n. 4
0
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': gam._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)
    all_parameters = set()
    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')
    fullDataRequired = ['all']
    while True:
        try:
            result = gapi.call(endpoint,
                               'get',
                               throw_reasons=throw_reasons,
                               date=tryDate,
                               customerId=customerId,
                               fields='warnings,usageReports(parameters(name))',
                               **kwargs)
            warnings = result.get('warnings', [])
            usage = result.get('usageReports')
            has_reports = bool(usage)
            fullData, tryDate = _check_full_data_available(
                warnings, tryDate, fullDataRequired, has_reports)
            if fullData < 0:
                print('No usage parameters available.')
                sys.exit(1)
            if has_reports:
                for parameter in usage[0]['parameters']:
                    name = parameter.get('name')
                    if name:
                        all_parameters.add(name)
            if fullData == 1:
                break
        except gapi.errors.GapiInvalidError as e:
            tryDate = _adjust_date(str(e))
    csvRows = []
    for parameter in sorted(all_parameters):
        csvRows.append({'parameter': parameter})
    display.write_csv_file(csvRows, titles,
                           f'{report.capitalize()} Report Usage Parameters',
                           todrive)
Esempio n. 5
0
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': gam._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)