package com.github.windbender.resources;
import java.net.URI;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.windbender.auth.Priv;
import com.github.windbender.auth.SessionAuth;
import com.github.windbender.auth.SessionCurProj;
import com.github.windbender.auth.SessionUser;
import com.github.windbender.core.JoinProjectRequest;
import com.github.windbender.core.SessionFilteredAuthorization;
import com.github.windbender.dao.InviteDAO;
import com.github.windbender.dao.ProjectDAO;
import com.github.windbender.dao.UserDAO;
import com.github.windbender.dao.UserProjectDAO;
import com.github.windbender.domain.Camera;
import com.github.windbender.domain.Invite;
import com.github.windbender.domain.Project;
import com.github.windbender.domain.User;
import com.github.windbender.domain.UserProject;
import com.github.windbender.service.EmailService;
import com.yammer.dropwizard.hibernate.UnitOfWork;
import com.yammer.metrics.annotation.Timed;
@Path("/projects/")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ProjectResource {
private static final int MAX_ADMIN = 20;
Logger log = LoggerFactory.getLogger(ProjectResource.class);
private ProjectDAO projectDAO;
private UserDAO userDAO;
private UserProjectDAO upDAO;
private InviteDAO inviteDAO;
private EmailService emailService;
public ProjectResource(ProjectDAO projectDAO,UserDAO userDAO,UserProjectDAO upDAO, InviteDAO inviteDAO, EmailService emailService) {
super();
this.projectDAO = projectDAO;
this.userDAO = userDAO;
this.upDAO = upDAO;
this.inviteDAO = inviteDAO;
this.emailService = emailService;
}
@GET
@Timed
@UnitOfWork
public List<String> list(@SessionUser User user) {
List<Project> list = projectDAO.findAll();
List<String> listNames = new ArrayList<String>();
for(Project p :list) {
String n = p.getName();
listNames.add(n);
}
return listNames;
}
@GET
@Timed
@UnitOfWork
@Path("invites")
public List<Invite> listInvites(@SessionAuth(required={Priv.ADMIN}) SessionFilteredAuthorization auths,@Context HttpServletRequest request,@SessionUser User user,@SessionCurProj Project currentProject) {
Project p = this.projectDAO.findById(currentProject.getId());
List<Invite> list = this.inviteDAO.findAllByProject(p);
return list;
}
@GET
@Timed
@UnitOfWork
@Path("cameras")
public List<Camera> listCameras(@SessionAuth(required={Priv.UPLOAD}) SessionFilteredAuthorization auths,@Context HttpServletRequest request,@SessionUser User user) {
Project cp = (Project) request.getSession().getAttribute("current_project");
Project p = projectDAO.findById(cp.getId());
Set<Camera> s = p.getCameras();
List<Camera> l = new ArrayList<Camera>(s);
return l;
}
@GET
@Timed
@UnitOfWork
@Path("{id}")
public Project fetch(@SessionAuth(required = { Priv.ADMIN }) SessionFilteredAuthorization auths,
@SessionUser User user, @SessionCurProj Project currentProject,
@PathParam("id") Long projectId) {
Project p = projectDAO.findById(projectId);
return p;
}
@PUT
@Timed
@Path("{id}")
@UnitOfWork
public Response update(
@SessionAuth(required = { Priv.ADMIN }) SessionFilteredAuthorization auths,
@SessionUser User user, @SessionCurProj Project currentProject,
@PathParam("id") Long id, @Valid Project project) {
Project p = projectDAO.findById(id);
if (p == null)
throw new WebApplicationException(Response.Status.FORBIDDEN);
if (!p.getId().equals(project.getId()))
throw new WebApplicationException(Response.Status.FORBIDDEN);
if(!p.getPrimaryAdmin().getId().equals(user.getId())) throw new WebApplicationException(Response.Status.FORBIDDEN);
project.setPrimaryAdmin(user);
Project newProject = projectDAO.save(project);
//
URI uri = UriBuilder.fromResource(ProjectResource.class).build(
newProject.getId());
log.info("the response uri will be " + uri);
return Response.created(uri).build();
}
@DELETE
@Timed
@Path("{id}")
@Consumes(MediaType.TEXT_PLAIN)
@UnitOfWork
public Response delete(
@SessionAuth(required = { Priv.ADMIN }) SessionFilteredAuthorization auths,
@SessionUser User user, @SessionCurProj Project currentProject,
@PathParam("id") Long id) {
Project deleteableProject = projectDAO.findById(id);
if(deleteableProject == null) throw new WebApplicationException(Response.Status.FORBIDDEN);
projectDAO.delete(id);
return Response.ok().build();
}
@GET
@Timed
@UnitOfWork
@Path("accept")
public Response accept( @QueryParam("code") String code) {
log.info("redeeming invite code "+code);
Invite i = this.inviteDAO.findByCode(code);
Map<String,String> m = new HashMap<String,String>();
m.put("email",i.getEmail());
m.put("projectName", i.getProject().getName());
m.put("projectDesc", i.getProject().getName());
m.put("fromUser",i.getInviter().getUsername());
m.put("fromUserEmail",i.getInviter().getEmail());
return Response.ok(m).build();
}
@POST
@Timed
@UnitOfWork
@Path("deleteInvite")
public Response deleteInvite( @SessionUser User user, @SessionCurProj Project currentProject, String inviteId) {
int invite_id = Integer.parseInt(inviteId);
Invite i = this.inviteDAO.findByById(invite_id);
this.inviteDAO.delete(i);
return Response.ok().build();
}
@POST
@Timed
@UnitOfWork
@Path("invite")
public Response invite( @SessionUser User user, @SessionCurProj Project currentProject, Map<String,String> m) {
try {
String inviteEmail = m.get("email");
Invite i = new Invite();
i.setInviter(user);
i.setProject(currentProject);
String inviteCode = UserResource.makeVerifyCode();
i.setInviteCode(inviteCode);
i.setInviteCodeSentDate(new DateTime());
i.setUserCreated(false);
i.setEmail(inviteEmail);
i.setCanAdmin(Boolean.parseBoolean(m.get("canAdmin")));
i.setCanUpload(Boolean.parseBoolean(m.get("canUpload")));
i.setCanCategorize(Boolean.parseBoolean(m.get("canCategorize")));
i.setCanReport(Boolean.parseBoolean(m.get("canReport")));
emailService.sendInviteEmail(user,inviteEmail,inviteCode,currentProject);
this.inviteDAO.save(i);
return Response.ok().build();
} catch( MessagingException | NoSuchAlgorithmException e) {
throw new WebApplicationException(e);
}
}
@POST
@Timed
@UnitOfWork
public Response add(
@SessionUser User user, @SessionCurProj Project currentProject,
@Valid Project project) {
log.info("Ok we have the following session user " + user);
project.setPrimaryAdmin(user);
Project newProject = projectDAO.save(project);
URI uri = UriBuilder.fromResource(ProjectResource.class).build(
newProject.getId());
log.info("the response uri will be " + uri);
return Response.created(uri).build();
}
// @POST
// @Timed
// @UnitOfWork
// @Consumes(MediaType.APPLICATION_JSON)
// @Produces(MediaType.APPLICATION_JSON)
// public Response createProject(@SessionUser User user,CreateProjectRequest request) {
// log.info("GOT an new project "+request);
// if(request.getProjectName() == null) throw new IllegalArgumentException("sorry, the name cannot be null");
// // verify the name is not already taken!!
// Project pOld = this.projectDAO.findByName(request.getProjectName());
// if(pOld != null) {
// throw new ConflictException("Sorry that project name is already taken");
// }
// // verify the name is not offensive since everyone will see it.
////TODO something here about offensive words
// // verify the user doesn't have the limit of primary admins already. 20 ?
// List<Project> allUserProjects = this.projectDAO.findByPrimaryAdmin(user);
// if(allUserProjects.size() > MAX_ADMIN) {
// throw new ConflictException("Sorry you have reached the limit on the number of projects you can create");
// }
// // create the project.
// Project p = new Project();
// p.setName(request.getProjectName());
// p.setDescription(request.getProjectDescription());
// // set the primary admin to the user.
// p.setPrimaryAdmin(user);
// // and save
// this.projectDAO.save(p);
//
// return Response.ok().build();
// }
@POST
@Timed
@UnitOfWork
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("join")
public Response joinProject(@SessionUser User user,JoinProjectRequest request) {
log.info("GOT an new project "+request);
//TODO setup a permissions sort of things.
String name = request.getSelectedProject();
Project p = this.projectDAO.findByName(name);
if(p != null) {
UserProject up = new UserProject();
User u = this.userDAO.findById(user.getId());
up.setProject(p);
up.setUser(u);
this.upDAO.save(up);
} else {
}
return Response.ok().build();
}
}