Skip to content
This repository has been archived by the owner on Apr 6, 2021. It is now read-only.

Commit

Permalink
Merge pull request #43 from carne-iot/0.0.4.RELEASE
Browse files Browse the repository at this point in the history
Release 0.0.4.release
  • Loading branch information
juanmbellini committed Nov 21, 2017
2 parents ec58d79 + 86034de commit f08913c
Show file tree
Hide file tree
Showing 14 changed files with 47 additions and 148 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<groupId>ar.edu.itba.iot.carne-iot</groupId>
<artifactId>server</artifactId>
<version>0.0.3.RELEASE</version>
<version>0.0.4.RELEASE</version>
<packaging>pom</packaging>
<name>${project.groupId}:${project.artifactId}</name>

Expand Down
2 changes: 1 addition & 1 deletion server-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>ar.edu.itba.iot.carne-iot</groupId>
<artifactId>server</artifactId>
<version>0.0.3.RELEASE</version>
<version>0.0.4.RELEASE</version>
</parent>

<artifactId>server-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package ar.edu.itba.iot.carne_iot.server.models;

import ar.edu.itba.iot.carne_iot.server.error_handling.errros.IllegalStateError;
import ar.edu.itba.iot.carne_iot.server.error_handling.errros.ValidationError;
import ar.edu.itba.iot.carne_iot.server.error_handling.helpers.ValidationExceptionThrower;
import ar.edu.itba.iot.carne_iot.server.error_handling.helpers.ValidationHelper;
import ar.edu.itba.iot.carne_iot.server.exceptions.CustomIllegalStateException;
import ar.edu.itba.iot.carne_iot.server.exceptions.ValidationException;
import ar.edu.itba.iot.carne_iot.server.models.constants.ValidationConstants;
import ar.edu.itba.iot.carne_iot.server.models.constants.ValidationErrorConstants;

