Proper support for alternate auth accounts
There should be a convenient way for users to switch between different authenticated accounts in gcalcli.
Currently this can be done by twiddling oauth files (see #805), but the mechanism is clunky and not very discoverable. The ideal would probably be to have a set of named auth accounts and to be able to configure --account=someaccount@domain in cli args and config files.
Or maybe instead of separate configs per account, the config.toml structure should change to support e.g.
[accounts."account1@domain".calendars]
ignore-calendars = ["cal1", "cal2"]
?
I hit one snag that the oauth tokens we receive don't seem to include an account name or email to identify separate accounts. It seemed like the openid and …userinfo.email scopes might help get that included (relevant OAuth docs), but I haven't quite figured out how yet, and requesting more than one scope seems to make the auth flow more complicated with checkboxes on the scopes you have to make sure to manually check.
Alternatively we could just let users manually name the accounts and store one unnamed one as "default", like:
$ gcalcli init
…
Successfully loaded credentials for account "default".
$ gcalcli init --account=work
…
Successfully loaded credentials for account "work".
K for reference, I was able to successfully fetch account ID / email using their recommended way from google_auth_oauthlib docs:
flow = InstalledAppFlow.from_client_config(
…
scopes=[
"openid",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/calendar",
],
)
session = flow.authorized_session()
profile_info = session.get(
'https://www.googleapis.com/userinfo/v2/me').json()
but I can't figure out how to get it to require multiple scopes like that w/o the annoying checkboxes and am leaning towards just letting users explicitly assign names to the accounts like gcalcli init --account=someaccount2.
I like the idea of using an --account flag to define the location of the oauth/config files. Previously, I ran two commands in my conky config to see calendars from two separate accounts. An --account flag should allow my use case to work again, provided the flag works with other commands like list, agenda, etc.
[accounts."account1@domain".calendars]
This seems unnecessarily complicated to me. Having a different toml files for each account is a lot easier to understand. If you want to avoid duplication in configuration, it maybe be better to have config.toml included by default, with any changes in other.toml overwriting it, but others copying the config.toml configuration.
Eh, could be I'm overcomplicating things. My priority in however it's specified is to remove any temptation for people to manually twiddle oauth files, so we're not locked into some implied contract of where these files need to live.
How would these "config.toml" and "other.toml" files be specified when you're invoking gcalcli though?
config.toml would be the default.
For other.toml, options could be:
--config=other.toml--config=other--config=account@domain(and the file would need to be called something like[email protected])
Might work okay. I suspect that'd also end up having a lot of complications in practice:
- It still needs to have some 1-to-1 mapping between the config and the account auth token for gcalcli to work properly
- What commands do you actually run to set up a new account?
- Would a secondary config "replace" or "extend" options like
ignore-calendars?
Granted these are all details that need to be figured out for pretty much any strategy, but could start getting really messy really fast using implicit mappings or magic names.
I agree with --config=other.toml being a good way to invoke another instance.
In an ideal world, if I ran gcalcli init --config=sports.toml a new config called sports.toml would be created with a reference to that specific account auth token. Then, in the event that any subcommand is issued with the --config flag, it would refer gcalcli to that instance (meaning the secondary config would "replace" rather than "extend" options like ignore-calendars. They would be completely separate instances.
Ultimately, I'd think that the .toml would need to have an explicit reference to the account auth token to ensure 1-to-1 mapping.
Upon reflection I think --config=other.toml is the best option as it makes it easiest for the uninitiated to understand what is going on, and enables config files outside the standard config directories if a full path is supplied.
gcalcli init --config=sports.toml
Good idea! Should be gcalcli --config=sports.toml init though 😉
K then a few things:
- From the cli command I wouldn't guess that's triggering an account switch, so maybe rename the arg to
--account-configor something? - +1 having an explicit reference to the account token in the generated config will be helpful
- Are we imagining this arg as a full path? There'll be a few more little complexities to figure out for that
- Will want clear setup instructions for this since parts of it don't exactly feel self-documenting
BTW the recommended way of pointing to an explicit config file / dir is $GCALCLI_CONFIG and that should be fine as-is. Could use an env var for this account config thing too, but I kinda prefer an explicit arg for the init case.
I also realized init could just prompt you for whether to overwrite the default account or set up an alternate. That would make it friendlier having it suggest new file paths you could edit instead of having to figure out everything upfront as cli args.
Any update on this?
Nope, I can review PRs but haven't had time to put towards building whole new features.
Could help build some momentum if you could share about your use cases and whether the ideas here sound like they'd actually solve it well for you.
I've got both work and personal calendars. I would like to be able to pull both of them up at once, easily. And, in theory, in the future (although I know it's not what this issue's about), display all my events from both accounts on a single calendar view like you see on the Google Calendar mobile app, for instance.
For those who come across this in the future, here is my current work-around setup (+some tmux stuff to make it convenient).
tmux-calendar.sh:
#!/bin/bash
if [[ "$#" > 0 ]]; then
tmux kill-window -t $1':=Calendar'
tmux new-window -t $1 -d -n 'Calendar' '~/PATH-TO-FILE/print-calendar.sh work'
tmux split-window -h -l 40% -t $1':=Calendar.0' 'sleep 0.5; ~/PATH-TO-FILE/print-calendar.sh personal'
else
tmux kill-window -t ':=Calendar'
tmux new-window -d -n 'Calendar' '~/PATH-TO-FILE/print-calendar.sh work'
tmux split-window -h -l 40% -t ':=Calendar.0' 'sleep 0.5; ~/PATH-TO-FILE/print-calendar.sh personal'
fi
print-calendar.sh:
#!/bin/bash
ln -sf ~/.local/share/gcalcli/cache-$1 ~/.local/share/gcalcli/cache
ln -sf ~/.local/share/gcalcli/oauth-$1 ~/.local/share/gcalcli/oauth
gcalcli calm
while read -rs; do sleep 1; done
.tmux.conf (addition):
bind C-u run-shell "~/PATH-TO-FILE/tmux-calendar.sh; tmux select-window -t :=Calendar"
my tmux session creator bash script (addition):
tmux run-shell "~/PATH-TO-FILE/tmux-calendar.sh =SESSION_NAME"