-
-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/google calendar read only support #52790
Feature/google calendar read only support #52790
Conversation
By default the current read/write access will be given, but the user has the option to set read only access which stops the add event service from registering
This comment has been minimized.
This comment has been minimized.
# Conflicts: # homeassistant/components/google/__init__.py
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a nice change. Can you also include a pointer to a documentation update that goes along with this? (with a back reference to this PR)
I saw the issue referenced also discusses how the docs are out of date, and so fixing that would be nice. Also this includes a new configuration option that needs documentation too.
For context, I think the best practice is: Send the documentation for the next
branch and code PRs at the same time referencing each other, we'll make sure it all makes sense together, then we'll get in the code, then get in the docs.
def get_scope(conf): | ||
"""Gets the google calendar scope based on the defined access level.""" | ||
|
||
scopes = "" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was looking at some other examples of using enums for config in home assistant and came across what zha
does with the RadioType
enum:
class RadioType(enum.Enum): |
Some of this logic can go away if the access is defined as an enum with the scope baked in, something like:
class FeatureAccess(Enum):
read_only = ("https://www.googleapis.com/auth/calendar.readonly")
readwrite = ("https://www.googleapis.com/auth/calendar")
def __init__(self, scope: str) -> None:
"""..."""
self._scope = scope
@property
def scope(self) -> str:
"""..."""
return self._scope
Then I think you can just get the enum value from the config and pull the scope out of it all inline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't realise this was a thing. Updated.
"""Check for the correct scopes in file.""" | ||
with open(token_file) as tokenfile: | ||
if "readonly" in tokenfile.read(): | ||
contents = tokenfile.read() | ||
if (config.get(CONF_CALENDAR_ACCESS) is FeatureAccess.ReadWrite and "readonly" in contents) or (config.get(CONF_CALENDAR_ACCESS) is FeatureAccess.Read and "readonly" not in contents): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest making the above change then doing a check for the entire scope url to simplify this logic, and perhaps make it less error prone. That is, I think what this is trying to do is assert that the tokenfile contains the desired scope, so explicitly checking if the desired scope is in the file may be more straight forward.
(I realize this PR extends the existing pattern, so i'm more suggesting the existing pattern is a little brittle)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to hopefully be more robust
This was done as a MR suggestion to simplify the code.
I've added the proposed doc changes at home-assistant/home-assistant.io#18605. I've also made the changes as suggested. |
One additional thing to note - If a user wanted to downgrade their access level, they will probably hit #51490 as I too hit this issue when adding this feature. I'm trying to work out why this is happening in the specified area of code, but struggling tbh. |
"""Check for the correct scopes in file.""" | ||
with open(token_file) as tokenfile: | ||
if "readonly" in tokenfile.read(): | ||
contents = tokenfile.read() | ||
target_scope = f"\"scope\": \"{config.get(CONF_CALENDAR_ACCESS).scope}\"" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know I asked for this to be more robust -- but maybe just check the scope to avoid over asserting on the json format. I am only saying this because I saw #53364 a few days ago where folks were compressing json and then it had a subtle side effect of breaking a regexp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reduced down to quoted scope. This is needed because read_write
scope is a subset of read_only
scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I completely missed that, oof, so I get it why the original check was just for the suffix then. Are you still happy with this approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new approach is fine. I think you were right to bring up the potential risk of whitespace messing with the check, and this new check is a bit more robust than the old way.
CONFIG_SCHEMA = vol.Schema( | ||
{ | ||
DOMAIN: vol.Schema( | ||
{ | ||
vol.Required(CONF_CLIENT_ID): cv.string, | ||
vol.Required(CONF_CLIENT_SECRET): cv.string, | ||
vol.Optional(CONF_TRACK_NEW): cv.boolean, | ||
vol.Optional(CONF_CALENDAR_ACCESS, default="read_write"): cv.enum( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR violates ADR-0010 @allenporter
How should we proceed? I would vote revert this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was not aware of this. I assume this was done to force old integrations to the new UI flow? If this was to be converted, what would the ACs be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this was done to force old integrations to the new UI flow
That is not the sole reason.
If this was to be converted, what would the ACs be?
The "ACs"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, the acceptance criteria of the conversion? For example, "The client id/secret and access level should be set via the UI flow"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would need an OAuth flow (config flow). Client ID & secrets are part of the YAML configuration, not the UI.
Just looked at the integration, seeing the settings for the specific calendars, I can see this will become problematic. Let's keep this PR in for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for looking closer. Are we good on documentation? Forgot to update the PR links so sorry about that.
My assumption is this is like #44529 which I aborted, and I haven't put time into exploring a separate oauth UI. An alternative is we do a hybrid of yaml plus config flow for everything but oauth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also interestingly this is configuring the oauth scope so it's even more borderline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OAuth scopes (variable / conditional) can be handled in an OAuth flow, that is not a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the reviews guys and sorry that what I thought was a simple PR ended up being a controversial update. I'll try and remember the ADR in the future.
What you guys are doing with Home Assistant is appreciated :)
Breaking change
N/A
Proposed change
This update provides the ability to configure google calendar support with either
readwrite
access (current behaviour) orread
access. This was the result of #45229, and I needed as I wanted to add my work account but felt uncomfortable giving write access (which could be quite destructive if compromised).Type of change
Additional information
This "fixes" #45229 while still providing the existing functionality by default.
You can chane
Checklist
black --fast homeassistant tests
)If user exposed functionality or configuration variables are added/changed:
Happy to do this once the PR has been approved.
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest
.requirements_all.txt
.Updated by running
python3 -m script.gen_requirements_all
..coveragerc
.The integration reached or maintains the following Integration Quality Scale:
To help with the load of incoming pull requests: