Skip to content

Commit

Permalink
saving access/refresh tokens in db
Browse files Browse the repository at this point in the history
  • Loading branch information
VSydor committed Jul 31, 2023
1 parent b8dcc29 commit e513d97
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.impactupgrade.nucleus.client;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.impactupgrade.nucleus.dao.HibernateDao;
import com.impactupgrade.nucleus.entity.Organization;
import com.impactupgrade.nucleus.environment.Environment;
import com.impactupgrade.nucleus.environment.EnvironmentConfig;
import com.impactupgrade.nucleus.model.CrmContact;
import com.impactupgrade.nucleus.util.HttpClient;
import com.impactupgrade.nucleus.util.OAuth2;
import org.json.JSONObject;

import javax.ws.rs.core.GenericType;
import java.util.ArrayList;
Expand All @@ -22,13 +25,31 @@ public class MinistryByTextClient {
protected static String API_ENDPOINT_BASE = "https://api-qa.ministrybytext.com/";

protected final Environment env;
protected HibernateDao<Long, Organization> organizationDao;

private final OAuth2.Context oAuth2Context;

public MinistryByTextClient(Environment env) {
this.env = env;
this.organizationDao = new HibernateDao<>(Organization.class);

Organization org = getOrganization();
JSONObject envJson = org.getEnvironmentJson();
JSONObject mbtJson = envJson.getJSONObject("mbt");

this.oAuth2Context = new OAuth2.ClientCredentialsContext(
env.getConfig().mbt.clientId, env.getConfig().mbt.clientSecret, null, null, AUTH_ENDPOINT);
env.getConfig().mbt.clientId, env.getConfig().mbt.clientSecret,
mbtJson.getString("accessToken"), mbtJson.getLong("expiresAt"), mbtJson.getString("refreshToken"), AUTH_ENDPOINT);
}

// TODO: move the code to util/common parent class?
protected Organization getOrganization() {
return organizationDao.getQueryResult(
"from Organization o where o.nucleusApiKey=:apiKey",
query -> {
query.setParameter("apiKey", env.getConfig().apiKey);
}
).get();
}

