Google Calendar integration improvements (#4147)
# What this PR does
- UI enhancements
- Fix bug when going through the Google OAuth2 disconnection flow. We
should send the `refresh_token` in the `revoke` HTTP request, rather
than the `access_token` (`access_token` expires frequently and can
result in Google sending back HTTP 400.. `refresh_token` is long lived
and can also be sent in the revoke flow)
## Checklist
- [ ] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
---------
Co-authored-by: Maxim Mordasov <maxim.mordasov@grafana.com>
This commit is contained in:
parent
4c79d69c17
commit
c6f5c9b14d
2 changed files with 30 additions and 22 deletions
|
|
@ -22,6 +22,16 @@ def persist_access_and_refresh_tokens(backend: typing.Type[BaseAuth], response:
|
|||
|
||||
|
||||
def disconnect_user_google_oauth2_settings(backend: typing.Type[BaseAuth], user: User, *args, **kwargs):
|
||||
"""
|
||||
Don't use `google_oauth2_user.access_token` when revoking token, use `refresh_token` instead. If we use
|
||||
the access token, we may get an HTTP 400 from Google because the token may be invalid or revoked.
|
||||
|
||||
https://stackoverflow.com/a/18578660/3902555
|
||||
"""
|
||||
logger.info(f"Disconnecting user {user.pk} from Google OAuth2")
|
||||
|
||||
# 2nd argument, uid, is not needed for GoogleOauth2 backend
|
||||
backend.revoke_token(user.google_oauth2_user.access_token, "")
|
||||
backend.revoke_token(user.google_oauth2_user.refresh_token, "")
|
||||
user.finish_google_oauth2_disconnection_flow()
|
||||
|
||||
logger.info(f"Successfully disconnected user {user.pk} from Google OAuth2")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { css } from '@emotion/css';
|
||||
import { Button, HorizontalGroup, InlineSwitch, VerticalGroup, useStyles2 } from '@grafana/ui';
|
||||
import { Button, HorizontalGroup, Switch, VerticalGroup, useStyles2 } from '@grafana/ui';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import { Block } from 'components/GBlock/Block';
|
||||
|
|
@ -21,11 +21,16 @@ const GoogleCalendar: React.FC<{ id: ApiSchemas['User']['pk'] }> = observer(({ i
|
|||
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const user = userStore.items[id];
|
||||
const [googleCalendarSettings, setGoogleCalendarSettings] = useState(user?.google_calendar_settings);
|
||||
const [showSchedulesDropdown, setShowSchedulesDropdown] = useState(
|
||||
user.google_calendar_settings?.oncall_schedules_to_consider_for_shift_swaps?.length > 0
|
||||
);
|
||||
const [googleCalendarSettings, setGoogleCalendarSettings] =
|
||||
useState<ApiSchemas['User']['google_calendar_settings']>();
|
||||
const [showSchedulesDropdown, setShowSchedulesDropdown] = useState<boolean>();
|
||||
|
||||
useEffect(() => {
|
||||
userStore.fetchItemById({ userPk: id }).then((user) => {
|
||||
setGoogleCalendarSettings(user.google_calendar_settings);
|
||||
setShowSchedulesDropdown(user.google_calendar_settings.oncall_schedules_to_consider_for_shift_swaps?.length > 0);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleShowSchedulesDropdownChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = event.target.checked;
|
||||
|
|
@ -36,12 +41,6 @@ const GoogleCalendar: React.FC<{ id: ApiSchemas['User']['pk'] }> = observer(({ i
|
|||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
setGoogleCalendarSettings(user.google_calendar_settings);
|
||||
}
|
||||
}, [user]);
|
||||
|
||||
const handleSchedulesChange = (value) => {
|
||||
setGoogleCalendarSettings((v) => ({ ...v, oncall_schedules_to_consider_for_shift_swaps: value }));
|
||||
|
||||
|
|
@ -50,10 +49,12 @@ const GoogleCalendar: React.FC<{ id: ApiSchemas['User']['pk'] }> = observer(({ i
|
|||
});
|
||||
};
|
||||
|
||||
const user = userStore.items[id];
|
||||
|
||||
return (
|
||||
<VerticalGroup>
|
||||
<Block bordered className={styles.root}>
|
||||
<VerticalGroup>
|
||||
<VerticalGroup spacing="lg">
|
||||
{user.has_google_oauth2_connected ? (
|
||||
<VerticalGroup>
|
||||
<HorizontalGroup justify="space-between">
|
||||
|
|
@ -71,7 +72,7 @@ const GoogleCalendar: React.FC<{ id: ApiSchemas['User']['pk'] }> = observer(({ i
|
|||
</HorizontalGroup>
|
||||
</VerticalGroup>
|
||||
) : (
|
||||
<HorizontalGroup justify="space-between">
|
||||
<HorizontalGroup justify="space-between" spacing="lg">
|
||||
<HorizontalGroup spacing="md">
|
||||
<GoogleCalendarLogo width={32} height={32} />
|
||||
<div>
|
||||
|
|
@ -93,13 +94,10 @@ const GoogleCalendar: React.FC<{ id: ApiSchemas['User']['pk'] }> = observer(({ i
|
|||
{user.has_google_oauth2_connected && (
|
||||
<VerticalGroup>
|
||||
<WithPermissionControlTooltip userAction={UserActions.UserSettingsWrite}>
|
||||
<InlineSwitch
|
||||
showLabel
|
||||
label="Specify the schedules to sync with Google calendar"
|
||||
value={showSchedulesDropdown}
|
||||
transparent
|
||||
onChange={handleShowSchedulesDropdownChange}
|
||||
/>
|
||||
<HorizontalGroup align="center">
|
||||
<Switch value={showSchedulesDropdown} onChange={handleShowSchedulesDropdownChange} />
|
||||
<Text type="secondary">Specify the schedules to sync with Google calendar</Text>
|
||||
</HorizontalGroup>
|
||||
</WithPermissionControlTooltip>
|
||||
{showSchedulesDropdown && (
|
||||
<div style={{ width: '100%' }}>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue