Commit a62bd764 by Tuukka Kivilahti

Merge branch 'feature/vectorama2015-restapi' into 'master'

Vectorama2015 REST API - Registration kiosks

Required to get registration kiosks going

See merge request !287
2 parents a84b600b ae3b0ab6
......@@ -15,3 +15,4 @@
moya-git.properties
*/*/bin
pom.xml.versionsBackup
.idea/
\ No newline at end of file
......@@ -96,7 +96,6 @@ import fi.codecrew.moya.utilities.PasswordFunctions;
import fi.codecrew.moya.utilities.SearchQuery;
import fi.codecrew.moya.utilities.SearchResult;
import fi.codecrew.moya.utilities.moyamessage.MoyaEventType;
import scala.tools.cmd.Spec;
@LocalBean
@Stateless
......@@ -268,13 +267,13 @@ public class UserBean implements UserBeanLocal {
return checkedRoles;
}
private static void addRecursive(Set<Role> checkedRoles, Collection<Role> roles) {
private void addRecursive(Set<Role> checkedRoles, Collection<Role> roles) {
for (Role r : roles) {
addRecursive(checkedRoles, r);
}
}
private static void addRecursive(Set<Role> checkedRoles, Role role) {
private void addRecursive(Set<Role> checkedRoles, Role role) {
if (role == null || checkedRoles.contains(role)) {
return;
}
......
......@@ -138,14 +138,36 @@
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jaxrs_2.11</artifactId>
<artifactId>swagger-jersey2-jaxrs_2.11</artifactId>
<version>${swagger.version}</version>
<exclusions>
<exclusion>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-servlet_2.11</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.17</version>
<scope>provided</scope>
</dependency>
</dependencies>
<parent>
......
......@@ -38,8 +38,6 @@ public class EventUserRestPojo {
public EventUserRestPojo() {
}
@XmlElement()
@ApiModelProperty("Nickname")
public String getNick() {
......
......@@ -13,43 +13,54 @@
<ui:define name="title">
<h1>#{i18n['user.edit.title']}</h1>
</ui:define>
<ui:define name="content">
<ui:define name="content">
<h:form>
<p:toolbar>
<f:facet name="left">
<h:outputText value="#{userCartView.current+1}" /> / <h:outputText value="#{userCartView.userCartSize}" />
<h:commandButton action="#{userCartView.prev()}" value="#{i18n['usercart.prev']}" rendered="#{userCartView.current > 0}" />
<h:commandButton action="#{userCartView.removeCurrent()}" value="#{i18n['usercart.removeCurrent']}" />
<h:commandButton action="#{userCartView.next()}" value="#{i18n['usercart.next']}" rendered="#{userCartView.userCartSize > (userCartView.current+1)}" />
<span class="ui-separator"><span class="ui-icon ui-icon-grip-dotted-vertical" /></span>
<p:commandButton action="#{userCartView.prev()}" value="#{i18n['usercart.prev']}"
icon="ui-icon-circle-arrow-w" ajax="false"
rendered="#{userCartView.current > 0}" />
<p:commandButton action="#{userCartView.removeCurrent()}" value="#{i18n['usercart.removeCurrent']}"
icon="ui-icon-close" ajax="false"/>
<p:commandButton action="#{userCartView.next()}" value="#{i18n['usercart.next']}"
icon="ui-icon-circle-arrow-e" ajax="false"
rendered="#{userCartView.userCartSize > (userCartView.current+1)}" />
</f:facet>
</p:toolbar>
</h:form>
<ui:fragment rendered="#{userView.hasPrintedCard}">
<h2>Card</h2>
<h:form>
<p:panelGrid columns="2">
<h:outputText value="#{i18n[card.name]}" />
<h:outputText value="#{i18n['printedCard.template']}" />
<h:outputText value="#{userView.printedCard.template.name}" />
<h:selectOneMenu value="#{userView.printedCard.cardState}">
<h:outputText value="#{i18n['printedCard.cardState']}"/>
<p:selectOneButton value="#{userView.printedCard.cardState}"
valueChangeListener="#{userView.cardStateChangeListener}">
<f:selectItems value="#{userView.printedCardStates}" />
</h:selectOneMenu>
<h:commandButton action="#{userView.setCardState()}" value="#{i18n['printedCard.setState']}" />
<f:ajax/>
</p:selectOneButton>
</p:panelGrid>
</h:form>
</ui:fragment>
<p>
<h:link outcome="/card/massprint" value="Mass Print">
<f:param name="cid" value="#{javax.enterprise.context.conversation.id}" />
</h:link>
</p>
<p>
<h:link outcome="/useradmin/changePassword" value="#{i18n['submenu.user.changePassword']}">
<f:param name="userid" value="#{userView.user.user.id}" />
</h:link>
</p>
<users:edit id="useredit" commitaction="#{userCartView.saveUser()}" commitvalue="#{i18n['user.save']}" />
<h:form id="roleform" rendered="#{roleView.canReadRoles}">
......
......@@ -43,6 +43,18 @@
<artifactId>moya-restpojo</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.16</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.16</version>
<scope>provided</scope>
</dependency>
</dependencies>
......
......@@ -18,12 +18,52 @@
*/
package fi.codecrew.moya.rest;
import com.wordnik.swagger.config.ScannerFactory;
import com.wordnik.swagger.jaxrs.config.BeanConfig;
import com.wordnik.swagger.jaxrs.config.ReflectiveJaxrsScanner;
import com.wordnik.swagger.jaxrs.reader.DefaultJaxrsApiReader;
import com.wordnik.swagger.jersey.JerseyApiReader;
import com.wordnik.swagger.jersey.listing.ApiListingResourceJSON;
import com.wordnik.swagger.jersey.listing.JerseyApiDeclarationProvider;
import com.wordnik.swagger.jersey.listing.JerseyResourceListingProvider;
import com.wordnik.swagger.reader.ClassReaders;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath(RestApplicationEntrypoint.REST_PATH)
public class RestApplicationEntrypoint extends Application {
public class RestApplicationEntrypoint extends ResourceConfig {
public static final String REST_PATH = "/rest";
private static final String BASE_URL = "/MoyaWeb";
private static final String API_RESOURCE_PACKAGE = "fi.codecrew.moya.rest";
public RestApplicationEntrypoint() {
// swagger
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.0");
beanConfig.setBasePath(BASE_URL + REST_PATH);
beanConfig.setResourcePackage(API_RESOURCE_PACKAGE);
beanConfig.setScan(true);
register(beanConfig);
//ReflectiveJaxrsScanner scanner = new ReflectiveJaxrsScanner();
//scanner.setResourcePackage(API_RESOURCE_PACKAGE);
//ScannerFactory.setScanner(scanner);
//ClassReaders.setReader(new JerseyApiReader());
//ClassReaders.setReader(new DefaultJaxrsApiReader());
register(ApiListingResourceJSON.class);
register(JerseyApiDeclarationProvider.class);
register(JerseyResourceListingProvider.class);
// mime multipart image uploads
register(MultiPartFeature.class);
// packages to scan
packages("com.wordnik.swagger.jaxrs.json", "fi.codecrew.moya.rest");
}
}
......@@ -37,6 +37,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import fi.codecrew.moya.beans.*;
import fi.codecrew.moya.enums.apps.UserPermission;
import fi.codecrew.moya.model.*;
import org.slf4j.Logger;
......@@ -46,14 +47,6 @@ import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
import fi.codecrew.moya.beans.CardTemplateBeanLocal;
import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.beans.PlaceGroupBeanLocal;
import fi.codecrew.moya.beans.ReaderBeanLocal;
import fi.codecrew.moya.beans.TicketBeanLocal;
import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.rest.pojo.userinfo.v1.EventUserRestPojo;
import fi.codecrew.moya.rest.pojo.userinfo.v1.PrintedCardRestPojo;
import fi.codecrew.moya.rest.pojo.userinfo.v1.SimpleEventuserRoot;
......@@ -270,21 +263,6 @@ public class UserRestView {
return new EventUserRestPojo();
}
@POST
@Path("/create")
@Produces({ MediaType.APPLICATION_JSON })
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@ApiOperation(value = "Create user", response = EventUserRestPojo.class)
public Response createEventUser() {
if (permbean.hasPermission(UserPermission.CREATE_NEW) == false) {
return Response.status(Status.FORBIDDEN).build();
}
return Response.status(Status.NOT_IMPLEMENTED).build();
}
@GET
@Path("/")
@Produces({ MediaType.APPLICATION_JSON })
......
......@@ -24,7 +24,7 @@ import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.beans.QueueBeanLocal;
import fi.codecrew.moya.beans.map.QueueBeanLocal;
import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser;
......
package fi.codecrew.moya.rest.v2;
import fi.codecrew.moya.enums.Gender;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.User;
import fi.codecrew.moya.rest.v2.pojo.UserPojo;
import java.io.Serializable;
/**
* Created by jkj on 2015-05-31.
*/
public class PojoFactoryV2 implements Serializable {
public UserPojo createUserPojo(EventUser eventUser) {
User user = eventUser.getUser();
UserPojo pojo = new UserPojo();
pojo.eventuserId = eventUser.getId();
pojo.userId = user.getId();
pojo.nick = user.getNick();
pojo.login = user.getLogin();
pojo.firstname = user.getFirstnames();
pojo.lastname = user.getLastname();
pojo.birthday = user.getBirthday();
if (user.getGender() == Gender.MALE) {
pojo.gender = UserPojo.UserGender.MALE;
} else if (user.getGender() == Gender.FEMALE) {
pojo.gender = UserPojo.UserGender.FEMALE;
} else {
pojo.gender = UserPojo.UserGender.UNSPECIFIED;
}
pojo.phoneNumber = user.getPhone();
pojo.streetAddress = user.getAddress();
pojo.zipCode = user.getZip();
pojo.postOffice = user.getTown();
return pojo;
}
}
package fi.codecrew.moya.rest.v2;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.enums.Gender;
import fi.codecrew.moya.enums.apps.UserPermission;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.User;
import fi.codecrew.moya.model.UserImage;
import fi.codecrew.moya.rest.PojoUtils;
import fi.codecrew.moya.rest.pojo.userinfo.v1.EventUserRestPojo;
import fi.codecrew.moya.rest.v2.pojo.UserPojo;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
@RequestScoped
@Path("/v2/user")
@Api(value = "/v2/user", description = "User operations")
public class UserRestViewV2 {
private static final Logger logger = LoggerFactory.getLogger(UserRestViewV2.class);
@EJB
EventBeanLocal eventBean;
@EJB
PermissionBeanLocal permissionBean;
@EJB
UserBeanLocal userBean;
@Inject
PojoFactoryV2 pojoFactory;
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Find user", response = UserPojo.class)
public Response getEventUser(@QueryParam("email") @ApiParam("Email address") String email,
@QueryParam("login") @ApiParam("Username") String userName) {
try {
if (permissionBean.hasPermission(UserPermission.VIEW_ALL) == false) {
return Response.status(Response.Status.FORBIDDEN).build();
}
// If username not given, try to find username by email
if (userName == null || userName.isEmpty()) {
userName = userBean.findUsernameByEmailUsername(email);
}
// Get the user
EventUser eventUser = userBean.findEventuserByLogin(userName);
if (eventUser == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
// Return the EventUser
return Response.ok(pojoFactory.createUserPojo(eventUser)).build();
} catch (Exception e) {
logger.error("Finding event user failed", e);
return Response.serverError().build();
}
}
@POST
@Path("/create")
@Produces({ MediaType.APPLICATION_JSON })
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Create user", response = UserPojo.class)
public Response createUser(UserPojo userPojo) {
if (permissionBean.hasPermission(UserPermission.CREATE_NEW) == false) {
return Response.status(Response.Status.FORBIDDEN).build();
}
try {
EventUser eventUser = new EventUser(new User(), eventBean.getCurrentEvent(), permissionBean.getCurrentUser());
eventUser.setNick(userPojo.nick);
eventUser.setLogin(userPojo.login);
eventUser.setFirstnames(userPojo.firstname);
eventUser.setLastname(userPojo.lastname);
eventUser.setBirthday(userPojo.birthday);
if (userPojo.gender == UserPojo.UserGender.MALE) {
eventUser.setGender(Gender.MALE);
} else if (userPojo.gender == UserPojo.UserGender.FEMALE) {
eventUser.setGender(Gender.FEMALE);
} else {
eventUser.setGender(Gender.UNDEFINED);
}
eventUser.setPhone(userPojo.phoneNumber);
eventUser.setEmail(userPojo.email);
eventUser.setAddress(userPojo.streetAddress);
eventUser.setZip(userPojo.zipCode);
eventUser.setTown(userPojo.postOffice);
userBean.createNewUser(eventUser, userPojo.password);
return Response.ok(pojoFactory.createUserPojo(eventUser)).build();
} catch(Exception e) {
logger.error("Creating user failed", e);
return Response.serverError().entity(PojoUtils.initErrorPojo(e.getMessage())).build();
}
}
/**
* Post forma parameter "image" with the image data in it.
* @param request
* @param userId
* @return
* @throws IOException
*/
@PUT
@Path("/{userid}/image")
@ApiOperation(value = "Upload image", response = EventUserRestPojo.class)
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response updateUserImage(@Context HttpServletRequest request,
@PathParam("userid") @ApiParam("User ID") Integer userId,
@FormDataParam("image") FormDataContentDisposition imageInfo,
@FormDataParam("image") InputStream imageStream,
@FormDataParam("image") FormDataBodyPart body) {
logger.info("Starting to upload new user image for user {}", userId);
try {
if (permissionBean.hasPermission(UserPermission.MODIFY) == false || permissionBean.hasPermission(UserPermission.VIEW_ALL) == false) {
return Response.status(Response.Status.FORBIDDEN).build();
}
EventUser eventUser = userBean.findByUserId(userId, true);
logger.info("Mimetype: " + body.getMediaType());
userBean.uploadImage(eventUser, body.getMediaType().getType(), imageStream, imageInfo.getFileName(), null);
logger.info("Image uploaded");
return Response.ok(pojoFactory.createUserPojo(eventUser)).build();
} catch (Exception e) {
logger.error("Image upload failed", e);
return Response.serverError().entity(PojoUtils.initErrorPojo("Image upload failed")).build();
}
}
/**
* Get user image
* @param userId
* @return
*/
@GET
@Path("/{userid}/image")
@ApiOperation(value = "Download user image")
//@Consumes()
//@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
//@Produces({MediaType.APPLICATION_JSON, "image/png", "image/jpeg"})
//@Produces({MediaType.MULTIPART_FORM_DATA, "image/png", "image/jpeg"})
public Response downloadUserImage(@PathParam("userid") @ApiParam("User ID") Integer userId) {
try {
User user = userBean.getUser(userId);
UserImage image = user.getCurrentImage();
//logger.info("Mimetype: " + body.getMediaType());
return Response.ok(image.getImageData(), image.getMimeType()).build();
} catch(Exception e) {
logger.error("Getting image failed", e);
return Response.serverError().entity(PojoUtils.initErrorPojo(e.getMessage())).build();
}
}
@POST
@Path("/{userid}/check-password")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@ApiOperation(value = "Check user password", response = UserPojo.class)
public Response checkPassword(@PathParam("userid") @ApiParam("User ID") Integer userId,
@FormParam("password") @ApiParam("Password") String password) {
try {
if (permissionBean.hasPermission(UserPermission.VIEW_ALL) == false) {
return Response.status(Response.Status.FORBIDDEN).build();
}
EventUser user = userBean.findByUserId(userId, true);
if (user == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
//boolean passwordOk = user.checkPassword(password);
boolean passwordOk = userBean.checkPassword(user, password);
if (passwordOk) {
return Response.ok(pojoFactory.createUserPojo(user), MediaType.APPLICATION_JSON_TYPE).build();
}
return Response.status(Response.Status.UNAUTHORIZED).entity(PojoUtils.initErrorPojo("Wrong password")).build();
} catch (Exception e) {
logger.error("Checking user authentication failed", e);
return Response.serverError().entity(PojoUtils.initErrorPojo("Checking password failed")).build();
}
}
}
package fi.codecrew.moya.rest.v2.pojo;
import com.wordnik.swagger.annotations.ApiModel;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.Date;
/**
* Created by jkj on 2015-05-31.
*/
@XmlRootElement()
@ApiModel(description = "User")
public class UserPojo {
public enum UserGender {
MALE,
FEMALE,
UNSPECIFIED
}
public String nick = "";
public String login = "";
public Integer eventuserId = 0;
public Integer userId = 0;
public String firstname = "";
public String lastname = "";
public String password = "";
// foo..
public Date birthday;
public UserGender gender;
public String phoneNumber;
public String email;
// address info
public String streetAddress;
public String zipCode;
public String postOffice;
}
package fi.codecrew.moya.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.wordnik.swagger.config.ConfigFactory;
import com.wordnik.swagger.config.ScannerFactory;
import com.wordnik.swagger.config.SwaggerConfig;
import com.wordnik.swagger.jaxrs.config.ReflectiveJaxrsScanner;
import com.wordnik.swagger.jaxrs.reader.DefaultJaxrsApiReader;
import com.wordnik.swagger.reader.ClassReaders;
import fi.codecrew.moya.rest.RestApplicationEntrypoint;
@WebServlet(name = "SwaggerJaxrsConfig", loadOnStartup = 1, description = "Configure Swaggered API documentation")
public class SwaggerJaxrsConfig extends HttpServlet {
private static final long serialVersionUID = 35868122371671912L;
private static final Logger log = LoggerFactory.getLogger(SwaggerJaxrsConfig.class);
private static final String BASE_URL = "/MoyaWeb";
private static final String API_RESOURCE_PACKAGE = "fi.codecrew.moya.rest";
@Override
public void init() throws ServletException {
log.info("Initializing Swagger configuration servlet");
try {
// Configure basic API settings shown in API doc JSON.
SwaggerConfig swaggerConfig = new SwaggerConfig();
swaggerConfig.setBasePath(BASE_URL + RestApplicationEntrypoint.REST_PATH);
swaggerConfig.setApiVersion("1.0.0");
ConfigFactory.setConfig(swaggerConfig);
// Configure scanning for API annotations in desired packaget
// ServletScanner scanner = new ServletScanner();
// scanner.setResourcePackage(API_RESOURCE_PACKAGE);
// DefaultJaxrsScanner scanner = new DefaultJaxrsScanner();
ReflectiveJaxrsScanner scanner = new ReflectiveJaxrsScanner();
scanner.setResourcePackage(API_RESOURCE_PACKAGE);
ScannerFactory.setScanner(scanner);
// Reads annotations from the scanned classes.
ClassReaders.setReader(new DefaultJaxrsApiReader());
log.info("Initializing Swagger configuration succeeded.");
} catch (Exception e) {
log.error("Initializing Swagger configuration failed", e);
}
}
@Override
public void destroy() {
log.info("Destroying Swagger configuration servlet");
}
}
......@@ -29,6 +29,8 @@ import javax.enterprise.context.ConversationScoped;
import javax.enterprise.inject.Produces;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import javax.inject.Inject;
import javax.inject.Named;
import javax.json.JsonObject;
......@@ -657,4 +659,8 @@ public class UserView extends GenericCDIView {
this.emailCheck = emailCheck;
}
public void cardStateChangeListener(ValueChangeEvent valueChange) {
logger.debug("PrintedCard state changed from {} to {}", valueChange.getOldValue(), valueChange.getNewValue());
setCardState();
}
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!