import javax.persistence.*;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.LinkedList;
Expand Down Expand Up @@ -41,13 +42,6 @@ public class Device implements ValidationExceptionThrower {
@Column(name = "last_temperature_update")
private Instant lastTemperatureUpdate;

/**
* The actual state of this device.
*/
@Column(name = "state", length = 64)
@Enumerated(EnumType.STRING)
private State state;


/* package */ Device() {
// For Hibernate
Expand All @@ -62,7 +56,6 @@ public Device(long id) {
this.id = id;
this.temperature = null;
this.lastTemperatureUpdate = null;
this.state = State.IDLE;
}

/**
Expand All @@ -87,52 +80,19 @@ public Instant getLastTemperatureUpdate() {
return lastTemperatureUpdate;
}

/**
* @return The actual state of this device.
*/
public State getState() {
return state;
}

/**
* Sets the actual temperature measured by this device.
*
* @param temperature The actual temperature measured by this device.
* @throws ValidationException If the temperature is not valid.
*/
public void setTemperature(BigDecimal temperature) throws ValidationException {
if (this.state != State.ACTIVE) {
throw new CustomIllegalStateException(CHANGE_TEMPERATURE_IN_NOT_ACTIVE_STATE);
}
validateTemperature(temperature);

this.temperature = temperature;
this.lastTemperatureUpdate = Instant.now();
}

/**
* Changes this device state to active.
*/
public void startCooking() {
this.state = State.ACTIVE;
}

/**
* Changes this device state to idle.
*/
public void stopCooking() {
this.state = State.IDLE;
}


/**
* Enum listing all possible states for a {@link Device}.
*/
public enum State {
IDLE,
ACTIVE,
}


// ====================
// Validators
Expand Down Expand Up @@ -163,8 +123,4 @@ private void validateTemperature(BigDecimal temperature) throws ValidationExcept

/* package */ static final int PRECISION = 5;
/* package */ static final int SCALE = 2;

private static final IllegalStateError CHANGE_TEMPERATURE_IN_NOT_ACTIVE_STATE =
new IllegalStateError("Device must be active to set the temperature",
Device.class.getSimpleName());
}
2 changes: 1 addition & 1 deletion server-persistence-interfaces/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>ar.edu.itba.iot.carne-iot</groupId>
<artifactId>server</artifactId>
<version>0.0.3.RELEASE</version>
<version>0.0.4.RELEASE</version>
</parent>

<artifactId>server-persistence-interfaces</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion server-persistence/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>ar.edu.itba.iot.carne-iot</groupId>
<artifactId>server</artifactId>
<version>0.0.3.RELEASE</version>
<version>0.0.4.RELEASE</version>
</parent>

<artifactId>server-persistence</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion server-services-interfaces/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>ar.edu.itba.iot.carne-iot</groupId>
<artifactId>server</artifactId>
<version>0.0.3.RELEASE</version>
<version>0.0.4.RELEASE</version>
</parent>

<artifactId>server-services-interfaces</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,20 +105,12 @@ public interface DeviceService {
String pair(long ownerId, long deviceId);

/**
* Makes a {@link Device} start cooking (i.e change its state to {@link Device.State#ACTIVE}).
* This is an idempotent operation.
* Performs pairing of {@link ar.edu.itba.iot.carne_iot.server.models.Device}s, using a system {@link User}.
*
* @param deviceId The id of the {@link Device} that will start cooking.
*/
void startCooking(long deviceId);

/**
* Makes a {@link Device} stop cooking (i.e change its state to {@link Device.State#IDLE}).
* This is an idempotent operation.
*
* @param deviceId The id of the {@link Device} that will stop cooking.
* @param deviceId The id of the {@link ar.edu.itba.iot.carne_iot.server.models.Device} to be paired.
* @return The token generated by the pairing process.
*/
void stopCooking(long deviceId);
String pair(long deviceId);

/**
* Updates the temperature of a given {@link Device}.
Expand Down
2 changes: 1 addition & 1 deletion server-services/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>ar.edu.itba.iot.carne-iot</groupId>
<artifactId>server</artifactId>
<version>0.0.3.RELEASE</version>
<version>0.0.4.RELEASE</version>
</parent>

<artifactId>server-services</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
import ar.edu.itba.iot.carne_iot.server.exceptions.UniqueViolationException;
import ar.edu.itba.iot.carne_iot.server.models.Device;
import ar.edu.itba.iot.carne_iot.server.models.DeviceRegistration;
import ar.edu.itba.iot.carne_iot.server.models.Session;
import ar.edu.itba.iot.carne_iot.server.models.User;
import ar.edu.itba.iot.carne_iot.server.persistence.daos.DeviceDao;
import ar.edu.itba.iot.carne_iot.server.persistence.daos.DeviceRegistrationDao;
import ar.edu.itba.iot.carne_iot.server.persistence.daos.SessionDao;
import ar.edu.itba.iot.carne_iot.server.persistence.daos.UserDao;
import ar.edu.itba.iot.carne_iot.server.persistence.query_helpers.DeviceQueryHelper;
import ar.edu.itba.iot.carne_iot.server.persistence.query_helpers.DeviceRegistrationQueryHelper;
Expand All @@ -27,8 +25,8 @@
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Collections;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
Expand All @@ -41,9 +39,11 @@
public class DeviceServiceImpl implements DeviceService, UniqueViolationExceptionThrower {

/**
* Amount of tries to perform the pairing process.
* A system {@link User} to be used to create device tokens.
*/
private static final int MAX_TRIES = 10;
private static final User deviceUser = new User("device",
LocalDate.of(1900, 1, 1),
"username", "email@email.com", "hashed");

/**
* DAO for managing {@link User}s data.
Expand Down Expand Up @@ -75,24 +75,18 @@ public class DeviceServiceImpl implements DeviceService, UniqueViolationExceptio
*/
private final JwtTokenGenerator jwtTokenGenerator;

/**
* DAO for retrieving {@link Session}s data.
*/
private final SessionDao sessionDao;


@Autowired
public DeviceServiceImpl(UserDao userDao, DeviceDao deviceDao, DeviceRegistrationDao deviceRegistrationDao,
DeviceQueryHelper deviceQueryHelper,
DeviceRegistrationQueryHelper deviceRegistrationQueryHelper,
JwtTokenGenerator jwtTokenGenerator, SessionDao sessionDao) {
JwtTokenGenerator jwtTokenGenerator) {
this.userDao = userDao;
this.deviceDao = deviceDao;
this.deviceRegistrationDao = deviceRegistrationDao;
this.deviceQueryHelper = deviceQueryHelper;
this.deviceRegistrationQueryHelper = deviceRegistrationQueryHelper;
this.jwtTokenGenerator = jwtTokenGenerator;
this.sessionDao = sessionDao;
}


Expand Down Expand Up @@ -209,7 +203,6 @@ public void unregisterDevice(long deviceId) {
}

@Override
@Transactional
@PreAuthorize("@devicePermissionProvider.isOwnerOrAdmin(#deviceId)")
public String pair(long ownerId, long deviceId) {
final User user = userDao.findById(ownerId).orElseThrow(NoSuchEntityException::new);
Expand All @@ -220,39 +213,14 @@ public String pair(long ownerId, long deviceId) {
throw new CustomIllegalStateException(OPERATION_OVER_UNREGISTERED_DEVICE);
}

// Try to create the token...
boolean validToken = false;
int tries = 0;
JwtTokenGenerator.TokenAndSessionContainer container = null;
while (!validToken && tries < MAX_TRIES) {
container = jwtTokenGenerator.generateDeviceToken(user, device);
validToken = !sessionDao.existsByOwnerAndJti(user, container.getJti());
tries++;
}
if (tries >= MAX_TRIES) {
throw new RuntimeException("Could not create a session after " + MAX_TRIES + "tries");
}

// Store token in order to pass the
Objects.requireNonNull(container, "The container was not initialized correctly");
final Session session = new Session(user, container.getJti()); // Actually not a session, but whatever
sessionDao.save(session);

return container.getToken();
return jwtTokenGenerator.generateDeviceToken(user, device).getToken();
}

@Override
@Transactional
@PreAuthorize("@devicePermissionProvider.isOwnerOrAdmin(#deviceId)")
public void startCooking(long deviceId) {
performChangeOfState(deviceId, Device::startCooking);
}

@Override
@Transactional
@PreAuthorize("@devicePermissionProvider.isOwnerOrAdmin(#deviceId)")
public void stopCooking(long deviceId) {
performChangeOfState(deviceId, Device::stopCooking);
@PreAuthorize("@adminPermissionProvider.isAdmin()")
public String pair(long deviceId) {
final Device device = deviceDao.findById(deviceId).orElseThrow(NoSuchEntityException::new);
return jwtTokenGenerator.generateDeviceToken(deviceUser, device).getToken();
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion server-webapp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>ar.edu.itba.iot.carne-iot</groupId>
<artifactId>server</artifactId>
<version>0.0.3.RELEASE</version>
<version>0.0.4.RELEASE</version>
</parent>

<artifactId>server-webapp</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ public class DeviceDto implements Resoursable {
@JsonSerialize(using = Java8InstantSerializer.class)
private Instant lastTemperatureUpdate;

@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Device.State state;


public DeviceDto() {
// For Jersey
Expand All @@ -46,7 +43,6 @@ public DeviceDto() {
this.id = device.getId();
this.temperature = device.getTemperature();
this.lastTemperatureUpdate = device.getLastTemperatureUpdate();
this.state = device.getState();
}

public Long getId() {
Expand All @@ -60,8 +56,4 @@ public BigDecimal getTemperature() {
public Instant getLastTemperatureUpdate() {
return lastTemperatureUpdate;
}

public Device.State getState() {
return state;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,34 +136,6 @@ public Response unregisterDevice(@PathParam("id") @Base64url final Long id) {
// Device state changers
// ======================================

@PUT
@Path("/{id : .+}/cooking")
public Response startCooking(@PathParam("id") @Base64url final Long id) {
if (id == null) {
throw new IllegalParamValueException(Collections.singletonList("id"));
}

LOGGER.debug("Device with id {} started cooking", id);

deviceService.startCooking(id);

return Response.noContent().build();
}

@DELETE
@Path("/{id : .+}/cooking")
public Response stopCooking(@PathParam("id") @Base64url final Long id) {
if (id == null) {
throw new IllegalParamValueException(Collections.singletonList("id"));
}

LOGGER.debug("Device with id {} stopped cooking", id);

deviceService.stopCooking(id);

return Response.noContent().build();
}

@PUT
@Path("/{id : .+}/temperature")
@Consumes(MediaType.APPLICATION_JSON)
Expand All @@ -182,4 +154,22 @@ public Response updateTemperature(@PathParam("id") @Base64url final Long id, Str

return Response.noContent().build();
}

@POST
@Path("/{deviceId : .+}/pair")
public Response pairDevice(@PathParam("deviceId") @Base64url final Long deviceId) {

LOGGER.debug("Trying to pair device with id {}", deviceId);

// Create a JWT for the paired device
final String token = deviceService.pair(deviceId);

LOGGER.debug("Device {} successfully paired", deviceId);

// TODO: if token can be invalidated, add an "invalidation" url

return Response.noContent()
.header("X-Device-Token", token)
.build();
}
}
Loading

0 comments on commit f08913c

Please sign in to comment.