Skip to content

Commit

Permalink
Handle insufficient calendar permissions better.
Browse files Browse the repository at this point in the history
  • Loading branch information
phw198 committed Sep 1, 2024
1 parent 361e7b2 commit f06e354
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 26 deletions.
11 changes: 7 additions & 4 deletions src/OutlookGoogleCalendarSync/Forms/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1536,8 +1536,10 @@ private void GetMyGoogleCalendars_Click(object sender, EventArgs e) {

log.Debug("Retrieving Google calendar list.");
this.bGetGoogleCalendars.Text = "Cancel retrieval";
Boolean successfulRetrieval = false;
try {
Ogcs.Google.Calendar.Instance.GetCalendars();
successfulRetrieval = true;
} catch (AggregateException agex) {
agex.AnalyseAggregate(false);
} catch (global::Google.Apis.Auth.OAuth2.Responses.TokenResponseException ex) {
Expand All @@ -1549,12 +1551,12 @@ private void GetMyGoogleCalendars_Click(object sender, EventArgs e) {
"Please check the output on the Sync tab for more details.", "Google calendar retrieval failed",
MessageBoxButtons.OK, MessageBoxIcon.Error);
StringBuilder sb = new StringBuilder();
console.BuildOutput("Unable to get the list of Google calendars. The following error occurred:", ref sb, false);
if (ex is ApplicationException && ex.InnerException != null && ex.InnerException is global::Google.GoogleApiException) {
console.BuildOutput("Unable to get the list of Google calendars.", ref sb, false);
if (ex is ApplicationException) {
console.BuildOutput(ex.Message, ref sb, false);
console.Update(sb, Console.Markup.fail, logit: true);
} else {
console.BuildOutput(ex.FriendlyMessage(), ref sb, false);
console.BuildOutput(" The following error occurred: " + ex.FriendlyMessage(), ref sb, false);
console.Update(sb, Console.Markup.error, logit: true);
if (Settings.Instance.Proxy.Type == "IE") {
if (Ogcs.Extensions.MessageBox.Show("Please ensure you can access the internet with Internet Explorer.\r\n" +
Expand All @@ -1567,7 +1569,8 @@ private void GetMyGoogleCalendars_Click(object sender, EventArgs e) {
}
}

cbGoogleCalendars_BuildList();
if (successfulRetrieval)
cbGoogleCalendars_BuildList();

bGetGoogleCalendars.Enabled = true;
cbGoogleCalendars.Enabled = true;
Expand Down
40 changes: 34 additions & 6 deletions src/OutlookGoogleCalendarSync/Google/Authenticator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,22 @@ namespace OutlookGoogleCalendarSync.Google {
public class Authenticator {
private static readonly ILog log = LogManager.GetLogger(typeof(Authenticator));

private string[] requiredScopes = new[] {
CalendarService.ScopeConstants.Calendar,
"email" };

private Boolean authenticated = false;
public Boolean Authenticated { get { return authenticated; } }
private String GrantedScopes;
public Boolean SufficientPermissions {
get {
if (string.IsNullOrEmpty(GrantedScopes)) return false;
foreach (String s in requiredScopes) {
if (!GrantedScopes.Contains(s)) return false;
}
return true;
}
}

public const String TokenFile = "Google.Apis.Auth.OAuth2.Responses.TokenResponse-user";
private String tokenFullPath;
Expand Down Expand Up @@ -104,20 +118,30 @@ private async Task<bool> getAuthenticated(ClientSecrets cs) {
if (!tokenFileExists)
log.Info("No Google credentials file available - need user authorisation for OGCS to manage their calendar.");

string[] scopes = new[] { "https://www.googleapis.com/auth/calendar", "email" };

UserCredential credential = null;
try {
if (!SufficientPermissions) File.Delete(tokenFullPath);

//This will open the authorisation process in a browser, if required
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(cs, scopes, "user", CancelTokenSource.Token, tokenStore);
if (tokenFileExists)
log.Debug("User has provided Google authorisation and credential file saved.");
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(cs, requiredScopes, "user", CancelTokenSource.Token, tokenStore);
if (tokenFileExists) {
log.Debug("User has completed Google authorisation and credential file saved. Checking granular permissions...");

GrantedScopes = credential.Token.Scope;
if (!SufficientPermissions) {
log.Warn("They have not granted permission to the calendar.");

String noAuthGiven = "Sorry, but this application will not work if you don't allow it access to your Google Calendar :(";
Ogcs.Extensions.MessageBox.Show(noAuthGiven, "Authorisation not given", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
throw new ApplicationException(noAuthGiven);
}
}

} catch (global::Google.Apis.Auth.OAuth2.Responses.TokenResponseException ex) {
//Ogcs.Exception.AnalyseTokenResponse(ex);
if (ex.Error.Error == "access_denied") {
String noAuthGiven = "Sorry, but this application will not work if you don't allow it access to your Google Calendar :(";
log.Warn("User did not provide authorisation code. Sync will not be able to work.");
String noAuthGiven = "Sorry, but this application will not work if you don't allow it access to your Google Calendar :(";
Ogcs.Extensions.MessageBox.Show(noAuthGiven, "Authorisation not given", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
throw new ApplicationException(noAuthGiven);
} else {
Expand All @@ -127,6 +151,10 @@ private async Task<bool> getAuthenticated(ClientSecrets cs) {
} catch (OperationCanceledException) {
Forms.Main.Instance.Console.Update("Unable to authenticate with Google. The operation was cancelled.", Console.Markup.warning);

} catch (ApplicationException ex) {
Forms.Main.Instance.Console.UpdateWithError(null, ex.LogAsFail());
return false;

} catch (System.Exception ex) {
Ogcs.Exception.Analyse(ex);
Forms.Main.Instance.Console.UpdateWithError("Unable to authenticate with Google. The following error occurred:", ex);
Expand Down
29 changes: 13 additions & 16 deletions src/OutlookGoogleCalendarSync/Google/GoogleCalendar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,7 @@ public static Calendar Instance {
instance = new Ogcs.Google.Calendar {
Authenticator = new Ogcs.Google.Authenticator()
};
instance.Authenticator.GetAuthenticated();
if (instance.Authenticator.Authenticated) {
instance.Authenticator.OgcsUserStatus();
_ = instance.ColourPalette;
} else {
instance = null;
if (Forms.Main.Instance.Console.DocumentText.Contains("Authorisation to allow OGCS to manage your Google calendar was cancelled."))
throw new OperationCanceledException();
else
throw new ApplicationException("Google handshake failed.");
}
_ = instance.Service;
}
return instance;
}
Expand Down Expand Up @@ -67,13 +57,20 @@ public CalendarService Service {
get {
if (service == null) {
log.Debug("Google service not yet instantiated.");
Authenticator = new Ogcs.Google.Authenticator();
Authenticator.GetAuthenticated();
if (Authenticator.Authenticated)
if (Authenticator?.Authenticated ?? false) {
Authenticator.OgcsUserStatus();
else {
service = null;
throw new ApplicationException("Google handshake failed.");
_ = ColourPalette;
} else {
if (Forms.Main.Instance.Console.DocumentText.Contains("Authorisation to allow OGCS to manage your Google calendar was cancelled."))
throw new OperationCanceledException();
else if (Authenticator != null && !Authenticator.SufficientPermissions) {
throw new ApplicationException("OGCS has not been granted permission to manage your calendars. " +
"When authorising access to your Google account, please ensure permission is granted to <b>all the items</b> requested.");
} else {
instance = null;
throw new ApplicationException("Google handshake failed.");
}
}
}
return service;
Expand Down

0 comments on commit f06e354

Please sign in to comment.