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(); -            } -        } -    }  }  | 
