private void initChannelMapping(ApiKey apiKey, final List<CalendarConfig> calendarConfigs) { bodyTrackHelper.deleteChannelMappings(apiKey); ChannelMapping mapping = new ChannelMapping(); mapping.deviceName = "google_calendar"; mapping.channelName = "events"; mapping.timeType = ChannelMapping.TimeType.gmt; mapping.channelType = ChannelMapping.ChannelType.timespan; mapping.guestId = apiKey.getGuestId(); mapping.apiKeyId = apiKey.getId(); bodyTrackHelper.persistChannelMapping(mapping); BodyTrackHelper.ChannelStyle channelStyle = new BodyTrackHelper.ChannelStyle(); channelStyle.timespanStyles = new BodyTrackHelper.MainTimespanStyle(); channelStyle.timespanStyles.defaultStyle = new BodyTrackHelper.TimespanStyle(); channelStyle.timespanStyles.defaultStyle.fillColor = "#92da46"; channelStyle.timespanStyles.defaultStyle.borderColor = "#92da46"; channelStyle.timespanStyles.defaultStyle.borderWidth = 2; channelStyle.timespanStyles.defaultStyle.top = 1.0; channelStyle.timespanStyles.defaultStyle.bottom = 1.0; channelStyle.timespanStyles.values = new HashMap(); GoogleCalendarConnectorSettings connectorSettings = (GoogleCalendarConnectorSettings) settingsService.getConnectorSettings(apiKey.getId()); int n = calendarConfigs.size(); if (connectorSettings != null) { n = 0; for (CalendarConfig calendar : connectorSettings.calendars) { if (!calendar.hidden) n++; } } double rowHeight = 1.f / (n * 2 + 1); int i = 0; for (CalendarConfig config : calendarConfigs) { if (connectorSettings != null && config.hidden) continue; BodyTrackHelper.TimespanStyle stylePart = new BodyTrackHelper.TimespanStyle(); final int rowsFromTop = (i + 1) * 2 - 1; stylePart.top = (double) rowsFromTop * rowHeight - (rowHeight * 0.25); stylePart.bottom = stylePart.top + rowHeight + (rowHeight * 0.25); stylePart.fillColor = config.backgroundColor; stylePart.borderColor = config.backgroundColor; channelStyle.timespanStyles.values.put(config.id, stylePart); i++; } bodyTrackHelper.setDefaultStyle(apiKey.getGuestId(), "google_calendar", "events", channelStyle); }
@GET @Path("/settings/{apiKeyId}") @Produces({MediaType.APPLICATION_JSON}) public String getConnectorSettings(@PathParam("apiKeyId") long apiKeyId) throws UpdateFailedException, IOException { final ApiKey apiKey = guestService.getApiKey(apiKeyId); final long guestId = AuthHelper.getGuestId(); if (apiKey.getGuestId() != guestId) throw new RuntimeException("attempt to retrieve ApiKey from another guest!"); final Object settings = settingsService.getConnectorSettings(apiKey.getId()); String json = mapper.writeValueAsString(settings); return json; }
@POST @Path("/settings/{apiKeyId}") @Produces({MediaType.APPLICATION_JSON}) public StatusModel saveConnectorSettings( @PathParam("apiKeyId") long apiKeyId, @FormParam("json") String json) { final ApiKey apiKey = guestService.getApiKey(apiKeyId); final long guestId = AuthHelper.getGuestId(); try { if (apiKey.getGuestId() != guestId) throw new RuntimeException("attempt to retrieve ApiKey from another guest!"); settingsService.saveConnectorSettings(apiKey.getId(), json); } catch (Throwable e) { return new StatusModel(false, e.getMessage()); } return new StatusModel(true, "saved connector settings"); }
private Calendar getCalendar(final ApiKey apiKey) throws UpdateFailedException { HttpTransport httpTransport = new NetHttpTransport(); JacksonFactory jsonFactory = new JacksonFactory(); // Get all the attributes for this connector's oauth token from the stored attributes final String accessToken = guestService.getApiKeyAttribute(apiKey, "accessToken"); final String refreshToken = guestService.getApiKeyAttribute(apiKey, "refreshToken"); final String clientId = guestService.getApiKeyAttribute(apiKey, "google.client.id"); final String clientSecret = guestService.getApiKeyAttribute(apiKey, "google.client.secret"); final GoogleCredential.Builder builder = new GoogleCredential.Builder(); builder.setTransport(httpTransport); builder.setJsonFactory(jsonFactory); builder.setClientSecrets(clientId, clientSecret); GoogleCredential credential = builder.build(); final Long tokenExpires = Long.valueOf(guestService.getApiKeyAttribute(apiKey, "tokenExpires")); credential.setExpirationTimeMilliseconds(tokenExpires); credential.setAccessToken(accessToken); credential.setRefreshToken(refreshToken); try { if (tokenExpires < System.currentTimeMillis()) { boolean tokenRefreshed = false; // Don't worry about checking if we are running on a mirrored test instance. // Refreshing tokens independently on both the main server and a mirrored instance // seems to work just fine. // Try to swap the expired access token for a fresh one. tokenRefreshed = credential.refreshToken(); if (tokenRefreshed) { Long newExpireTime = credential.getExpirationTimeMilliseconds(); logger.info( "google calendar token has been refreshed, new expire time = " + newExpireTime); // Update stored expire time guestService.setApiKeyAttribute(apiKey, "accessToken", credential.getAccessToken()); guestService.setApiKeyAttribute(apiKey, "tokenExpires", newExpireTime.toString()); } } } catch (TokenResponseException e) { logger.warn( "module=GoogleCalendarUpdater component=background_updates action=refreshToken" + " connector=" + apiKey.getConnector().getName() + " guestId=" + apiKey.getGuestId() + " status=permanently failed"); // Notify the user that the tokens need to be manually renewed notificationsService.addNamedNotification( apiKey.getGuestId(), Notification.Type.WARNING, connector().statusNotificationName(), "Heads Up. We failed in our attempt to automatically refresh your Google Calendar authentication tokens.<br>" + "Please head to <a href=\"javascript:App.manageConnectors()\">Manage Connectors</a>,<br>" + "scroll to the Google Calendar connector, and renew your tokens (look for the <i class=\"icon-resize-small icon-large\"></i> icon)"); // Record permanent update failure since this connector is never // going to succeed guestService.setApiKeyStatus( apiKey.getId(), ApiKey.Status.STATUS_PERMANENT_FAILURE, Utils.stackTrace(e)); throw new UpdateFailedException( "refresh token attempt permanently failed due to a bad token refresh response", e, true); } catch (IOException e) { logger.warn( "module=GoogleCalendarUpdater component=background_updates action=refreshToken" + " connector=" + apiKey.getConnector().getName() + " guestId=" + apiKey.getGuestId() + " status=temporarily failed"); // Notify the user that the tokens need to be manually renewed throw new UpdateFailedException("refresh token attempt failed", e, true); } final Calendar.Builder calendarBuilder = new Calendar.Builder(httpTransport, jsonFactory, credential); final Calendar calendar = calendarBuilder.build(); return calendar; }