Skip to content

Commit

Permalink
Add util inspect-auth command to dump auth token metadata (#780)
Browse files Browse the repository at this point in the history
Fixes #777.
  • Loading branch information
dbarnett authored Sep 26, 2024
1 parent 9ca0112 commit 92af8b4
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 15 deletions.
3 changes: 2 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ v4.5.0
* Drop support for python <3.10
* Add `init` command to explicitly request auth setup/refresh
* Add support for config.toml file and `gcalcli config edit` command
* Add support for `gcalcli util config-schema|reset-cache` commands
* Add support for `gcalcli util config-schema|reset-cache|inspect-auth`
commands
* Behavior change: `--noincluderc` now skips gcalclirc files unconditionally,
w/ or w/o --config-folder
- POSSIBLE ACTION REQUIRED: Use `@path/to/gcalclirc` explicitly if it stops
Expand Down
6 changes: 6 additions & 0 deletions gcalcli/argparsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,12 @@ def get_argument_parser():
description="Delete gcalcli's internal cache file as a workaround for "
"caching bugs like insanum/gcalcli#622",
)
util_sub.add_parser(
'inspect-auth',
help='show metadata about auth token',
description="Dump metadata about the saved auth token gcalcli is set "
"up to use for you",
)

# Enrich with argcomplete options.
argcomplete.autocomplete(parser)
Expand Down
15 changes: 15 additions & 0 deletions gcalcli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,21 @@ def main():
'No cache file found. Exiting without deleting '
'anything...\n'
)
elif parsed_args.subcommand == 'inspect-auth':
auth_data = utils.inspect_auth()
for k, v in auth_data.items():
printer.msg(f"{k}: {v}\n")
if 'format' in auth_data:
printer.msg(
"\n"
"The grant's entry under "
"https://myaccount.google.com/connections should also "
"list creation time and other info Google provides on "
"the access grant.\n"
'Hint: filter by "Access to: Calendar" if you have '
"trouble finding the right one.\n")
else:
printer.err_msg("No existing auth token found\n")

except GcalcliError as exc:
printer.err_msg(str(exc))
Expand Down
82 changes: 68 additions & 14 deletions gcalcli/utils.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import calendar
from collections import OrderedDict
import json
import locale
import os
import pathlib
import pickle
import re
import subprocess
import time
from datetime import datetime, timedelta
from typing import Tuple
from typing import Any, Tuple

import babel
from dateutil.parser import parse as dateutil_parse
from dateutil.tz import tzlocal
from parsedatetime.parsedatetime import Calendar

from . import auth, env

locale.setlocale(locale.LC_ALL, '')
fuzzy_date_parse = Calendar().parse
fuzzy_datetime_parse = Calendar().parseDT
Expand All @@ -21,11 +26,11 @@
REMINDER_REGEX = r'^(\d+)([wdhm]?)(?:\s+(popup|email|sms))?$'

DURATION_REGEX = re.compile(
r'^((?P<days>[\.\d]+?)(?:d|day|days))?[ :]*'
r'((?P<hours>[\.\d]+?)(?:h|hour|hours))?[ :]*'
r'((?P<minutes>[\.\d]+?)(?:m|min|mins|minute|minutes))?[ :]*'
r'((?P<seconds>[\.\d]+?)(?:s|sec|secs|second|seconds))?$'
)
r'^((?P<days>[\.\d]+?)(?:d|day|days))?[ :]*'
r'((?P<hours>[\.\d]+?)(?:h|hour|hours))?[ :]*'
r'((?P<minutes>[\.\d]+?)(?:m|min|mins|minute|minutes))?[ :]*'
r'((?P<seconds>[\.\d]+?)(?:s|sec|secs|second|seconds))?$'
)


def parse_reminder(rem):
Expand Down Expand Up @@ -54,8 +59,10 @@ def set_locale(new_locale):
locale.setlocale(locale.LC_ALL, new_locale)
except locale.Error as exc:
raise ValueError(
'Error: ' + str(exc) +
'!\n Check supported locales of your system.\n')
'Error: '
+ str(exc)
+ '!\n Check supported locales of your system.\n'
)


def get_times_from_duration(
Expand Down Expand Up @@ -111,7 +118,8 @@ def get_time_from_str(when):
on fuzzy matching with parsedatetime
"""
zero_oclock_today = datetime.now(tzlocal()).replace(
hour=0, minute=0, second=0, microsecond=0)
hour=0, minute=0, second=0, microsecond=0
)

try:
event_time = dateutil_parse(
Expand Down Expand Up @@ -144,9 +152,11 @@ def get_timedelta_from_str(delta):
parts = DURATION_REGEX.match(delta)
if parts is not None:
try:
time_params = {name: float(param)
for name, param
in parts.groupdict().items() if param}
time_params = {
name: float(param)
for name, param in parts.groupdict().items()
if param
}
parsed_delta = timedelta(**time_params)
except ValueError:
pass
Expand Down Expand Up @@ -175,8 +185,13 @@ def is_all_day(event):
# and end at midnight. This is ambiguous with Google Calendar events that
# are not all-day but happen to begin and end at midnight.

return (event['s'].hour == 0 and event['s'].minute == 0
and event['e'].hour == 0 and event['e'].minute == 0)
return (
event['s'].hour == 0
and event['s'].minute == 0
and event['e'].hour == 0
and event['e'].minute == 0
)


def localize_datetime(dt):
if not hasattr(dt, 'tzinfo'): # Why are we skipping these?
Expand Down Expand Up @@ -217,3 +232,42 @@ def shorten_path(path: pathlib.Path) -> pathlib.Path:
if path.parts[:expanduser_len] == tilde_home.expanduser().parts:
return tilde_home.joinpath(*path.parts[expanduser_len:])
return path


def inspect_auth() -> dict[str, Any]:
auth_data: dict[str, Any] = OrderedDict()
auth_path = None
for path in env.data_file_paths('oauth'):
if path.exists():
auth_path = path
auth_data['path'] = shorten_path(path)
break
if auth_path:
with auth_path.open('rb') as gcalcli_oauth:
try:
creds = pickle.load(gcalcli_oauth)
auth_data['format'] = 'pickle'
except (pickle.UnpicklingError, EOFError):
# Try reading as legacy json format as fallback.
try:
gcalcli_oauth.seek(0)
creds = auth.creds_from_legacy_json(
json.load(gcalcli_oauth)
)
auth_data['format'] = 'json'
except (OSError, ValueError, EOFError):
pass
if 'format' in auth_data:
for k in [
'client_id',
'scopes',
'valid',
'token_state',
'expiry',
'expired',
]:
if hasattr(creds, k):
auth_data[k] = getattr(creds, k)
else:
auth_data['format'] = 'unknown'
return auth_data

0 comments on commit 92af8b4

Please sign in to comment.