diff options
Diffstat (limited to 'src/com/p4square/f1oauth')
-rw-r--r-- | src/com/p4square/f1oauth/Attribute.java | 87 | ||||
-rw-r--r-- | src/com/p4square/f1oauth/F1API.java | 44 | ||||
-rw-r--r-- | src/com/p4square/f1oauth/F1Access.java | 242 | ||||
-rw-r--r-- | src/com/p4square/f1oauth/F1Exception.java | 15 | ||||
-rw-r--r-- | src/com/p4square/f1oauth/SecondPartyVerifier.java | 23 |
5 files changed, 345 insertions, 66 deletions
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 <jesse@jesterpm.net> + */ +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 <jesse@jesterpm.net> + */ +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<String, String> 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<String, String> 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<Map> entity = new JacksonRepresentation<Map>(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<Map> entity = + new JacksonRepresentation<Map>(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<String, String> 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<Map> entity = + new JacksonRepresentation<Map>(response.getEntity(), Map.class); + + Map attributeGroups = (Map) entity.getObject().get("attributeGroups"); + List<Map> groups = (List<Map>) attributeGroups.get("attributeGroup"); + + for (Map group : groups) { + List<Map> attributes = (List<Map>) 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<Map> entity = + new JacksonRepresentation<Map>(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<String, String> 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<Map> entity = new JacksonRepresentation<Map>(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<Map>(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<String, String> 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<Map> entity = new JacksonRepresentation<Map>(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(); - } - } - } } |