mirror of
https://github.com/skogaby/butterfly.git
synced 2026-04-25 07:59:02 -05:00
Write eventlog.write requests to the database, and validate incoming PCBIDs for database existence
This commit is contained in:
parent
cd12a94d50
commit
b94e4d44ce
|
|
@ -53,7 +53,7 @@ public abstract class AbstractHibernateDao<T extends Serializable> {
|
|||
this.currentSession.close();
|
||||
}
|
||||
|
||||
public void closeCurrentSessionwithTransaction() {
|
||||
public void closeCurrentSessionWithTransaction() {
|
||||
this.currentTransaction.commit();
|
||||
this.currentSession.close();
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ public abstract class AbstractHibernateDao<T extends Serializable> {
|
|||
operation.call(entities[i]);
|
||||
}
|
||||
|
||||
this.closeCurrentSessionwithTransaction();
|
||||
this.closeCurrentSessionWithTransaction();
|
||||
} catch (Exception e) {
|
||||
this.currentTransaction.rollback();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
package com.buttongames.butterfly.hibernate.dao.impl;
|
||||
|
||||
import com.buttongames.butterfly.hibernate.dao.AbstractHibernateDao;
|
||||
import com.buttongames.butterfly.model.ButterflyPcb;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* DAO for interacting with <code>ButterflyPcb</code> objects in the database.
|
||||
* @author skogaby (skogabyskogaby@gmail.com)
|
||||
*/
|
||||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||
@Repository
|
||||
public class ButterflyPcbDao extends AbstractHibernateDao<ButterflyPcb> {
|
||||
|
||||
@Autowired
|
||||
public ButterflyPcbDao(final SessionFactory sessionFactory) {
|
||||
super(sessionFactory);
|
||||
setClazz(ButterflyPcb.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.buttongames.butterfly.hibernate.dao.impl;
|
||||
|
||||
import com.buttongames.butterfly.hibernate.dao.AbstractHibernateDao;
|
||||
import com.buttongames.butterfly.model.Machine;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.query.Query;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* DAO for interacting with <code>Machine</code> objects in the database.
|
||||
* @author skogaby (skogabyskogaby@gmail.com)
|
||||
*/
|
||||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||
@Repository
|
||||
public class MachineDao extends AbstractHibernateDao<Machine> {
|
||||
|
||||
@Autowired
|
||||
public MachineDao(final SessionFactory sessionFactory) {
|
||||
super(sessionFactory);
|
||||
setClazz(Machine.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a machine by its PCBID.
|
||||
* @param pcbId The PCBID to query for.
|
||||
* @return The matching Machine, or null if none are found.
|
||||
*/
|
||||
public Machine findByPcbId(final String pcbId) {
|
||||
this.openCurrentSession();
|
||||
|
||||
final Query<Machine> query = this.currentSession.createQuery("from Machine where pcbid = :pcbid");
|
||||
query.setParameter("pcbid", pcbId);
|
||||
final Machine result = query.uniqueResult();
|
||||
|
||||
this.closeCurrentSession();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.buttongames.butterfly.http;
|
|||
|
||||
import com.buttongames.butterfly.compression.Lz77;
|
||||
import com.buttongames.butterfly.encryption.Rc4;
|
||||
import com.buttongames.butterfly.hibernate.dao.impl.MachineDao;
|
||||
import com.buttongames.butterfly.http.exception.InvalidPcbIdException;
|
||||
import com.buttongames.butterfly.http.exception.InvalidRequestException;
|
||||
import com.buttongames.butterfly.http.exception.InvalidRequestMethodException;
|
||||
import com.buttongames.butterfly.http.exception.InvalidRequestModelException;
|
||||
|
|
@ -91,6 +93,9 @@ public class ButterflyHttpServer {
|
|||
/** Handler for requests for the <code>tax</code> module. */
|
||||
private final TaxRequestHandler taxRequestHandler;
|
||||
|
||||
/** DAO for interacting with <code>Machine</code> objects in the database. */
|
||||
private final MachineDao machineDao;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
|
|
@ -102,7 +107,8 @@ public class ButterflyHttpServer {
|
|||
final FacilityRequestHandler facilityRequestHandler,
|
||||
final PackageRequestHandler packageRequestHandler,
|
||||
final EventLogRequestHandler eventLogRequestHandler,
|
||||
final TaxRequestHandler taxRequestHandler) {
|
||||
final TaxRequestHandler taxRequestHandler,
|
||||
final MachineDao machineDao) {
|
||||
this.servicesRequestHandler = servicesRequestHandler;
|
||||
this.pcbEventRequestHandler = pcbEventRequestHandler;
|
||||
this.pcbTrackerRequestHandler = pcbTrackerRequestHandler;
|
||||
|
|
@ -111,6 +117,7 @@ public class ButterflyHttpServer {
|
|||
this.packageRequestHandler = packageRequestHandler;
|
||||
this.eventLogRequestHandler = eventLogRequestHandler;
|
||||
this.taxRequestHandler = taxRequestHandler;
|
||||
this.machineDao = machineDao;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -182,8 +189,12 @@ public class ButterflyHttpServer {
|
|||
}));
|
||||
exception(MismatchedRequestUriException.class, (((exception, request, response) -> {
|
||||
response.status(400);
|
||||
response.body("Request URI does not match request body");
|
||||
response.body("Request URI does not match request body.");
|
||||
})));
|
||||
exception(InvalidPcbIdException.class, (((exception, request, response) -> {
|
||||
response.status(403);
|
||||
response.body("PCBID is not valid or nonexistent.");
|
||||
})));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -214,7 +225,7 @@ public class ButterflyHttpServer {
|
|||
throw new InvalidRequestModuleException();
|
||||
}
|
||||
|
||||
// 3) validate that the request URI matches the request body;
|
||||
// 3) validate that the PCBID exists in the database
|
||||
final String encryptionKey = request.headers(CRYPT_KEY_HEADER);
|
||||
final String compressionScheme = request.headers(COMPRESSION_HEADER);
|
||||
byte[] reqBody = request.bodyAsBytes();
|
||||
|
|
@ -235,8 +246,7 @@ public class ButterflyHttpServer {
|
|||
reqBody = BinaryXmlUtils.binaryToXml(reqBody);
|
||||
}
|
||||
|
||||
// read the request body into an XML document and check its properties
|
||||
// to verify it matches the request URI
|
||||
// read the request body into an XML document
|
||||
Element rootNode = XmlUtils.byteArrayToXmlFile(reqBody);
|
||||
|
||||
if (rootNode == null ||
|
||||
|
|
@ -250,6 +260,12 @@ public class ButterflyHttpServer {
|
|||
final String requestBodyModule = moduleNode.getNodeName();
|
||||
final String requestBodyMethod = moduleNode.getAttribute("method");
|
||||
|
||||
// check if the PCB exists in the database
|
||||
if (this.machineDao.findByPcbId(requestBodyPcbId) == null) {
|
||||
throw new InvalidPcbIdException();
|
||||
}
|
||||
|
||||
// 4) validate that the request URI matches the request body
|
||||
if (StringUtils.isBlank(requestBodyModel) ||
|
||||
StringUtils.isBlank(requestBodyModule) ||
|
||||
StringUtils.isBlank(requestBodyMethod) ||
|
||||
|
|
@ -266,9 +282,7 @@ public class ButterflyHttpServer {
|
|||
request.attribute("module", requestBodyModule);
|
||||
request.attribute("method", requestBodyMethod);
|
||||
|
||||
// TODO: Verify the PCBID
|
||||
|
||||
// 4) return the node corresponding to the actual call
|
||||
// 5) return the node corresponding to the actual call
|
||||
return moduleNode;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package com.buttongames.butterfly.http.exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when a request is made with a PCBID that's not in the database.
|
||||
* @author skogaby (skogabyskogaby@gmail.com)
|
||||
*/
|
||||
public class InvalidPcbIdException extends RuntimeException {
|
||||
}
|
||||
|
|
@ -1,8 +1,12 @@
|
|||
package com.buttongames.butterfly.http.handlers.impl;
|
||||
|
||||
import com.buttongames.butterfly.hibernate.dao.impl.Ddr16GameplayEventLogDao;
|
||||
import com.buttongames.butterfly.http.exception.InvalidRequestMethodException;
|
||||
import com.buttongames.butterfly.http.handlers.BaseRequestHandler;
|
||||
import com.buttongames.butterfly.model.Ddr16GameplayEventLog;
|
||||
import com.buttongames.butterfly.util.TimeUtils;
|
||||
import com.buttongames.butterfly.xml.KXmlBuilder;
|
||||
import com.buttongames.butterfly.xml.XmlUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
|
@ -10,6 +14,9 @@ import org.w3c.dom.Element;
|
|||
import spark.Request;
|
||||
import spark.Response;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* Handler for any requests that come to the <code>eventlog</code> module.
|
||||
* @author skogaby (skogabyskogaby@gmail.com)
|
||||
|
|
@ -19,6 +26,16 @@ public class EventLogRequestHandler extends BaseRequestHandler {
|
|||
|
||||
private final Logger LOG = LogManager.getLogger(EventLogRequestHandler.class);
|
||||
|
||||
/**
|
||||
* The DAO for creating gameplay event logs in the database.
|
||||
*/
|
||||
private final Ddr16GameplayEventLogDao gameplayEventLogDao;
|
||||
|
||||
|
||||
public EventLogRequestHandler(final Ddr16GameplayEventLogDao gameplayEventLogDao) {
|
||||
this.gameplayEventLogDao = gameplayEventLogDao;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an incoming request for the <code>eventlog</code> module.
|
||||
* @param requestBody The XML document of the incoming request.
|
||||
|
|
@ -31,7 +48,7 @@ public class EventLogRequestHandler extends BaseRequestHandler {
|
|||
final String requestMethod = request.attribute("method");
|
||||
|
||||
if (requestMethod.equals("write")) {
|
||||
return handleWriteRequest(request, response);
|
||||
return handleWriteRequest(requestBody, request, response);
|
||||
} else {
|
||||
throw new InvalidRequestMethodException();
|
||||
}
|
||||
|
|
@ -39,12 +56,31 @@ public class EventLogRequestHandler extends BaseRequestHandler {
|
|||
|
||||
/**
|
||||
* Handles an incoming request for <code>eventlog.write</code>
|
||||
* @param requestBody The XML document of the incoming request.
|
||||
* @param request The Spark request
|
||||
* @param response The Spark response
|
||||
* @return A response object for Spark
|
||||
*/
|
||||
private Object handleWriteRequest(final Request request, final Response response) {
|
||||
// TODO: actually store the events coming in from the client
|
||||
private Object handleWriteRequest(final Element requestBody, final Request request, final Response response) {
|
||||
// save the event to the database
|
||||
final String reqModel = request.attribute("model");
|
||||
final String reqPcbId = request.attribute("pcbid");
|
||||
final int retryCount = XmlUtils.intValueAtPath(requestBody, "/eventlog/retrycnt");
|
||||
final String eventId = XmlUtils.strValueAtPath(requestBody, "/eventlog/data/eventid");
|
||||
final int eventOrder = XmlUtils.intValueAtPath(requestBody, "/eventlog/data/eventorder");
|
||||
final LocalDateTime pcbTime = TimeUtils.timeFromEpoch(XmlUtils.longValueAtPath(requestBody, "/eventlog/data/pcbtime"));
|
||||
final long gameSession = XmlUtils.longValueAtPath(requestBody, "/eventlog/data/gamesession");
|
||||
final String stringData1 = new String(Base64.getDecoder().decode(XmlUtils.strValueAtPath(requestBody, "/eventlog/data/strdata1")));
|
||||
final String stringData2 = new String(Base64.getDecoder().decode(XmlUtils.strValueAtPath(requestBody, "/eventlog/data/strdata2")));
|
||||
final long numData1 = XmlUtils.longValueAtPath(requestBody, "/eventlog/data/numdata1");
|
||||
final long numData2 = XmlUtils.longValueAtPath(requestBody, "/eventlog/data/numdata2");
|
||||
final String locationId = XmlUtils.strValueAtPath(requestBody, "/eventlog/data/locationid");
|
||||
|
||||
final Ddr16GameplayEventLog event = new Ddr16GameplayEventLog(reqPcbId, reqModel, retryCount, eventId,
|
||||
eventOrder, pcbTime, gameSession, stringData1, stringData2, numData1, numData2, locationId);
|
||||
this.gameplayEventLogDao.create(event);
|
||||
|
||||
// send the response
|
||||
KXmlBuilder respBuilder = KXmlBuilder.create("response")
|
||||
.e("eventlog")
|
||||
.s64("gamesession", 0).up()
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import java.io.Externalizable;
|
|||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Model class that represents a gameplay event from a DDR 16 machine.
|
||||
|
|
@ -50,7 +51,7 @@ public class Ddr16GameplayEventLog implements Externalizable {
|
|||
|
||||
/** The PCB time of the event. */
|
||||
@Column(name = "pcb_time")
|
||||
private long pcbTime;
|
||||
private LocalDateTime pcbTime;
|
||||
|
||||
/** The game session of the event. */
|
||||
@Column(name = "game_session")
|
||||
|
|
@ -73,16 +74,15 @@ public class Ddr16GameplayEventLog implements Externalizable {
|
|||
private long numData2;
|
||||
|
||||
/** The location ID for the facility of the machine. */
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "facility_id")
|
||||
private Ddr16Facility facility;
|
||||
@Column(name = "location_id")
|
||||
private String locationId;
|
||||
|
||||
public Ddr16GameplayEventLog() { }
|
||||
|
||||
public Ddr16GameplayEventLog(final String pcbId, final String model, final int retryCount,
|
||||
final String eventId, final int eventOrder, final long pcbTime, final long gameSession,
|
||||
final String eventId, final int eventOrder, final LocalDateTime pcbTime, final long gameSession,
|
||||
final String stringData1, final String stringData2, final long numData1, final long numData2,
|
||||
final Ddr16Facility facility) {
|
||||
final String locationId) {
|
||||
this.pcbId = pcbId;
|
||||
this.model = model;
|
||||
this.retryCount = retryCount;
|
||||
|
|
@ -94,7 +94,7 @@ public class Ddr16GameplayEventLog implements Externalizable {
|
|||
this.stringData2 = stringData2;
|
||||
this.numData1 = numData1;
|
||||
this.numData2 = numData2;
|
||||
this.facility = facility;
|
||||
this.locationId = locationId;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -105,13 +105,13 @@ public class Ddr16GameplayEventLog implements Externalizable {
|
|||
out.writeInt(this.retryCount);
|
||||
out.writeUTF(this.eventId);
|
||||
out.writeInt(this.eventOrder);
|
||||
out.writeLong(this.pcbTime);
|
||||
out.writeObject(this.pcbTime);
|
||||
out.writeLong(this.gameSession);
|
||||
out.writeUTF(this.stringData1);
|
||||
out.writeUTF(this.stringData2);
|
||||
out.writeLong(this.numData1);
|
||||
out.writeLong(this.numData2);
|
||||
out.writeObject(this.facility);
|
||||
out.writeUTF(this.locationId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -122,13 +122,13 @@ public class Ddr16GameplayEventLog implements Externalizable {
|
|||
this.setRetryCount(in.readInt());
|
||||
this.setEventId(in.readUTF());
|
||||
this.setEventOrder(in.readInt());
|
||||
this.setPcbTime(in.readLong());
|
||||
this.setPcbTime((LocalDateTime) in.readObject());
|
||||
this.setGameSession(in.readLong());
|
||||
this.setStringData1(in.readUTF());
|
||||
this.setStringData2(in.readUTF());
|
||||
this.setNumData1(in.readLong());
|
||||
this.setNumData2(in.readLong());
|
||||
this.setFacility((Ddr16Facility) in.readObject());
|
||||
this.setLocationId(in.readUTF());
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
|
|
@ -179,11 +179,11 @@ public class Ddr16GameplayEventLog implements Externalizable {
|
|||
this.eventOrder = eventOrder;
|
||||
}
|
||||
|
||||
public long getPcbTime() {
|
||||
public LocalDateTime getPcbTime() {
|
||||
return pcbTime;
|
||||
}
|
||||
|
||||
public void setPcbTime(long pcbTime) {
|
||||
public void setPcbTime(LocalDateTime pcbTime) {
|
||||
this.pcbTime = pcbTime;
|
||||
}
|
||||
|
||||
|
|
@ -227,11 +227,11 @@ public class Ddr16GameplayEventLog implements Externalizable {
|
|||
this.numData2 = numData2;
|
||||
}
|
||||
|
||||
public Ddr16Facility getFacility() {
|
||||
return facility;
|
||||
public String getLocationId() {
|
||||
return locationId;
|
||||
}
|
||||
|
||||
public void setFacility(Ddr16Facility facility) {
|
||||
this.facility = facility;
|
||||
public void setLocationId(String locationId) {
|
||||
this.locationId = locationId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import java.time.LocalDateTime;
|
|||
*/
|
||||
@Entity
|
||||
@Table(name = "machines")
|
||||
public class ButterflyPcb implements Externalizable {
|
||||
public class Machine implements Externalizable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
|
@ -62,10 +62,10 @@ public class ButterflyPcb implements Externalizable {
|
|||
@Column(name = "port")
|
||||
private int port;
|
||||
|
||||
public ButterflyPcb() { }
|
||||
public Machine() { }
|
||||
|
||||
public ButterflyPcb(final ButterflyUser user, final String pcbId, final LocalDateTime registerTime,
|
||||
final boolean enabled, final int port) {
|
||||
public Machine(final ButterflyUser user, final String pcbId, final LocalDateTime registerTime,
|
||||
final boolean enabled, final int port) {
|
||||
this.user = user;
|
||||
this.pcbId = pcbId;
|
||||
this.registerTime = registerTime;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.buttongames.butterfly.spring.configuration;
|
||||
|
||||
import com.buttongames.butterfly.hibernate.dao.impl.ButterflyPcbDao;
|
||||
import com.buttongames.butterfly.hibernate.dao.impl.MachineDao;
|
||||
import com.buttongames.butterfly.hibernate.dao.impl.ButterflyUserDao;
|
||||
import com.buttongames.butterfly.hibernate.dao.impl.Ddr16FacilityDao;
|
||||
import com.buttongames.butterfly.hibernate.dao.impl.Ddr16GameplayEventLogDao;
|
||||
|
|
@ -87,8 +87,8 @@ public class HibernateConfiguration {
|
|||
}
|
||||
|
||||
@Bean
|
||||
public ButterflyPcbDao butterflyPcbDao(final SessionFactory sessionFactory) {
|
||||
return new ButterflyPcbDao(sessionFactory);
|
||||
public MachineDao butterflyPcbDao(final SessionFactory sessionFactory) {
|
||||
return new MachineDao(sessionFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package com.buttongames.butterfly.spring.configuration;
|
||||
|
||||
import com.buttongames.butterfly.hibernate.dao.impl.Ddr16GameplayEventLogDao;
|
||||
import com.buttongames.butterfly.hibernate.dao.impl.Ddr16PcbEventLogDao;
|
||||
import com.buttongames.butterfly.hibernate.dao.impl.MachineDao;
|
||||
import com.buttongames.butterfly.http.ButterflyHttpServer;
|
||||
import com.buttongames.butterfly.http.handlers.impl.EventLogRequestHandler;
|
||||
import com.buttongames.butterfly.http.handlers.impl.FacilityRequestHandler;
|
||||
|
|
@ -30,15 +32,16 @@ public class HttpConfiguration {
|
|||
final FacilityRequestHandler facilityRequestHandler,
|
||||
final PackageRequestHandler packageRequestHandler,
|
||||
final EventLogRequestHandler eventLogRequestHandler,
|
||||
final TaxRequestHandler taxRequestHandler) {
|
||||
final TaxRequestHandler taxRequestHandler,
|
||||
final MachineDao machineDao) {
|
||||
return new ButterflyHttpServer(servicesRequestHandler, pcbEventRequestHandler, pcbTrackerRequestHandler,
|
||||
messageRequestHandler, facilityRequestHandler, packageRequestHandler, eventLogRequestHandler,
|
||||
taxRequestHandler);
|
||||
taxRequestHandler, machineDao);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EventLogRequestHandler eventLogRequestHandler() {
|
||||
return new EventLogRequestHandler();
|
||||
public EventLogRequestHandler eventLogRequestHandler(final Ddr16GameplayEventLogDao gameplayEventLogDao) {
|
||||
return new EventLogRequestHandler(gameplayEventLogDao);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user