package controllers; import controllers.compositions.AdminUserCheck; import controllers.compositions.UserCheck; import models.Lead; import models.ServerNode; import models.User; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.map.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import play.libs.Json; import play.mvc.Controller; import play.mvc.Result; import play.mvc.With; import server.ApplicationContext; import tyrex.services.UUID; import java.util.List; /** * Created with IntelliJ IDEA. * User: guym * Date: 8/20/13 * Time: 12:12 PM */ public class LeadsController extends Controller { private static Logger logger = LoggerFactory.getLogger(LeadsController.class); @With( UserCheck.class ) public static Result postLead( String userId , String authToken ){ User user = ( User) ctx().args.get("user"); JsonNode postLeadBody = request().body().asJson(); logger.info("postLeadBody = " + postLeadBody ); String email = (String) postLeadBody.get("email").asText(); Lead lead = Lead.findByOwnerAndEmail( user, email ); if ( lead == null ){ lead = new Lead(); lead.email = email; lead.owner = user; lead.uuid = UUID.create(); lead.confirmationCode = UUID.create().replaceAll("-", ""); lead.validated = false; lead.extra = postLeadBody.toString(); lead.save(); }else{ logger.info("lead [{}] already exists for user [{}], sending email again", email, user.toDebugString() ); } logger.info("sending registration mail to [{}]", lead.toDebugString() ); ApplicationContext.get().getMailSender().sendRegistrationMail( lead ); return ok(Json.toJson(lead)); } /** * * * This is a REST API call used by users to extend leads' widget timeout. * * Leads provide their email and get more trial time in return. * * Currently, we allow user A to extend time on widgets defined by user B. * We also allow to assign a single hacker to multiple widgets. * This is a potential security threat as a hacker can "snatch" widgets and keep assigning a dummy lead * to each widget, thus denying it from other leads. * * Currently we will do with a permissions definition for users that can assign leads to widgets. * This reduces the problems to users with this permission. * A wider resolution is required. * * * @param userId - the user's primary key * @param authToken - the user's authentication token * @param leadId - the lead's primary key * @param instanceId = the server node primary key * @return - success or error */ @With( UserCheck.class ) public static Result assignLeadToWidgetInstance( String userId, String authToken, Long leadId, Long instanceId ){ User user = (User) ctx().args.get("user"); logger.info(user.getPermissions().toString()); if ( !user.getPermissions().isCanAssignLeads() ){ logger.error("user {} tried to assign lead {} to instanceId {} but failed due to permissions", new Object[]{user.toDebugString(), leadId, instanceId}); return forbidden("You need permission to assign leads"); } ServerNode serverNode = ServerNode.find.byId( instanceId ); Lead lead = Lead.find.byId( leadId ); if ( lead == null || !lead.owner.getId().equals( user.getId() )){ // whether lead does not exist return notFound("no lead with id " + leadId ); } // lets verify serverNode exists and is not assigned to another lead already. // if it is assigned to another lead, we want to give the same message as if the server node // does not exist. if ( serverNode == null || ( serverNode.getLead() != null && !serverNode.getLead().getId().equals(lead.getId()))){ // whether serverNode already assigned or does not exist return notFound("instanceId " + instanceId + " does not exist"); }else if ( lead.getServerId() != null && !lead.getServerId().equals(serverNode.getId()) ){ // whether lead already assigned return notFound("invalid params"); } else if ( serverNode.getLead() == null && lead.getServerId() == null ){ serverNode.setLead( lead ); serverNode.save(); return ok("assigned"); }else if ( serverNode.getLead() != null && serverNode.getLead().getId().equals( lead.getId() )){ return ok("already assigned"); } return ok("nothing to do"); } @With( UserCheck.class ) public static Result confirmEmail( String userId, String authToken, Long leadId, String confirmationCode ){ User user = (User) ctx().args.get("user"); Lead lead = Lead.findByOwnerIdAndConfirmationCode( user, leadId, confirmationCode); if ( lead == null ){ return notFound("no such lead"); }else{ lead.validated = true; lead.save(); return ok( Json.toJson(lead)); } } @With( UserCheck.class ) public static Result getLead( String userId, String authToken, String email ){ User user = (User) ctx().args.get("user"); Lead lead = Lead.findByOwnerAndEmail( user, email ); return ok( Json.toJson(lead)); } @With( AdminUserCheck.class ) public static Result getAdminLeads( String userId, String authToken ){ List<Lead> leads = Lead.find.all(); ObjectMapper mapper = new ObjectMapper(); mapper.getSerializationConfig().addMixInAnnotations( Lead.class , LeadUserMixin.class ); return ok( mapper.valueToTree( leads ) ); } public static class LeadUserMixin{ @JsonProperty public User owner; } @With( UserCheck.class ) public static Result getLeads( String userId, String authToken ){ User user = ( User ) ctx().args.get("user"); List<Lead> leads = Lead.findAllByOwner( user ); return ok( Json.toJson( leads ) ); } }