public List<Group> getGroups(String campusId) {
Expand Down Expand Up @@ -94,8 +115,22 @@ public static class SubscriberRelation {
public String relationship;
}

// TODO: move the code to util/common parent class?
protected HttpClient.HeaderBuilder headers() {
return HttpClient.HeaderBuilder.builder().authBearerToken(oAuth2Context.refresh().accessToken());
String currentAccessToken = oAuth2Context.accessToken();
if (currentAccessToken != oAuth2Context.refresh().accessToken()) {
Organization org = getOrganization();
JSONObject envJson = org.getEnvironmentJson();
JSONObject mbtJson = envJson.getJSONObject("mbt");

mbtJson.put("accessToken", oAuth2Context.accessToken());
mbtJson.put("expiresAt", oAuth2Context.expiresAt() != null ? oAuth2Context.expiresAt() : null);
mbtJson.put("refreshToken", oAuth2Context.refreshToken());
org.setEnvironmentJson(envJson);
organizationDao.update(org);
}

return HttpClient.HeaderBuilder.builder().authBearerToken(oAuth2Context.accessToken());
}

//TODO: remove once done with testing
Expand Down
37 changes: 35 additions & 2 deletions src/main/java/com/impactupgrade/nucleus/client/RaiselyClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.impactupgrade.nucleus.dao.HibernateDao;
import com.impactupgrade.nucleus.entity.Organization;
import com.impactupgrade.nucleus.environment.Environment;
import com.impactupgrade.nucleus.environment.EnvironmentConfig;
import com.impactupgrade.nucleus.util.HttpClient;
import com.impactupgrade.nucleus.util.OAuth2;
import org.json.JSONObject;

import java.util.List;
import java.util.Map;
Expand All @@ -18,13 +21,30 @@ public class RaiselyClient {
private static final String AUTH_URL = RAISELY_API_URL + "/login";

protected final Environment env;
protected HibernateDao<Long, Organization> organizationDao;

private final OAuth2.Context oAuth2Context;

public RaiselyClient(Environment env) {
this.env = env;
this.organizationDao = new HibernateDao<>(Organization.class);

Organization org = getOrganization();
JSONObject envJson = org.getEnvironmentJson();
JSONObject raiselyJson = envJson.getJSONObject("raisely");

this.oAuth2Context = new OAuth2.UsernamePasswordContext(
env.getConfig().raisely.username, env.getConfig().raisely.password, Map.of("requestAdminToken", "true"), null, null, AUTH_URL);
env.getConfig().raisely.username, env.getConfig().raisely.password, Map.of("requestAdminToken", "true"),
raiselyJson.getString("accessToken"), raiselyJson.getLong("expiresAt"), raiselyJson.getString("refreshToken"), AUTH_URL);
}

protected Organization getOrganization() {
return organizationDao.getQueryResult(
"from Organization o where o.nucleusApiKey=:apiKey",
query -> {
query.setParameter("apiKey", env.getConfig().apiKey);
}
).get();
}

//*Note this uses the donation ID from the Stripe metadata. Different from the donation UUID
Expand Down Expand Up @@ -53,7 +73,20 @@ public RaiselyClient.Donation getDonation(String donationId) {
}

protected HttpClient.HeaderBuilder headers() {
return HttpClient.HeaderBuilder.builder().authBearerToken(oAuth2Context.refresh().accessToken());
String currentAccessToken = oAuth2Context.accessToken();
if (currentAccessToken != oAuth2Context.refresh().accessToken()) {
Organization org = getOrganization();
JSONObject envJson = org.getEnvironmentJson();
JSONObject raisely = envJson.getJSONObject("raisely");

raisely.put("accessToken", oAuth2Context.accessToken());
raisely.put("expiresAt", oAuth2Context.expiresAt() != null ? oAuth2Context.expiresAt() : null);
raisely.put("refreshToken", oAuth2Context.refreshToken());
org.setEnvironmentJson(envJson);
organizationDao.update(org);
}

return HttpClient.HeaderBuilder.builder().authBearerToken(oAuth2Context.accessToken());
}

//Response Objects
Expand Down
37 changes: 35 additions & 2 deletions src/main/java/com/impactupgrade/nucleus/client/SpokeClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.google.common.base.Strings;
import com.impactupgrade.nucleus.dao.HibernateDao;
import com.impactupgrade.nucleus.entity.Organization;
import com.impactupgrade.nucleus.environment.Environment;
import com.impactupgrade.nucleus.environment.EnvironmentConfig;
import com.impactupgrade.nucleus.model.CrmContact;
import com.impactupgrade.nucleus.util.HttpClient;
import com.impactupgrade.nucleus.util.OAuth2;
import org.json.JSONObject;

import javax.ws.rs.core.GenericType;
import java.util.ArrayList;
Expand All @@ -23,13 +26,30 @@ public class SpokeClient {
protected static String API_ENDPOINT_BASE = "https://integration.spokephone.com/";

protected final Environment env;
protected HibernateDao<Long, Organization> organizationDao;

private final OAuth2.Context oAuth2Context;

public SpokeClient(Environment env) {
this.env = env;
this.organizationDao = new HibernateDao<>(Organization.class);

Organization org = getOrganization();
JSONObject envJson = org.getEnvironmentJson();
JSONObject spokeJson = envJson.getJSONObject("spoke");

this.oAuth2Context = new OAuth2.ClientCredentialsContext(
env.getConfig().spoke.clientId, env.getConfig().spoke.clientSecret, null, null, AUTH_ENDPOINT);
env.getConfig().spoke.clientId, env.getConfig().spoke.clientSecret,
spokeJson.getString("accessToken"), spokeJson.getLong("expiresAt"), spokeJson.getString("refreshToken"), AUTH_ENDPOINT);
}

protected Organization getOrganization() {
return organizationDao.getQueryResult(
"from Organization o where o.nucleusApiKey=:apiKey",
query -> {
query.setParameter("apiKey", env.getConfig().apiKey);
}
).get();
}

public List<Phonebook> getPhonebooks() {
Expand Down Expand Up @@ -110,7 +130,20 @@ public static class ContactRequest {
}

protected HttpClient.HeaderBuilder headers() {
return HttpClient.HeaderBuilder.builder().authBearerToken(oAuth2Context.refresh().accessToken());
String currentAccessToken = oAuth2Context.accessToken();
if (currentAccessToken != oAuth2Context.refresh().accessToken()) {
Organization org = getOrganization();
JSONObject envJson = org.getEnvironmentJson();
JSONObject spokeJson = envJson.getJSONObject("spoke");

spokeJson.put("accessToken", oAuth2Context.accessToken());
spokeJson.put("expiresAt", oAuth2Context.expiresAt() != null ? oAuth2Context.expiresAt() : null);
spokeJson.put("refreshToken", oAuth2Context.refreshToken());
org.setEnvironmentJson(envJson);
organizationDao.update(org);
}

return HttpClient.HeaderBuilder.builder().authBearerToken(oAuth2Context.accessToken());
}

//TODO: remove once done with testing
Expand Down
37 changes: 34 additions & 3 deletions src/main/java/com/impactupgrade/nucleus/client/VirtuousClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Strings;
import com.impactupgrade.nucleus.dao.HibernateDao;
import com.impactupgrade.nucleus.entity.Organization;
import com.impactupgrade.nucleus.environment.Environment;
import com.impactupgrade.nucleus.environment.EnvironmentConfig;
import com.impactupgrade.nucleus.util.HttpClient;
import com.impactupgrade.nucleus.util.OAuth2;
import org.json.JSONObject;

import java.time.Duration;
import java.time.LocalDateTime;
Expand All @@ -29,16 +32,32 @@ public class VirtuousClient {
private static final int DEFAULT_LIMIT = 100;

protected final Environment env;
protected HibernateDao<Long, Organization> organizationDao;

private String apiKey;
private final OAuth2.Context oAuth2Context;

public VirtuousClient(Environment env) {
this.env = env;
this.organizationDao = new HibernateDao<>(Organization.class);

Organization org = getOrganization();
JSONObject envJson = org.getEnvironmentJson();
JSONObject virtuousJson = envJson.getJSONObject("virtuous");

this.apiKey = env.getConfig().virtuous.secretKey;
this.oAuth2Context = new OAuth2.UsernamePasswordContext(
env.getConfig().virtuous.username, env.getConfig().virtuous.password, null,
env.getConfig().virtuous.accessToken, env.getConfig().virtuous.refreshToken, env.getConfig().virtuous.tokenServerUrl);
virtuousJson.getString("accessToken"), virtuousJson.getLong("expiresAt"), virtuousJson.getString("refreshToken"), env.getConfig().virtuous.tokenServerUrl);
}

protected Organization getOrganization() {
return organizationDao.getQueryResult(
"from Organization o where o.nucleusApiKey=:apiKey",
query -> {
query.setParameter("apiKey", env.getConfig().apiKey);
}
).get();
}

// Contact
Expand Down Expand Up @@ -256,8 +275,20 @@ private HttpClient.HeaderBuilder headers() {
//If the verification code and user credentials are correct, you will receive a token as seen in the Token authentication above.
//To request a new Token after the user enters the verification code, add an OTP header:
//curl -d "grant_type=password&username=YOUR_EMAIL&password=YOUR_PASSWORD&otp=YOUR_OTP" -X POST https://api.virtuoussoftware.com/Token

return HttpClient.HeaderBuilder.builder().authBearerToken(oAuth2Context.refresh().accessToken());
String currentAccessToken = oAuth2Context.accessToken();
if (currentAccessToken != oAuth2Context.refresh().accessToken()) {
Organization org = getOrganization();
JSONObject envJson = org.getEnvironmentJson();
JSONObject virtuousJson = envJson.getJSONObject("virtuous");

virtuousJson.put("accessToken", oAuth2Context.accessToken());
virtuousJson.put("expiresAt", oAuth2Context.expiresAt() != null ? oAuth2Context.expiresAt() : null);
virtuousJson.put("refreshToken", oAuth2Context.refreshToken());
org.setEnvironmentJson(envJson);
organizationDao.update(org);
}

return HttpClient.HeaderBuilder.builder().authBearerToken(oAuth2Context.accessToken());
}

public static class ContactSearchResponse {
Expand Down
21 changes: 15 additions & 6 deletions src/main/java/com/impactupgrade/nucleus/util/OAuth2.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ public static abstract class Context {
protected Tokens tokens;
protected String tokenUrl;

public Context(String accessToken, String refreshToken, String tokenUrl) {
this.tokens = new Tokens(accessToken, null, refreshToken);
public Context(String accessToken, Long expiresAt, String refreshToken, String tokenUrl) {
Date expiresAtDate = expiresAt != null ? Date.from(Instant.ofEpochSecond(expiresAt)) : null;
this.tokens = new Tokens(accessToken, expiresAtDate, refreshToken);
this.tokenUrl = tokenUrl;
}

Expand All @@ -48,6 +49,14 @@ public String accessToken() {
return tokens != null ? tokens.accessToken() : null;
}

public Date expiresAt() {
return tokens != null ? tokens.expiresAt : null;
}

public String refreshToken() {
return tokens != null ? tokens.refreshToken() : null;
}

protected Tokens refreshTokens() {
if (tokens == null) {
log.warn("can't refresh null!");
Expand Down Expand Up @@ -83,8 +92,8 @@ public static final class ClientCredentialsContext extends Context {
private final String clientId;
private final String clientSecret;

public ClientCredentialsContext(String clientId, String clientSecret, String accessToken, String refreshToken, String tokenUrl) {
super(accessToken, refreshToken, tokenUrl);
public ClientCredentialsContext(String clientId, String clientSecret, String accessToken, Long expiresAt, String refreshToken, String tokenUrl) {
super(accessToken, expiresAt, refreshToken, tokenUrl);
this.clientId = clientId;
this.clientSecret = clientSecret;
}
Expand Down Expand Up @@ -116,8 +125,8 @@ public static final class UsernamePasswordContext extends Context {
public UsernamePasswordContext(
String username, String password,
Map<String, String> requestTokenParams,
String accessToken, String refreshToken, String tokenUrl) {
super(accessToken, refreshToken, tokenUrl);
String accessToken, Long expiresAt, String refreshToken, String tokenUrl) {
super(accessToken, expiresAt, refreshToken, tokenUrl);
this.username = username;
this.password = password;
this.requestTokenParams = requestTokenParams;
Expand Down

0 comments on commit e513d97

Please sign in to comment.