From 66469ff2f76ac916e289e066377570b38554fdcc Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Thu, 28 Aug 2014 07:34:22 -0700 Subject: Rough outline of the F1 attribute logic. Parts of addAttribute have been implemented in F1User, but I may move it out into a general F1 API class. --- src/com/p4square/f1oauth/F1OAuthHelper.java | 7 +++ src/com/p4square/f1oauth/F1User.java | 72 +++++++++++++++++++++- src/com/p4square/f1oauth/SecondPartyVerifier.java | 2 +- .../grow/frontend/AssessmentResultsPage.java | 14 +++++ 4 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/com/p4square/f1oauth/F1OAuthHelper.java b/src/com/p4square/f1oauth/F1OAuthHelper.java index b5241c4..187fb6b 100644 --- a/src/com/p4square/f1oauth/F1OAuthHelper.java +++ b/src/com/p4square/f1oauth/F1OAuthHelper.java @@ -65,6 +65,13 @@ public class F1OAuthHelper extends OAuthHelper { mBaseUrl = "https://" + churchCode + "." + baseUrl + VERSION_STRING; } + /** + * @return The base url for the F1 API, ending with a slash. + */ + public String getBaseUrl() { + return mBaseUrl; + } + /** * @return the URL for the initial RequestToken request. */ diff --git a/src/com/p4square/f1oauth/F1User.java b/src/com/p4square/f1oauth/F1User.java index e5ab487..942f534 100644 --- a/src/com/p4square/f1oauth/F1User.java +++ b/src/com/p4square/f1oauth/F1User.java @@ -19,6 +19,7 @@ public class F1User extends OAuthUser { public static final String LAST_NAME = "lastName"; public static final String ICODE = "@iCode"; + private final String mBaseUrl; private final Map mData; /** @@ -28,9 +29,10 @@ public class F1User extends OAuthUser { * @param data F1 Person Record. * @throws IllegalStateException if data.get("person") is null. */ - public F1User(OAuthUser user, Map data) { + public F1User(String baseUrl, OAuthUser user, Map data) { super(user.getLocation(), user.getToken()); + mBaseUrl = baseUrl; mData = (Map) data.get("person"); if (mData == null) { throw new IllegalStateException("Bad data"); @@ -67,4 +69,72 @@ public class F1User extends OAuthUser { public Object get(String key) { return mData.get(key); } + + /** + * @return the F1 API base url. + */ + public String getBaseUrl() { + return mBaseUrl; + } + + /* + public addAttribute(Attribute attribute, String comment) { + String baseUrl = getBaseUrl(); + Map newAttributeTemplate = null; + + // Get Attribute Template + Request request = new Request(Method.GET, + baseUrl + "People/" + getIdentifier() + "/Attributes/new.json"); + request.setChallengeResponse(getChallengeResponse()); + Response response = getContext().getClientDispatcher().handle(request); + + Representation representation = response.getEntity(); + try { + Status status = response.getStatus(); + if (status.isSuccess()) { + JacksonRepresentation entity = new JacksonRepresentation(response.getEntity(), Map.class); + newAttributeTemplate = entity.getObject(); + } + + } finally { + if (representation != null) { + representation.release(); + } + } + + if (newAttributeTemplate == null) { + LOG.error("Could not retrieve attribute template!"); + return; + } + + // Populate Attribute Template + + + // POST new attribute + Request request = new Request(Method.POST, + baseUrl + "People/" + getIdentifier() + "/Attributes.json"); + request.setChallengeResponse(getChallengeResponse()); + Response response = getContext().getClientDispatcher().handle(request); + + Representation representation = response.getEntity(); + try { + Status status = response.getStatus(); + if (status.isSuccess()) { + JacksonRepresentation entity = new JacksonRepresentation(response.getEntity(), Map.class); + newAttributeTemplate = entity.getObject(); + } + + } finally { + if (representation != null) { + representation.release(); + } + } + + if (newAttributeTemplate == null) { + LOG.error("Could retrieve attribute template!"); + return; + } + + } + */ } diff --git a/src/com/p4square/f1oauth/SecondPartyVerifier.java b/src/com/p4square/f1oauth/SecondPartyVerifier.java index b1afcfa..9fb771f 100644 --- a/src/com/p4square/f1oauth/SecondPartyVerifier.java +++ b/src/com/p4square/f1oauth/SecondPartyVerifier.java @@ -79,7 +79,7 @@ public class SecondPartyVerifier implements Verifier { if (status.isSuccess()) { JacksonRepresentation entity = new JacksonRepresentation(response.getEntity(), Map.class); Map data = entity.getObject(); - return new F1User(user, data); + return new F1User(mHelper.getBaseUrl(), user, data); } else { throw new OAuthException(status); diff --git a/src/com/p4square/grow/frontend/AssessmentResultsPage.java b/src/com/p4square/grow/frontend/AssessmentResultsPage.java index 9c69c69..95c3f6a 100644 --- a/src/com/p4square/grow/frontend/AssessmentResultsPage.java +++ b/src/com/p4square/grow/frontend/AssessmentResultsPage.java @@ -82,6 +82,9 @@ public class AssessmentResultsPage extends FreeMarkerPageResource { return new StringRepresentation("Redirecting to " + nextPage); } + // Publish results in F1 + publishScoreInF1(response.getMap()); + root.put("stage", score); return new TemplateRepresentation(t, root, MediaType.TEXT_HTML); @@ -92,6 +95,17 @@ public class AssessmentResultsPage extends FreeMarkerPageResource { } } + private void publishScoreInF1(Map results) { + if (!(getRequest().getClientInfo().getUser() instanceof F1User)) { + // Only useful if the user is from F1. + return; + } + + F1User user = (F1User) getRequest().getClientInfo().getUser(); + + // TODO: Update the attribute. + } + /** * @return The backend endpoint URI */ -- cgit v1.2.3 From c2feb363e513c0dea83d507eb9ba1918748d4e8e Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Tue, 9 Sep 2014 07:44:01 -0700 Subject: Moving F1OAuthHelper to F1Access. F1Access will provide a collection of F1 API methods, rather than placing all of those methods in F1User as I was originally planning. --- src/com/p4square/f1oauth/F1Access.java | 207 +++++++++++++++++++++ src/com/p4square/f1oauth/F1OAuthHelper.java | 144 -------------- src/com/p4square/f1oauth/F1User.java | 72 +------ .../p4square/f1oauth/SecondPartyAuthenticator.java | 4 +- src/com/p4square/f1oauth/SecondPartyVerifier.java | 6 +- .../grow/frontend/AssessmentResultsPage.java | 2 + src/com/p4square/grow/frontend/GrowFrontend.java | 12 +- .../p4square/grow/frontend/NewAccountResource.java | 6 +- src/com/p4square/restlet/oauth/OAuthHelper.java | 4 +- 9 files changed, 226 insertions(+), 231 deletions(-) create mode 100644 src/com/p4square/f1oauth/F1Access.java delete mode 100644 src/com/p4square/f1oauth/F1OAuthHelper.java diff --git a/src/com/p4square/f1oauth/F1Access.java b/src/com/p4square/f1oauth/F1Access.java new file mode 100644 index 0000000..35957bf --- /dev/null +++ b/src/com/p4square/f1oauth/F1Access.java @@ -0,0 +1,207 @@ +/* + * Copyright 2014 Jesse Morgan + */ + +package com.p4square.f1oauth; + +import java.net.URLEncoder; + +import org.apache.log4j.Logger; + +import org.restlet.Context; +import org.restlet.Response; +import org.restlet.Request; +import org.restlet.data.ChallengeResponse; +import org.restlet.data.ChallengeScheme; +import org.restlet.data.MediaType; +import org.restlet.data.Method; +import org.restlet.data.Status; +import org.restlet.engine.util.Base64; +import org.restlet.representation.StringRepresentation; + +import com.p4square.restlet.oauth.OAuthException; +import com.p4square.restlet.oauth.OAuthHelper; +import com.p4square.restlet.oauth.OAuthUser; +import com.p4square.restlet.oauth.Token; + +/** + * F1 API Access. + * + * @author Jesse Morgan + */ +public class F1Access { + public enum UserType { + WEBLINK, PORTAL; + } + + private static final Logger LOG = Logger.getLogger(F1Access.class); + + private static final String VERSION_STRING = "/v1/"; + private static final String REQUESTTOKEN_URL = "Tokens/RequestToken"; + private static final String AUTHORIZATION_URL = "Login"; + private static final String ACCESSTOKEN_URL= "Tokens/AccessToken"; + private static final String TRUSTED_ACCESSTOKEN_URL = "/AccessToken"; + + private final String mBaseUrl; + private final String mMethod; + + private final OAuthHelper mOAuthHelper; + + /** + */ + public F1Access(Context context, String consumerKey, String consumerSecret, + String baseUrl, String churchCode, UserType userType) { + + switch (userType) { + case WEBLINK: + mMethod = "WeblinkUser"; + break; + case PORTAL: + mMethod = "PortalUser"; + break; + default: + throw new IllegalArgumentException("Unknown UserType"); + } + + mBaseUrl = "https://" + churchCode + "." + baseUrl + VERSION_STRING; + + // Create the OAuthHelper. This implicitly registers the helper to + // handle outgoing requests which need OAuth authentication. + mOAuthHelper = new OAuthHelper(context, consumerKey, consumerSecret) { + @Override + protected String getRequestTokenUrl() { + return mBaseUrl + REQUESTTOKEN_URL; + } + + @Override + public String getLoginUrl(Token requestToken, String callback) { + String loginUrl = mBaseUrl + mMethod + AUTHORIZATION_URL + + "?oauth_token=" + URLEncoder.encode(requestToken.getToken()); + + if (callback != null) { + loginUrl += "&oauth_callback=" + URLEncoder.encode(callback); + } + + return loginUrl; + } + + @Override + protected String getAccessTokenUrl() { + return mBaseUrl + ACCESSTOKEN_URL; + } + }; + + } + + /** + * Request an AccessToken for a particular username and password. + * + * This is an F1 extension to OAuth: + * http://developer.fellowshipone.com/docs/v1/Util/AuthDocs.help#2creds + */ + public OAuthUser getAccessToken(String username, String password) throws OAuthException { + Request request = new Request(Method.POST, mBaseUrl + mMethod + TRUSTED_ACCESSTOKEN_URL); + request.setChallengeResponse(new ChallengeResponse(ChallengeScheme.HTTP_OAUTH)); + + String base64String = Base64.encode((username + " " + password).getBytes(), false); + request.setEntity(new StringRepresentation(base64String)); + + return mOAuthHelper.processAccessTokenRequest(request); + } + + /** + * Create a new Account. + * + * @param firstname The user's first name. + * @param lastname The user's last name. + * @param email The user's email address. + * @param redirect The URL to send the user to after confirming his address. + * + * @return true if created, false if the account already exists. + */ + public boolean createAccount(String firstname, String lastname, String email, String redirect) + throws OAuthException { + String req = String.format("{\n\"account\":{\n\"firstName\":\"%s\",\n" + + "\"lastName\":\"%s\",\n\"email\":\"%s\",\n" + + "\"urlRedirect\":\"%s\"\n}\n}", + firstname, lastname, email, redirect); + + Request request = new Request(Method.POST, mBaseUrl + "Accounts"); + request.setChallengeResponse(new ChallengeResponse(ChallengeScheme.HTTP_OAUTH)); + request.setEntity(new StringRepresentation(req, MediaType.APPLICATION_JSON)); + + Response response = mOAuthHelper.getResponse(request); + + Status status = response.getStatus(); + if (Status.SUCCESS_NO_CONTENT.equals(status)) { + return true; + + } else if (Status.CLIENT_ERROR_CONFLICT.equals(status)) { + return false; + + } else { + throw new OAuthException(status); + } + } + + /* + public addAttribute(Attribute attribute, String comment) { + String baseUrl = getBaseUrl(); + Map newAttributeTemplate = null; + + // Get Attribute Template + Request request = new Request(Method.GET, + baseUrl + "People/" + getIdentifier() + "/Attributes/new.json"); + request.setChallengeResponse(getChallengeResponse()); + Response response = getContext().getClientDispatcher().handle(request); + + Representation representation = response.getEntity(); + try { + Status status = response.getStatus(); + if (status.isSuccess()) { + JacksonRepresentation entity = new JacksonRepresentation(response.getEntity(), Map.class); + newAttributeTemplate = entity.getObject(); + } + + } finally { + if (representation != null) { + representation.release(); + } + } + + if (newAttributeTemplate == null) { + LOG.error("Could not retrieve attribute template!"); + return; + } + + // Populate Attribute Template + + + // POST new attribute + Request request = new Request(Method.POST, + baseUrl + "People/" + getIdentifier() + "/Attributes.json"); + request.setChallengeResponse(getChallengeResponse()); + Response response = getContext().getClientDispatcher().handle(request); + + Representation representation = response.getEntity(); + try { + Status status = response.getStatus(); + if (status.isSuccess()) { + JacksonRepresentation entity = new JacksonRepresentation(response.getEntity(), Map.class); + newAttributeTemplate = entity.getObject(); + } + + } finally { + if (representation != null) { + representation.release(); + } + } + + if (newAttributeTemplate == null) { + LOG.error("Could retrieve attribute template!"); + return; + } + + } + */ +} diff --git a/src/com/p4square/f1oauth/F1OAuthHelper.java b/src/com/p4square/f1oauth/F1OAuthHelper.java deleted file mode 100644 index 187fb6b..0000000 --- a/src/com/p4square/f1oauth/F1OAuthHelper.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2013 Jesse Morgan - */ - -package com.p4square.f1oauth; - -import java.net.URLEncoder; - -import org.apache.log4j.Logger; - -import org.restlet.Context; -import org.restlet.Response; -import org.restlet.Request; -import org.restlet.data.ChallengeResponse; -import org.restlet.data.ChallengeScheme; -import org.restlet.data.MediaType; -import org.restlet.data.Method; -import org.restlet.data.Status; -import org.restlet.engine.util.Base64; -import org.restlet.representation.StringRepresentation; - -import com.p4square.restlet.oauth.OAuthException; -import com.p4square.restlet.oauth.OAuthHelper; -import com.p4square.restlet.oauth.OAuthUser; -import com.p4square.restlet.oauth.Token; - -/** - * - * @author Jesse Morgan - */ -public class F1OAuthHelper extends OAuthHelper { - public enum UserType { - WEBLINK, PORTAL; - } - - private static final Logger LOG = Logger.getLogger(F1OAuthHelper.class); - - private static final String VERSION_STRING = "/v1/"; - private static final String REQUESTTOKEN_URL = "Tokens/RequestToken"; - private static final String AUTHORIZATION_URL = "Login"; - private static final String ACCESSTOKEN_URL= "Tokens/AccessToken"; - private static final String TRUSTED_ACCESSTOKEN_URL = "/AccessToken"; - - private final String mBaseUrl; - private final String mMethod; - - /** - * @param method Either WeblinkUser or PortalUser. - */ - public F1OAuthHelper(Context context, String consumerKey, String consumerSecret, - String baseUrl, String churchCode, UserType userType) { - super(context, consumerKey, consumerSecret); - - switch (userType) { - case WEBLINK: - mMethod = "WeblinkUser"; - break; - case PORTAL: - mMethod = "PortalUser"; - break; - default: - throw new IllegalArgumentException("Unknown UserType"); - } - - mBaseUrl = "https://" + churchCode + "." + baseUrl + VERSION_STRING; - } - - /** - * @return The base url for the F1 API, ending with a slash. - */ - public String getBaseUrl() { - return mBaseUrl; - } - - /** - * @return the URL for the initial RequestToken request. - */ - protected String getRequestTokenUrl() { - return mBaseUrl + REQUESTTOKEN_URL; - } - - /** - * @return the URL to redirect the user to for Authentication. - */ - public String getLoginUrl(Token requestToken, String callback) { - String loginUrl = mBaseUrl + mMethod + AUTHORIZATION_URL - + "?oauth_token=" + URLEncoder.encode(requestToken.getToken()); - - if (callback != null) { - loginUrl += "&oauth_callback=" + URLEncoder.encode(callback); - } - - return loginUrl; - } - - - /** - * @return the URL for the AccessToken request. - */ - protected String getAccessTokenUrl() { - return mBaseUrl + ACCESSTOKEN_URL; - } - - /** - * Request an AccessToken for a particular username and password. - * - * This is an F1 extension to OAuth: - * http://developer.fellowshipone.com/docs/v1/Util/AuthDocs.help#2creds - */ - public OAuthUser getAccessToken(String username, String password) throws OAuthException { - Request request = new Request(Method.POST, mBaseUrl + mMethod + TRUSTED_ACCESSTOKEN_URL); - request.setChallengeResponse(new ChallengeResponse(ChallengeScheme.HTTP_OAUTH)); - - String base64String = Base64.encode((username + " " + password).getBytes(), false); - request.setEntity(new StringRepresentation(base64String)); - - return processAccessTokenRequest(request); - } - - public boolean createAccount(String firstname, String lastname, String email, String redirect) - throws OAuthException { - String req = String.format("{\n\"account\":{\n\"firstName\":\"%s\",\n" - + "\"lastName\":\"%s\",\n\"email\":\"%s\",\n" - + "\"urlRedirect\":\"%s\"\n}\n}", - firstname, lastname, email, redirect); - - Request request = new Request(Method.POST, mBaseUrl + "Accounts"); - request.setChallengeResponse(new ChallengeResponse(ChallengeScheme.HTTP_OAUTH)); - request.setEntity(new StringRepresentation(req, MediaType.APPLICATION_JSON)); - - Response response = getResponse(request); - - Status status = response.getStatus(); - if (Status.SUCCESS_NO_CONTENT.equals(status)) { - return true; - - } else if (Status.CLIENT_ERROR_CONFLICT.equals(status)) { - return false; - - } else { - throw new OAuthException(status); - } - } -} diff --git a/src/com/p4square/f1oauth/F1User.java b/src/com/p4square/f1oauth/F1User.java index 942f534..e5ab487 100644 --- a/src/com/p4square/f1oauth/F1User.java +++ b/src/com/p4square/f1oauth/F1User.java @@ -19,7 +19,6 @@ public class F1User extends OAuthUser { public static final String LAST_NAME = "lastName"; public static final String ICODE = "@iCode"; - private final String mBaseUrl; private final Map mData; /** @@ -29,10 +28,9 @@ public class F1User extends OAuthUser { * @param data F1 Person Record. * @throws IllegalStateException if data.get("person") is null. */ - public F1User(String baseUrl, OAuthUser user, Map data) { + public F1User(OAuthUser user, Map data) { super(user.getLocation(), user.getToken()); - mBaseUrl = baseUrl; mData = (Map) data.get("person"); if (mData == null) { throw new IllegalStateException("Bad data"); @@ -69,72 +67,4 @@ public class F1User extends OAuthUser { public Object get(String key) { return mData.get(key); } - - /** - * @return the F1 API base url. - */ - public String getBaseUrl() { - return mBaseUrl; - } - - /* - public addAttribute(Attribute attribute, String comment) { - String baseUrl = getBaseUrl(); - Map newAttributeTemplate = null; - - // Get Attribute Template - Request request = new Request(Method.GET, - baseUrl + "People/" + getIdentifier() + "/Attributes/new.json"); - request.setChallengeResponse(getChallengeResponse()); - Response response = getContext().getClientDispatcher().handle(request); - - Representation representation = response.getEntity(); - try { - Status status = response.getStatus(); - if (status.isSuccess()) { - JacksonRepresentation entity = new JacksonRepresentation(response.getEntity(), Map.class); - newAttributeTemplate = entity.getObject(); - } - - } finally { - if (representation != null) { - representation.release(); - } - } - - if (newAttributeTemplate == null) { - LOG.error("Could not retrieve attribute template!"); - return; - } - - // Populate Attribute Template - - - // POST new attribute - Request request = new Request(Method.POST, - baseUrl + "People/" + getIdentifier() + "/Attributes.json"); - request.setChallengeResponse(getChallengeResponse()); - Response response = getContext().getClientDispatcher().handle(request); - - Representation representation = response.getEntity(); - try { - Status status = response.getStatus(); - if (status.isSuccess()) { - JacksonRepresentation entity = new JacksonRepresentation(response.getEntity(), Map.class); - newAttributeTemplate = entity.getObject(); - } - - } finally { - if (representation != null) { - representation.release(); - } - } - - if (newAttributeTemplate == null) { - LOG.error("Could retrieve attribute template!"); - return; - } - - } - */ } diff --git a/src/com/p4square/f1oauth/SecondPartyAuthenticator.java b/src/com/p4square/f1oauth/SecondPartyAuthenticator.java index 1983d69..8deefec 100644 --- a/src/com/p4square/f1oauth/SecondPartyAuthenticator.java +++ b/src/com/p4square/f1oauth/SecondPartyAuthenticator.java @@ -21,9 +21,9 @@ import org.restlet.security.Authenticator; public class SecondPartyAuthenticator extends Authenticator { private static final Logger LOG = Logger.getLogger(SecondPartyAuthenticator.class); - private final F1OAuthHelper mHelper; + private final F1Access mHelper; - public SecondPartyAuthenticator(Context context, boolean optional, F1OAuthHelper helper) { + public SecondPartyAuthenticator(Context context, boolean optional, F1Access helper) { super(context, optional); mHelper = helper; diff --git a/src/com/p4square/f1oauth/SecondPartyVerifier.java b/src/com/p4square/f1oauth/SecondPartyVerifier.java index 9fb771f..e2d6d00 100644 --- a/src/com/p4square/f1oauth/SecondPartyVerifier.java +++ b/src/com/p4square/f1oauth/SecondPartyVerifier.java @@ -30,9 +30,9 @@ public class SecondPartyVerifier implements Verifier { private static final Logger LOG = Logger.getLogger(SecondPartyVerifier.class); private final Restlet mDispatcher; - private final F1OAuthHelper mHelper; + private final F1Access mHelper; - public SecondPartyVerifier(Context context, F1OAuthHelper helper) { + public SecondPartyVerifier(Context context, F1Access helper) { if (helper == null) { throw new IllegalArgumentException("Helper can not be null."); } @@ -79,7 +79,7 @@ public class SecondPartyVerifier implements Verifier { if (status.isSuccess()) { JacksonRepresentation entity = new JacksonRepresentation(response.getEntity(), Map.class); Map data = entity.getObject(); - return new F1User(mHelper.getBaseUrl(), user, data); + return new F1User(user, data); } else { throw new OAuthException(status); diff --git a/src/com/p4square/grow/frontend/AssessmentResultsPage.java b/src/com/p4square/grow/frontend/AssessmentResultsPage.java index 95c3f6a..c205503 100644 --- a/src/com/p4square/grow/frontend/AssessmentResultsPage.java +++ b/src/com/p4square/grow/frontend/AssessmentResultsPage.java @@ -22,6 +22,8 @@ import com.p4square.fmfacade.json.JsonRequestClient; import com.p4square.fmfacade.json.JsonResponse; import com.p4square.fmfacade.json.ClientException; +import com.p4square.f1oauth.F1User; + import com.p4square.grow.config.Config; /** diff --git a/src/com/p4square/grow/frontend/GrowFrontend.java b/src/com/p4square/grow/frontend/GrowFrontend.java index 4b193d0..926670b 100644 --- a/src/com/p4square/grow/frontend/GrowFrontend.java +++ b/src/com/p4square/grow/frontend/GrowFrontend.java @@ -30,7 +30,7 @@ import com.p4square.fmfacade.FreeMarkerPageResource; import com.p4square.grow.config.Config; -import com.p4square.f1oauth.F1OAuthHelper; +import com.p4square.f1oauth.F1Access; import com.p4square.f1oauth.SecondPartyVerifier; import com.p4square.session.SessionCheckingAuthenticator; @@ -49,7 +49,7 @@ public class GrowFrontend extends FMFacade { private Config mConfig; - private F1OAuthHelper mHelper; + private F1Access mHelper; public GrowFrontend() { this(new Config()); @@ -73,13 +73,13 @@ public class GrowFrontend extends FMFacade { super.start(); } - synchronized F1OAuthHelper getHelper() { + synchronized F1Access getF1Access() { if (mHelper == null) { - mHelper = new F1OAuthHelper(getContext(), mConfig.getString("f1ConsumerKey", ""), + mHelper = new F1Access(getContext(), mConfig.getString("f1ConsumerKey", ""), mConfig.getString("f1ConsumerSecret", ""), mConfig.getString("f1BaseUrl", "staging.fellowshiponeapi.com"), mConfig.getString("f1ChurchCode", "pfseawa"), - F1OAuthHelper.UserType.WEBLINK); + F1Access.UserType.WEBLINK); } return mHelper; @@ -129,7 +129,7 @@ public class GrowFrontend extends FMFacade { SessionCheckingAuthenticator sessionChk = new SessionCheckingAuthenticator(context, true); // This is used to authenticate the user - SecondPartyVerifier f1Verifier = new SecondPartyVerifier(context, getHelper()); + SecondPartyVerifier f1Verifier = new SecondPartyVerifier(context, getF1Access()); LoginFormAuthenticator loginAuth = new LoginFormAuthenticator(context, false, f1Verifier); loginAuth.setLoginFormUrl(loginPage); loginAuth.setLoginPostUrl(loginPost); diff --git a/src/com/p4square/grow/frontend/NewAccountResource.java b/src/com/p4square/grow/frontend/NewAccountResource.java index 9155a00..54c1790 100644 --- a/src/com/p4square/grow/frontend/NewAccountResource.java +++ b/src/com/p4square/grow/frontend/NewAccountResource.java @@ -18,7 +18,7 @@ import org.restlet.ext.freemarker.TemplateRepresentation; import org.apache.log4j.Logger; -import com.p4square.f1oauth.F1OAuthHelper; +import com.p4square.f1oauth.F1Access; import com.p4square.restlet.oauth.OAuthException; import com.p4square.fmfacade.FreeMarkerPageResource; @@ -32,7 +32,7 @@ public class NewAccountResource extends FreeMarkerPageResource { private static Logger LOG = Logger.getLogger(NewAccountResource.class); private GrowFrontend mGrowFrontend; - private F1OAuthHelper mHelper; + private F1Access mHelper; private String mErrorMessage; @@ -44,7 +44,7 @@ public class NewAccountResource extends FreeMarkerPageResource { super.doInit(); mGrowFrontend = (GrowFrontend) getApplication(); - mHelper = mGrowFrontend.getHelper(); + mHelper = mGrowFrontend.getF1Access(); mErrorMessage = ""; diff --git a/src/com/p4square/restlet/oauth/OAuthHelper.java b/src/com/p4square/restlet/oauth/OAuthHelper.java index 39c1b02..67dd238 100644 --- a/src/com/p4square/restlet/oauth/OAuthHelper.java +++ b/src/com/p4square/restlet/oauth/OAuthHelper.java @@ -127,7 +127,7 @@ public abstract class OAuthHelper { * @return An OAuthUser object wrapping the AccessToken. * @throws OAuthException if the request failed. */ - protected OAuthUser processAccessTokenRequest(Request request) throws OAuthException { + public OAuthUser processAccessTokenRequest(Request request) throws OAuthException { Response response = getResponse(request); Token accessToken = processTokenRequest(response); @@ -143,7 +143,7 @@ public abstract class OAuthHelper { /** * Helper method to get a Response for a Request. */ - protected Response getResponse(Request request) { + public Response getResponse(Request request) { return mDispatcher.handle(request); } } -- cgit v1.2.3 From d01b3c8e49251c85cfa9c426064b841233c6c8e4 Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Sun, 21 Sep 2014 15:01:40 -0700 Subject: Adding Support for Assigning Attributes in F1. Adding a new interface, F1API for F1 APIs which require a valid access token. This is now used by AssessmentResultsPage to assign an attribute each time someone completes the assessment. Also adding an AttributeTool to list all attributes and assign attributes to users. --- src/com/p4square/f1oauth/Attribute.java | 87 ++++++++ src/com/p4square/f1oauth/F1API.java | 44 ++++ src/com/p4square/f1oauth/F1Access.java | 242 +++++++++++++++++---- src/com/p4square/f1oauth/F1Exception.java | 15 ++ src/com/p4square/f1oauth/SecondPartyVerifier.java | 23 +- src/com/p4square/grow/GrowProcessComponent.java | 1 - .../grow/frontend/AssessmentResultsPage.java | 25 ++- src/com/p4square/grow/tools/AttributeTool.java | 143 ++++++++++++ 8 files changed, 511 insertions(+), 69 deletions(-) create mode 100644 src/com/p4square/f1oauth/Attribute.java create mode 100644 src/com/p4square/f1oauth/F1API.java create mode 100644 src/com/p4square/f1oauth/F1Exception.java create mode 100644 src/com/p4square/grow/tools/AttributeTool.java diff --git a/src/com/p4square/f1oauth/Attribute.java b/src/com/p4square/f1oauth/Attribute.java new file mode 100644 index 0000000..fa46d90 --- /dev/null +++ b/src/com/p4square/f1oauth/Attribute.java @@ -0,0 +1,87 @@ +/* + * Copyright 2014 Jesse Morgan + */ + +package com.p4square.f1oauth; + +import java.util.Date; + +/** + * F1 Attribute Data. + * + * @author Jesse Morgan + */ +public class Attribute { + /*Attribute + *{ + "attribute": { + "@id": "", + "@uri": "", + "person": { + "@id": "1636208", + "@uri": "https://demo.fellowshiponeapi.com/v1/People/1636208" + }, + "attributeGroup": { + "@id": "", + "@uri": "", + "name": null, + "attribute": { + "@id": "958", + "@uri": "", + "name": null + } + }, + "startDate": null, + "endDate": null, + "comment": null, + "createdDate": null, + "lastUpdatedDate": null + } + */ + + private Date mStartDate; + private Date mEndDate; + private String mComment; + + /** + * @return the start date for the attribute. + */ + public Date getStartDate() { + return mStartDate; + } + + /** + * Set the start date for the attribute. + */ + public void setStartDate(Date date) { + mStartDate = date; + } + + /** + * @return the end date for the attribute. + */ + public Date getEndDate() { + return mEndDate; + } + + /** + * Set the end date for the attribute. + */ + public void setEndDate(Date date) { + mEndDate = date; + } + + /** + * @return The comment on the Attribute. + */ + public String getComment() { + return mComment; + } + + /** + * Set the comment on the attribute. + */ + public void setComment(String comment) { + mComment = comment; + } +} diff --git a/src/com/p4square/f1oauth/F1API.java b/src/com/p4square/f1oauth/F1API.java new file mode 100644 index 0000000..88801db --- /dev/null +++ b/src/com/p4square/f1oauth/F1API.java @@ -0,0 +1,44 @@ +/* + * Copyright 2014 Jesse Morgan + */ + +package com.p4square.f1oauth; + +import java.io.IOException; +import java.util.Map; + +import com.p4square.restlet.oauth.OAuthException; +import com.p4square.restlet.oauth.OAuthUser; + +/** + * F1 API methods which require an authenticated user. + * + * @author Jesse Morgan + */ +public interface F1API { + /** + * Fetch information about a user. + * + * @param user The user to fetch information about. + * @return An F1User object. + */ + F1User getF1User(OAuthUser user) throws OAuthException, IOException; + + /** + * Fetch a list of all attributes ids and names. + * + * @return A Map of attribute name to attribute id. + */ + Map getAttributeList() throws F1Exception; + + /** + * Add an attribute to the user. + * + * @param user The user to add the attribute to. + * @param attributeName The attribute to add. + * @param attribute The attribute to add. + */ + boolean addAttribute(String userId, String attributeName, Attribute attribute) + throws F1Exception; + +} diff --git a/src/com/p4square/f1oauth/F1Access.java b/src/com/p4square/f1oauth/F1Access.java index 35957bf..32550c4 100644 --- a/src/com/p4square/f1oauth/F1Access.java +++ b/src/com/p4square/f1oauth/F1Access.java @@ -4,19 +4,26 @@ package com.p4square.f1oauth; +import java.io.IOException; import java.net.URLEncoder; +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.log4j.Logger; import org.restlet.Context; -import org.restlet.Response; import org.restlet.Request; +import org.restlet.Response; import org.restlet.data.ChallengeResponse; import org.restlet.data.ChallengeScheme; import org.restlet.data.MediaType; import org.restlet.data.Method; import org.restlet.data.Status; import org.restlet.engine.util.Base64; +import org.restlet.ext.jackson.JacksonRepresentation; +import org.restlet.representation.Representation; import org.restlet.representation.StringRepresentation; import com.p4square.restlet.oauth.OAuthException; @@ -42,11 +49,16 @@ public class F1Access { private static final String ACCESSTOKEN_URL= "Tokens/AccessToken"; private static final String TRUSTED_ACCESSTOKEN_URL = "/AccessToken"; + private static final SimpleDateFormat DATE_FORMAT = + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + private final String mBaseUrl; private final String mMethod; private final OAuthHelper mOAuthHelper; + private final Map mAttributeIdByName; + /** */ public F1Access(Context context, String consumerKey, String consumerSecret, @@ -91,6 +103,7 @@ public class F1Access { } }; + mAttributeIdByName = new HashMap<>(); } /** @@ -144,64 +157,205 @@ public class F1Access { } } - /* - public addAttribute(Attribute attribute, String comment) { - String baseUrl = getBaseUrl(); - Map newAttributeTemplate = null; - - // Get Attribute Template - Request request = new Request(Method.GET, - baseUrl + "People/" + getIdentifier() + "/Attributes/new.json"); - request.setChallengeResponse(getChallengeResponse()); - Response response = getContext().getClientDispatcher().handle(request); - - Representation representation = response.getEntity(); - try { - Status status = response.getStatus(); - if (status.isSuccess()) { - JacksonRepresentation entity = new JacksonRepresentation(response.getEntity(), Map.class); - newAttributeTemplate = entity.getObject(); - } + /** + * @return An F1API authenticated by the given user. + */ + public F1API getAuthenticatedApi(OAuthUser user) { + return new AuthenticatedApi(user); + } + + private class AuthenticatedApi implements F1API { + private final OAuthUser mUser; + + public AuthenticatedApi(OAuthUser user) { + mUser = user; + } - } finally { - if (representation != null) { - representation.release(); + /** + * Fetch information about a user. + * + * @param user The user to fetch information about. + * @return An F1User object. + */ + @Override + public F1User getF1User(OAuthUser user) throws OAuthException, IOException { + Request request = new Request(Method.GET, user.getLocation() + ".json"); + request.setChallengeResponse(mUser.getChallengeResponse()); + Response response = mOAuthHelper.getResponse(request); + + try { + Status status = response.getStatus(); + if (status.isSuccess()) { + JacksonRepresentation entity = + new JacksonRepresentation(response.getEntity(), Map.class); + Map data = entity.getObject(); + return new F1User(user, data); + + } else { + throw new OAuthException(status); + } + } finally { + if (response.getEntity() != null) { + response.release(); + } } } - if (newAttributeTemplate == null) { - LOG.error("Could not retrieve attribute template!"); - return; + @Override + public Map getAttributeList() throws F1Exception { + // Note: this list is shared by all F1 users. + synchronized (mAttributeIdByName) { + if (mAttributeIdByName.size() == 0) { + // Reload attributes. Maybe it will be there now... + Request request = new Request(Method.GET, + mBaseUrl + "People/AttributeGroups.json"); + request.setChallengeResponse(mUser.getChallengeResponse()); + Response response = mOAuthHelper.getResponse(request); + + Representation representation = response.getEntity(); + try { + Status status = response.getStatus(); + if (status.isSuccess()) { + JacksonRepresentation entity = + new JacksonRepresentation(response.getEntity(), Map.class); + + Map attributeGroups = (Map) entity.getObject().get("attributeGroups"); + List groups = (List) attributeGroups.get("attributeGroup"); + + for (Map group : groups) { + List attributes = (List) group.get("attribute"); + if (attributes != null) { + for (Map attribute : attributes) { + String id = (String) attribute.get("@id"); + String name = ((String) attribute.get("name")); + mAttributeIdByName.put(name.toLowerCase(), id); + LOG.debug("Caching attribute '" + name + + "' with id '" + id + "'"); + } + } + } + } + + } catch (IOException e) { + throw new F1Exception("Could not parse AttributeGroups.", e); + + } finally { + if (representation != null) { + representation.release(); + } + } + } + + return mAttributeIdByName; + } } - // Populate Attribute Template + /** + * Add an attribute to the user. + * + * @param user The user to add the attribute to. + * @param attributeName The attribute to add. + * @param attribute The attribute to add. + */ + public boolean addAttribute(String userId, String attributeName, Attribute attribute) + throws F1Exception { + + // Get the attribute id. + String attributeId = getAttributeId(attributeName); + if (attributeId == null) { + throw new F1Exception("Could not find id for " + attributeName); + } + + // Get Attribute Template + Map attributeTemplate = null; + + { + Request request = new Request(Method.GET, + mBaseUrl + "People/" + userId + "/Attributes/new.json"); + request.setChallengeResponse(mUser.getChallengeResponse()); + Response response = mOAuthHelper.getResponse(request); + + Representation representation = response.getEntity(); + try { + Status status = response.getStatus(); + if (status.isSuccess()) { + JacksonRepresentation entity = + new JacksonRepresentation(response.getEntity(), Map.class); + attributeTemplate = entity.getObject(); + + } else { + throw new F1Exception("Failed to retrieve attribute template: " + + status); + } + + } catch (IOException e) { + throw new F1Exception("Could not parse attribute template.", e); + + } finally { + if (representation != null) { + representation.release(); + } + } + } + + if (attributeTemplate == null) { + throw new F1Exception("Could not retrieve attribute template."); + } + + // Populate Attribute Template + Map attributeMap = (Map) attributeTemplate.get("attribute"); + Map attributeGroup = (Map) attributeMap.get("attributeGroup"); + Map attributeIdMap = new HashMap<>(); + attributeIdMap.put("@id", attributeId); + attributeGroup.put("attribute", attributeIdMap); - // POST new attribute - Request request = new Request(Method.POST, - baseUrl + "People/" + getIdentifier() + "/Attributes.json"); - request.setChallengeResponse(getChallengeResponse()); - Response response = getContext().getClientDispatcher().handle(request); + if (attribute.getStartDate() != null) { + attributeMap.put("startDate", DATE_FORMAT.format(attribute.getStartDate())); + } - Representation representation = response.getEntity(); - try { - Status status = response.getStatus(); - if (status.isSuccess()) { - JacksonRepresentation entity = new JacksonRepresentation(response.getEntity(), Map.class); - newAttributeTemplate = entity.getObject(); + if (attribute.getStartDate() != null) { + attributeMap.put("endDate", DATE_FORMAT.format(attribute.getStartDate())); } - } finally { - if (representation != null) { - representation.release(); + attributeMap.put("comment", attribute.getComment()); + + // POST new attribute + Status status; + { + Request request = new Request(Method.POST, + mBaseUrl + "People/" + userId + "/Attributes.json"); + request.setChallengeResponse(mUser.getChallengeResponse()); + request.setEntity(new JacksonRepresentation(attributeTemplate)); + Response response = mOAuthHelper.getResponse(request); + + Representation representation = response.getEntity(); + try { + status = response.getStatus(); + + if (status.isSuccess()) { + return true; + } + + } finally { + if (representation != null) { + representation.release(); + } + } } + + LOG.debug("addAttribute failed POST: " + status); + return false; } - if (newAttributeTemplate == null) { - LOG.error("Could retrieve attribute template!"); - return; + /** + * @return an attribute id for the given attribute name. + */ + private String getAttributeId(String attributeName) throws F1Exception { + Map attributeMap = getAttributeList(); + + return attributeMap.get(attributeName.toLowerCase()); } } - */ } diff --git a/src/com/p4square/f1oauth/F1Exception.java b/src/com/p4square/f1oauth/F1Exception.java new file mode 100644 index 0000000..54c1a77 --- /dev/null +++ b/src/com/p4square/f1oauth/F1Exception.java @@ -0,0 +1,15 @@ +/* + * Copyright 2014 Jesse Morgan + */ + +package com.p4square.f1oauth; + +public class F1Exception extends Exception { + public F1Exception(String message) { + super(message); + } + + public F1Exception(String message, Exception cause) { + super(message, cause); + } +} diff --git a/src/com/p4square/f1oauth/SecondPartyVerifier.java b/src/com/p4square/f1oauth/SecondPartyVerifier.java index e2d6d00..882c7e7 100644 --- a/src/com/p4square/f1oauth/SecondPartyVerifier.java +++ b/src/com/p4square/f1oauth/SecondPartyVerifier.java @@ -54,7 +54,7 @@ public class SecondPartyVerifier implements Verifier { OAuthUser ouser = mHelper.getAccessToken(username, password); // Once we have a user, fetch the people record to get the user id. - F1User user = getF1User(ouser); + F1User user = mHelper.getAuthenticatedApi(ouser).getF1User(ouser); user.setEmail(username); // This seems like a hack... but it'll work @@ -69,25 +69,4 @@ public class SecondPartyVerifier implements Verifier { return RESULT_INVALID; // Invalid credentials } - private F1User getF1User(OAuthUser user) throws OAuthException, IOException { - Request request = new Request(Method.GET, user.getLocation() + ".json"); - request.setChallengeResponse(user.getChallengeResponse()); - Response response = mDispatcher.handle(request); - - try { - Status status = response.getStatus(); - if (status.isSuccess()) { - JacksonRepresentation entity = new JacksonRepresentation(response.getEntity(), Map.class); - Map data = entity.getObject(); - return new F1User(user, data); - - } else { - throw new OAuthException(status); - } - } finally { - if (response.getEntity() != null) { - response.release(); - } - } - } } diff --git a/src/com/p4square/grow/GrowProcessComponent.java b/src/com/p4square/grow/GrowProcessComponent.java index 18b3d5b..791f177 100644 --- a/src/com/p4square/grow/GrowProcessComponent.java +++ b/src/com/p4square/grow/GrowProcessComponent.java @@ -10,7 +10,6 @@ import java.io.IOException; import org.apache.log4j.Logger; import org.restlet.Application; -import org.restlet.Client; import org.restlet.Component; import org.restlet.Restlet; import org.restlet.data.ChallengeScheme; diff --git a/src/com/p4square/grow/frontend/AssessmentResultsPage.java b/src/com/p4square/grow/frontend/AssessmentResultsPage.java index c205503..ff1832c 100644 --- a/src/com/p4square/grow/frontend/AssessmentResultsPage.java +++ b/src/com/p4square/grow/frontend/AssessmentResultsPage.java @@ -4,6 +4,7 @@ package com.p4square.grow.frontend; +import java.util.Date; import java.util.Map; import freemarker.template.Template; @@ -22,9 +23,12 @@ import com.p4square.fmfacade.json.JsonRequestClient; import com.p4square.fmfacade.json.JsonResponse; import com.p4square.fmfacade.json.ClientException; +import com.p4square.f1oauth.Attribute; +import com.p4square.f1oauth.F1API; import com.p4square.f1oauth.F1User; import com.p4square.grow.config.Config; +import com.p4square.grow.provider.JsonEncodedProvider; /** * This page fetches the user's final score and displays the transitional page between @@ -105,7 +109,23 @@ public class AssessmentResultsPage extends FreeMarkerPageResource { F1User user = (F1User) getRequest().getClientInfo().getUser(); - // TODO: Update the attribute. + // Update the attribute. + String attributeName = "Assessment Complete - " + results.get("result"); + + try { + Attribute attribute = new Attribute(); + attribute.setStartDate(new Date()); + attribute.setComment(JsonEncodedProvider.MAPPER.writeValueAsString(results)); + + F1API f1 = mGrowFrontend.getF1Access().getAuthenticatedApi(user); + if (!f1.addAttribute(user.getIdentifier(), attributeName, attribute)) { + LOG.error("addAttribute failed for " + user.getIdentifier() + + " with attribute " + attributeName); + } + } catch (Exception e) { + LOG.error("addAttribute failed for " + user.getIdentifier() + + " with attribute " + attributeName, e); + } } /** @@ -124,7 +144,8 @@ public class AssessmentResultsPage extends FreeMarkerPageResource { final JsonResponse response = mJsonClient.get(getBackendEndpoint() + uri); final Status status = response.getStatus(); if (!status.isSuccess() && !Status.CLIENT_ERROR_NOT_FOUND.equals(status)) { - LOG.warn("Error making backend request for '" + uri + "'. status = " + response.getStatus().toString()); + LOG.warn("Error making backend request for '" + uri + "'. status = " + + response.getStatus().toString()); } return response; diff --git a/src/com/p4square/grow/tools/AttributeTool.java b/src/com/p4square/grow/tools/AttributeTool.java new file mode 100644 index 0000000..0775087 --- /dev/null +++ b/src/com/p4square/grow/tools/AttributeTool.java @@ -0,0 +1,143 @@ +/* + * Copyright 2014 Jesse Morgan + */ + +package com.p4square.grow.tools; + +import java.util.Arrays; +import java.util.Date; +import java.util.Map; + +import org.restlet.Client; +import org.restlet.Context; +import org.restlet.data.Protocol; + +import com.p4square.grow.config.Config; +import com.p4square.f1oauth.Attribute; +import com.p4square.f1oauth.F1Access; +import com.p4square.f1oauth.F1API; +import com.p4square.f1oauth.F1Exception; +import com.p4square.restlet.oauth.OAuthUser; + +/** + * Tool for manipulating F1 Attributes. + * + * @author Jesse Morgan + */ +public class AttributeTool { + + private static Config mConfig; + private static F1API mF1API; + + public static void usage() { + System.out.println("java com.p4square.grow.tools.AttributeTool ...\n"); + System.out.println("Commands:"); + System.out.println("\t--domain Set config domain"); + System.out.println("\t--dev Set config domain to dev"); + System.out.println("\t--config Merge in config file"); + System.out.println("\t--list List all attributes"); + System.out.println("\t--assign Assign an attribute"); + } + + public static void main(String... args) { + if (args.length == 0) { + usage(); + System.exit(1); + } + + mConfig = new Config(); + + try { + mConfig.updateConfig(AttributeTool.class.getResourceAsStream("/grow.properties")); + + int offset = 0; + while (offset < args.length) { + if ("--domain".equals(args[offset])) { + mConfig.setDomain(args[offset + 1]); + mF1API = null; + offset += 2; + + } else if ("--dev".equals(args[offset])) { + mConfig.setDomain("dev"); + mF1API = null; + offset += 1; + + } else if ("--config".equals(args[offset])) { + mConfig.updateConfig(args[offset + 1]); + mF1API = null; + offset += 2; + + } else if ("--list".equals(args[offset])) { + offset = list(args, ++offset); + + } else if ("--assign".equals(args[offset])) { + offset = assign(args, ++offset); + + } else { + throw new IllegalArgumentException("Unknown command " + args[offset]); + } + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(2); + } + } + + private static F1API getF1API() throws Exception { + if (mF1API == null) { + Context context = new Context(); + Client client = new Client(context, Arrays.asList(Protocol.HTTP, Protocol.HTTPS)); + context.setClientDispatcher(client); + + F1Access f1Access = new F1Access(context, + mConfig.getString("f1ConsumerKey"), + mConfig.getString("f1ConsumerSecret"), + mConfig.getString("f1BaseUrl"), + mConfig.getString("f1ChurchCode"), + F1Access.UserType.WEBLINK); + + // Gather Username and Password + String username = System.console().readLine("F1 Username: "); + char[] password = System.console().readPassword("F1 Password: "); + + OAuthUser user = f1Access.getAccessToken(username, new String(password)); + Arrays.fill(password, ' '); // Lost cause, but I'll still try. + + mF1API = f1Access.getAuthenticatedApi(user); + } + + return mF1API; + } + + private static int list(String[] args, int offset) throws Exception { + final F1API f1 = getF1API(); + + final Map attributes = f1.getAttributeList(); + System.out.printf("%7s %s\n", "ID", "Name"); + for (Map.Entry entry : attributes.entrySet()) { + System.out.printf("%7s %s\n", entry.getValue(), entry.getKey()); + } + + return offset; + } + + private static int assign(String[] args, int offset) throws Exception { + final String userId = args[offset++]; + final String attributeName = args[offset++]; + final String comment = args[offset++]; + + final F1API f1 = getF1API(); + + Attribute attribute = new Attribute(); + attribute.setStartDate(new Date()); + attribute.setComment(comment); + + if (f1.addAttribute(userId, attributeName, attribute)) { + System.out.println("Added attribute " + attributeName + " for " + userId); + } else { + System.out.println("Failed to add attribute " + attributeName + " for " + userId); + } + + return offset; + } +} -- cgit v1.2.3 From a5c349b8a1ec1cdfde396c42812e83c81aa31cb3 Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Sun, 21 Sep 2014 15:10:58 -0700 Subject: Removing comment. --- src/com/p4square/f1oauth/Attribute.java | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/com/p4square/f1oauth/Attribute.java b/src/com/p4square/f1oauth/Attribute.java index fa46d90..cc7cfc4 100644 --- a/src/com/p4square/f1oauth/Attribute.java +++ b/src/com/p4square/f1oauth/Attribute.java @@ -12,33 +12,6 @@ import java.util.Date; * @author Jesse Morgan */ public class Attribute { - /*Attribute - *{ - "attribute": { - "@id": "", - "@uri": "", - "person": { - "@id": "1636208", - "@uri": "https://demo.fellowshiponeapi.com/v1/People/1636208" - }, - "attributeGroup": { - "@id": "", - "@uri": "", - "name": null, - "attribute": { - "@id": "958", - "@uri": "", - "name": null - } - }, - "startDate": null, - "endDate": null, - "comment": null, - "createdDate": null, - "lastUpdatedDate": null - } - */ - private Date mStartDate; private Date mEndDate; private String mComment; -- cgit v1.2.3 From 3e703186928c5bd8f2c31f90b1c6e262c4080328 Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Sun, 21 Sep 2014 23:08:25 -0700 Subject: Assign Training Attribute on Chapter Complete. --- .../grow/frontend/ChapterCompletePage.java | 36 +++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/com/p4square/grow/frontend/ChapterCompletePage.java b/src/com/p4square/grow/frontend/ChapterCompletePage.java index b3896e9..a2c4ebe 100644 --- a/src/com/p4square/grow/frontend/ChapterCompletePage.java +++ b/src/com/p4square/grow/frontend/ChapterCompletePage.java @@ -4,6 +4,7 @@ package com.p4square.grow.frontend; +import java.util.Date; import java.util.Map; import freemarker.template.Template; @@ -22,10 +23,14 @@ import com.p4square.fmfacade.json.JsonRequestClient; import com.p4square.fmfacade.json.JsonResponse; import com.p4square.fmfacade.json.ClientException; +import com.p4square.f1oauth.Attribute; +import com.p4square.f1oauth.F1API; +import com.p4square.f1oauth.F1User; + import com.p4square.grow.config.Config; import com.p4square.grow.model.TrainingRecord; -import com.p4square.grow.provider.TrainingRecordProvider; import com.p4square.grow.provider.Provider; +import com.p4square.grow.provider.TrainingRecordProvider; /** * This resource displays the transitional page between chapters. @@ -93,6 +98,9 @@ public class ChapterCompletePage extends FreeMarkerPageResource { return new StringRepresentation("Redirecting to " + nextPage); } + // Publish the training chapter complete attribute. + assignAttribute(); + // Find the next chapter String nextChapter = null; { @@ -149,6 +157,32 @@ public class ChapterCompletePage extends FreeMarkerPageResource { } } + private void assignAttribute() { + if (!(getRequest().getClientInfo().getUser() instanceof F1User)) { + // Only useful if the user is from F1. + return; + } + + F1User user = (F1User) getRequest().getClientInfo().getUser(); + + // Update the attribute. + String attributeName = "Training Complete - " + mChapter; + + try { + Attribute attribute = new Attribute(); + attribute.setStartDate(new Date()); + + F1API f1 = mGrowFrontend.getF1Access().getAuthenticatedApi(user); + if (!f1.addAttribute(user.getIdentifier(), attributeName, attribute)) { + LOG.error("addAttribute failed for " + user.getIdentifier() + + " with attribute " + attributeName); + } + } catch (Exception e) { + LOG.error("addAttribute failed for " + user.getIdentifier() + + " with attribute " + attributeName, e); + } + } + /** * @return The backend endpoint URI */ -- cgit v1.2.3