package org.fluxtream.core.api;
import com.google.gson.Gson;
import com.wordnik.swagger.annotations.*;
import net.sf.json.JSONObject;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.fluxtream.core.Configuration;
import org.fluxtream.core.auth.AuthHelper;
import org.fluxtream.core.auth.TrustRelationshipRevokedException;
import org.fluxtream.core.connectors.Connector;
import org.fluxtream.core.domain.ApiKey;
import org.fluxtream.core.domain.TrustedBuddy;
import org.fluxtream.core.domain.Guest;
import org.fluxtream.core.mvc.models.AvatarImageModel;
import org.fluxtream.core.mvc.models.guest.GuestModel;
import org.fluxtream.core.services.BuddiesService;
import org.fluxtream.core.services.GuestService;
import org.fluxtream.core.utils.HttpUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static org.fluxtream.core.utils.Utils.hash;
@Path("/v1/guest")
@Component("RESTGuestController")
@Api(value = "/guest", description = "Retrieve guest information")
@Scope("request")
public class GuestController {
@Autowired
GuestService guestService;
Gson gson = new Gson();
@Autowired
Configuration env;
@Autowired
BuddiesService buddiesService;
@GET
@Path("/")
@Produces({ MediaType.APPLICATION_JSON })
@ApiResponses({
@ApiResponse(code=401, message="The user is no longer logged in"),
@ApiResponse(code=403, message="Buddy-to-access authorization has been revoked")
})
@ApiOperation(value = "Retrieve information on the currently logged in's guest", response = GuestModel.class)
public Response getCurrentGuest(@ApiParam(value="Include the guest's avatar?") @QueryParam("includeAvatar") final boolean includeAvatar,
@ApiParam(value="Buddy to access username parameter (" + BuddiesService.BUDDY_TO_ACCESS_PARAM + ")", required=false) @QueryParam(BuddiesService.BUDDY_TO_ACCESS_PARAM) String buddyToAccessParameter) throws InstantiationException,
IllegalAccessException, ClassNotFoundException {
try{
TrustedBuddy trustedBuddy;
try { trustedBuddy = AuthHelper.getBuddyTrustedBuddy(buddyToAccessParameter, buddiesService);
} catch (TrustRelationshipRevokedException e) {return Response.status(403).entity("Sorry, permission to access this data has been revoked. Please reload your browser window").build();}
Guest guest = ApiHelper.getBuddyToAccess(guestService, trustedBuddy);
if (guest==null)
return Response.status(401).entity("You are no longer logged in").build();
GuestModel guestModel = new GuestModel(guest, trustedBuddy !=null);
if (includeAvatar)
guestModel.avatar = getAvatarImageModel(buddyToAccessParameter, guest);
return Response.ok(guestModel).build();
}
catch (Exception e){
return Response.serverError().entity("Failed to get current guest: " + e.getMessage()).build();
}
}
@GET
@Path("/trusted")
@Produces({ MediaType.APPLICATION_JSON })
@ApiResponses({
@ApiResponse(code=401, message="The user is no longer logged in"),
@ApiResponse(code=403, message="Buddy-to-access authorization has been revoked")
})
@ApiOperation(value = "Retrieve information on a user's trusted buddy", response = GuestModel.class)
public Response getOwnTrustedBuddy(@ApiParam(value="Include the guest's avatar?") @QueryParam("includeAvatar") final boolean includeAvatar,
@ApiParam(value="Buddy to access guest id ", required=true) @QueryParam(BuddiesService.BUDDY_TO_ACCESS_PARAM) String buddyToAccessParameter) throws InstantiationException,
IllegalAccessException, ClassNotFoundException {
try{
try {
TrustedBuddy trustedBuddy = AuthHelper.getOwnTrustedBuddy(buddyToAccessParameter, buddiesService);
Guest guest = guestService.getGuestById(trustedBuddy.buddyId);
GuestModel guestModel = new GuestModel(guest, true);
if (includeAvatar)
guestModel.avatar = getAvatarImageModel(buddyToAccessParameter, guest);
return Response.ok(guestModel).build();
} catch (TrustRelationshipRevokedException e) {
return Response.status(403).entity("Sorry, permission to access this data has been revoked. Please reload your browser window").build();
}
}
catch (Exception e){
return Response.serverError().entity("Failed to get current guest: " + e.getMessage()).build();
}
}
@GET
@Path("/avatarImage")
@Produces({MediaType.APPLICATION_JSON})
@ApiResponses({
@ApiResponse(code=401, message="The user is no longer logged in"),
@ApiResponse(code=403, message="Buddy-to-access authorization has been revoked")
})
@ApiOperation(value = "Retrieve the avatar (gravatar) of the currently logged in's guest", response = AvatarImageModel.class)
public Response getAvatarImage(@ApiParam(value="Buddy to access username parameter (" + BuddiesService.BUDDY_TO_ACCESS_PARAM + ")", required=false) @QueryParam(BuddiesService.BUDDY_TO_ACCESS_PARAM) String buddyToAccessParameter) {
Guest guest = AuthHelper.getGuest();
AvatarImageModel avatarImage = getAvatarImageModel(buddyToAccessParameter, guest);
return Response.ok(avatarImage).build();
}
private AvatarImageModel getAvatarImageModel(String buddyToAccessParameter, Guest guest) {
AvatarImageModel avatarImage = new AvatarImageModel();
String type = "none";
String url;
try {
final TrustedBuddy trustedBuddy = AuthHelper.getBuddyTrustedBuddy(buddyToAccessParameter, buddiesService);
if (trustedBuddy !=null)
guest = guestService.getGuestById(trustedBuddy.guestId);
}
catch (TrustRelationshipRevokedException e) {}
if (guest.registrationMethod == Guest.RegistrationMethod.REGISTRATION_METHOD_FACEBOOK||
guest.registrationMethod == Guest.RegistrationMethod.REGISTRATION_METHOD_FACEBOOK_WITH_PASSWORD) {
url = getFacebookAvatarImageURL(guest);
if (url!=null)
type = "facebook";
} else {
url = getGravatarImageURL(guest);
if (url!=null)
type = "gravatar";
}
avatarImage.type = type;
avatarImage.url = url;
return avatarImage;
}
private String getGravatarImageURL(Guest guest) {
String emailHash = hash(guest.email.toLowerCase().trim()); //gravatar specifies the email should be trimmed, taken to lowercase, and then MD5 hashed
String gravatarURL = String.format("http://www.gravatar.com/avatar/%s?s=27&d=retro", emailHash);
HttpGet get = new HttpGet(gravatarURL);
int res = 0;
try { res = ((new DefaultHttpClient()).execute(get)).getStatusLine().getStatusCode(); }
catch (IOException e) {e.printStackTrace();}
return res==200 ? gravatarURL : null;
}
public String getFacebookAvatarImageURL(Guest guest) {
final ApiKey facebook = guestService.getApiKey(guest.getId(), Connector.getConnector("facebook"));
final String meString = guestService.getApiKeyAttribute(facebook, "me");
JSONObject meJSON = JSONObject.fromObject(meString);
final String facebookId = meJSON.getString("id");
try {
String avatarURL = String.format("http://graph.facebook.com/%s/picture?type=small&redirect=false&return_ssl_resources=true", facebookId);
String jsonString = HttpUtils.fetch(avatarURL);
JSONObject json = JSONObject.fromObject(jsonString);
if (json.has("data")) {
json = json.getJSONObject("data");
if (json.has("url")&&json.has("is_silhouette")) {
if (!json.getBoolean("is_silhouette")) {
return json.getString("url");
}
}
}
} catch (Throwable t){
t.printStackTrace();
}
return null;
}
@GET
@Path("/trustingBuddies")
@Produces({MediaType.APPLICATION_JSON})
@ApiOperation(value = "Retrieve the currently logged in guest's list of trustingBuddies", responseContainer = "Array",
response = GuestModel.class)
public List<GuestModel> getTrustingBuddies() {
Guest guest = AuthHelper.getGuest();
final List<Guest> trustingBuddies = buddiesService.getTrustedBuddies(guest.getId());
final List<GuestModel> trustingBuddyModels = new ArrayList<GuestModel>();
for (Guest trustingBuddy : trustingBuddies)
trustingBuddyModels.add(new GuestModel(trustingBuddy, true));
return trustingBuddyModels;
}
}