public ModelAndView upgradeToken(HttpServletRequest request) throws IOException, UnexpectedHttpResponseCodeException {
String scope = (String) request.getSession().getAttribute("oauth2Scope");
Connector scopedApi = systemService.getApiFromGoogleScope(scope);
Guest guest = AuthHelper.getGuest();
String errorParameter = request.getParameter("error");
if (errorParameter!=null) {
notificationsService.addNamedNotification(guest.getId(), Notification.Type.WARNING,
scopedApi.statusNotificationName(),
"There was a problem importing your " + scopedApi.prettyName() + " data: " + errorParameter);
return new ModelAndView("redirect:/app/");
}
String swapTokenUrl = "https://accounts.google.com/o/oauth2/token";
String code = request.getParameter("code");
String redirectUri = ControllerSupport.getLocationBase(request, env) + "google/oauth2/swapToken";
Map<String,String> params = new HashMap<String,String>();
params.put("code", code);
params.put("client_id", env.get("google.client.id"));
params.put("client_secret", env.get("google.client.secret"));
params.put("redirect_uri", redirectUri);
params.put("grant_type", "authorization_code");
// Get the google branding info. Default to fluxtream if not set, but can override in
// oauth.properties by setting the default google.client.brandName parameter
String brandName = env.get("google.client.brandName");
if(brandName == null) {
// Not set in oauth.properties file, default to "Fluxtream"
brandName="Fluxtream";
}
// Try to renew the token. On failure leave token=null
JSONObject token = null;
try {
String fetched = HttpUtils.fetch(swapTokenUrl, params);
token = JSONObject.fromObject(fetched);
} catch(Throwable e) {
token = null;
}
ApiKey apiKey;
final boolean isRenewToken = request.getSession().getAttribute(APIKEYID_ATTRIBUTE) != null;
if (isRenewToken) {
String apiKeyId = (String)request.getSession().getAttribute(APIKEYID_ATTRIBUTE);
apiKey = guestService.getApiKey(Long.valueOf(apiKeyId));
if (apiKey==null) {
Exception e = new Exception();
String stackTrace = ExceptionUtils.getStackTrace(e);
String errorMessage = "no apiKey with id '%s'... It looks like you are trying to renew the tokens of a non-existing Connector (/ApiKey)";
return errorController.handleError(500, errorMessage, stackTrace);
}
if (token == null || !token.has("refresh_token")) {
String message = (new StringBuilder("<p>We couldn't get your oauth2 refresh token. "))
.append("Something went wrong.</p>")
.append("<p>You'll have to surf to your ")
.append("<a target='_new' href='https://accounts.google.com/b/0/IssuedAuthSubTokens'>token mgmt page at Google</a> ")
.append("and hit \"Revoke Access\" next to \"").append(brandName).append(" — ").append(getGooglePrettyName(scopedApi)).append("\"</p>")
.append("<p>Then please, head to <a href=\"javascript:App.manageConnectors()\">Manage Connectors</a> ")
.append("and renew your tokens (look for the <i class=\"icon-resize-small icon-large\"></i> icon)</p>")
.append("<p>We apologize for the inconvenience</p>").toString();
notificationsService.addNamedNotification(guest.getId(),
Notification.Type.ERROR,
apiKey.getConnector().statusNotificationName(),
message);
// Record permanent failure since this connector won't work again until
// it is reauthenticated
guestService.setApiKeyStatus(apiKey.getId(), ApiKey.Status.STATUS_PERMANENT_FAILURE, null, ApiKey.PermanentFailReason.NEEDS_REAUTH);
return new ModelAndView("redirect:/app");
}
// Remove oauth1 keys if upgrading from previous connector version.
// Remember whether or not we're upgrading from previous connector version.
// If so, do a full history update. Otherwise don't force a full
// history update and allow the update to be whatever it normally would be
boolean upgradeFromOauth1 = false;
if (guestService.getApiKeyAttribute(apiKey, "googleConsumerKey")!=null) {
guestService.removeApiKeyAttribute(apiKey.getId(), "googleConsumerKey");
upgradeFromOauth1 = true;
}
if (guestService.getApiKeyAttribute(apiKey, "googleConsumerSecret")!=null) {
guestService.removeApiKeyAttribute(apiKey.getId(), "googleConsumerSecret");
upgradeFromOauth1 = true;
}
// If upgradeFromOauth1 reset the connector to force a full reimport on google calendar,
// otherwise just do a normal update
if (apiKey.getConnector().getName().equals("google_calendar")) {
connectorUpdateService.flushUpdateWorkerTasks(apiKey, upgradeFromOauth1);
}
} else {
apiKey = guestService.createApiKey(guest.getId(), scopedApi);
}
// We need to store google.client.id and google.client.secret with the
// apiKeyAttributes in either the case of original creation of the key
// or token renewal. createApiKey actually handles the former case, but