Permalink
Browse files

Fixed constraint violation serialization on client

  • Loading branch information...
christianbauer committed Jan 10, 2018
1 parent 74b16f5 commit 53715831f3e2150330a9e7cc010d26161e474d9c
@@ -229,11 +229,11 @@ protected void handlePasswordReset() {
if (password == null)
return;
if (!password.equals(passwordControl)) {
validationErrorHandler.accept(new ConstraintViolation[]{
new ConstraintViolation(
ConstraintViolation.Type.FIELD, "password", environment.getMessages().passwordsMustMatch()
)
});
ConstraintViolation violation = new ConstraintViolation();
violation.setConstraintType(ConstraintViolation.Type.FIELD);
violation.setPath("password");
violation.setMessage(environment.getMessages().passwordsMustMatch());
validationErrorHandler.accept(new ConstraintViolation[]{violation});
return;
}
Credential credential = new Credential(password, false);
@@ -150,8 +150,6 @@ public void start() {
asset.setName("My New Asset");
asset.setRealmId(environment.getApp().getTenant().getId());
asset.setTenantDisplayName(environment.getApp().getTenant().getDisplayName());
JsUtil.log(asset);
asset.setType(AssetType.THING);
}
@@ -26,9 +26,8 @@
import jsinterop.annotations.JsIgnore;
import jsinterop.annotations.JsType;
import jsinterop.base.Any;
import jsinterop.base.Js;
import org.openremote.app.client.util.JsUtil;
import org.openremote.model.asset.Asset;
import org.openremote.model.asset.AssetQuery;
import org.openremote.model.http.*;
import org.openremote.model.interop.BiConsumer;
import org.openremote.model.interop.Consumer;
@@ -42,23 +41,31 @@
import java.util.stream.DoubleStream;
import static com.google.gwt.http.client.Response.*;
import static org.openremote.model.http.ConstraintViolationReport.VIOLATION_EXCEPTION_HEADER;
import static org.openremote.model.http.BadRequestException.VIOLATION_EXCEPTION_HEADER;
@JsType
public class RequestService {
private static final Logger LOG = Logger.getLogger(RequestService.class.getName());
double ANY_STATUS_CODE = -1;
public static final double ANY_STATUS_CODE = -1;
// This consumer gets request params, sets credentials to authorize the request, then calls the given runnable
final protected BiConsumer<RequestParams, Runnable> requestAuthorizer;
final protected Runnable beforeRequest;
final protected Runnable afterRequest;
final protected Function<String, ConstraintViolationReport> constraintViolationReader;
public RequestService(BiConsumer<RequestParams, Runnable> requestAuthorizer,
Runnable beforeRequest,
Runnable afterRequest,
Function<String, ConstraintViolationReport> constraintViolationReader) {
this.requestAuthorizer = requestAuthorizer;
this.beforeRequest = beforeRequest;
this.afterRequest = afterRequest;
this.constraintViolationReader = constraintViolationReader;
}
@@ -151,9 +158,17 @@ public void sendAndReturn(Consumer<RequestParams<Void, Any>> onRequest,
Consumer<OUT> onResponse,
Consumer<RequestException> onException) {
if (beforeRequest != null) {
beforeRequest.run();
}
RequestParams<IN, OUT> requestParams = new RequestParams<>(
(responseCode, request, responseText) -> {
if (afterRequest != null) {
afterRequest.run();
}
if (responseCode == 0) {
onException.accept(new NoResponseException(0));
return;
@@ -165,7 +180,7 @@ public void sendAndReturn(Consumer<RequestParams<Void, Any>> onRequest,
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("Received 400 status with constraint violation report: " + responseText);
}
ConstraintViolationReport report = getConstraintViolationReport(responseText);
ConstraintViolationReport report = constraintViolationReader.apply(responseText);
onException.accept(new BadRequestException(SC_BAD_REQUEST, report));
} else {
if (LOG.isLoggable(Level.FINE)) {
@@ -229,8 +244,4 @@ public void sendAndReturn(Consumer<RequestParams<Void, Any>> onRequest,
requestAuthorizer.accept(requestParams, () -> onRequest.accept(requestParams));
}
}
protected ConstraintViolationReport getConstraintViolationReport(String responseText) {
return constraintViolationReader.apply(responseText);
}
}
@@ -309,6 +309,7 @@
}
serviceUrl = serviceUrl + "?Auth-Realm=" + this.realm;
if (this.keycloak) {
// TODO Should use keycloak.updateToken()?
serviceUrl = serviceUrl + "&Authorization=Bearer " + this.keycloak.token;
} else {
serviceUrl = serviceUrl + "&Authorization=Basic " + window.btoa(this.user + ":" + this.basicAuthPassword);
@@ -62,11 +62,11 @@
display: none;
}
/* Example how to style slotted children
#slots ::slotted(*) {
/* TODO Example how to style slotted children
border: 1px solid var(--theme-red);
*/
}
*/
</style>
<div id="loader"></div>
@@ -374,7 +374,7 @@ <h5>[[error]]</h5>
// Disable login/token refresh
this.set("login", false);
// TODO Close websocket?
this.disconnectEventService();
// Hide the slots
this.$.slots.style.display = "none";
@@ -429,8 +429,9 @@ <h5>[[error]]</h5>
(requestParams, onComplete) => {
this.getSecurity().authorizeRequestParams(requestParams, onComplete);
},
this.showLoader.bind(this),
this.hideLoader.bind(this),
(constraintViolationReportJson) => {
// TODO Anything else for constraint violation handling?
return JSON.parse(constraintViolationReportJson);
}
// TODO We should give a default error handler to RequestService
@@ -459,8 +460,7 @@ <h5>[[error]]</h5>
// Close explicitly on unload/refresh of page, otherwise close code will be 1001
window.addEventListener("beforeunload", () => {
console.log("Page unloaded, closing event service connection");
// TODO Should also cancel all subscriptions with the server
this.webSocket.close();
this.disconnectEventService();
});
};
@@ -493,6 +493,15 @@ <h5>[[error]]</h5>
});
}
disconnectEventService() {
if (this.webSocket && this.webSocket.readyState === this.webSocket.OPEN) {
console.log("Closing WebSocket");
// TODO Should also cancel all subscriptions with the server!
this.webSocket.close();
}
}
loadTenantDetails(onComplete) {
if (!this.login) {
onComplete();
@@ -508,9 +517,7 @@ <h5>[[error]]</h5>
onComplete();
},
(exception) => {
// TODO Exception handler, or see above for default error handler in RequestService
console.log("### GOT EXCEPTION");
console.dir(exception);
this.set("error", exception);
}
);
}
@@ -34,15 +34,6 @@
outline: 0;
}
.scrollable {
overflow: auto;
}
scrollable div {
-webkit-flex-shrink: 0;
flex-shrink: 0;
}
.or-Viewport {
width: 100%;
height: 100vh;
@@ -597,6 +588,16 @@
margin: 0.4em;
}
.or-FormMessages,
.or-Toast {
font-size: smaller;
font-weight: 600;
padding: 0.8em;
border-radius: 0.25em;
-webkit-box-shadow: 1px 1px 4px -1px rgba(0, 0, 0, 0.9);
-moz-box-shadow: 1px 1px 4px -1px rgba(0, 0, 0, 0.9);
box-shadow: 1px 1px 4px -1px rgba(0, 0, 0, 0.9);
}
.or-FormMessages,
.or-Toast {
font-size: smaller;
@@ -53,7 +53,7 @@
return e instanceof HTMLTemplateElement;
});
if (!assetTemplate) {
throw "Missing item <template> as child of asset list";
openremote.INSTANCE.set("error", "Missing item <template> as child of asset list");
}
this.set("assetTemplate", assetTemplate);
}
@@ -88,9 +88,7 @@
this.set("assets", response);
},
(exception) => {
// TODO Exception handler
console.log("### GOT EXCEPTION");
console.dir(exception);
openremote.INSTANCE.set("error", exception);
}
);
}
@@ -101,6 +99,10 @@
this.shadowRoot.host.removeChild(item);
});
if (!this.assetTemplate) {
return;
}
// For each asset, create a new item element and append the template, then append to host element
for (let asset of assets) {
let item = document.createElement("or-asset-list-item");
@@ -73,7 +73,7 @@
<or-toast></or-toast>
<!-- ############## Required: One <or-app> should wrap your frontend, you can enforce login/authentication ############## -->
<or-app login tenant-realm="customerA" timeout="10">
<or-app login tenant-realm="customerA">
<!-- You can use your own styles or the OpenRemote styles and theme -->
<a href="#" class="myAppHeadline">
@@ -99,9 +99,8 @@ <h3 style="color: var(--theme-red);">Note: This is under development and incompl
</p>
</div>
<!-- Switch to horizontal layout but flex vertical first and take as much vertical
space as needed, and allow children to scroll if content doesn't fit -->
<div class="flex layout horizontal scrollable">
<!-- Switch to horizontal layout but flex vertical first and take as much vertical space as needed -->
<div class="flex layout horizontal">
<!-- Flex and take as much horizontal space as possible -->
<div class="flex layout vertical">
@@ -141,7 +140,7 @@ <h3 style="color: var(--theme-red);">Note: This is under development and incompl
</div>
<!-- Flex and take as much horizontal space as possible, show scrollbars if content doesn't fit. -->
<div class="flex or-MainContent scrollable">
<div class="flex or-MainContent scroll">
<!-- Execute AssetQuery and subscribe for attribute changes -->
<or-asset type="room" id="blabla">
@@ -40,7 +40,7 @@
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static javax.ws.rs.core.Response.Status.NOT_FOUND;
import static org.openremote.model.Constants.MASTER_REALM;
import static org.openremote.model.http.ConstraintViolationReport.VIOLATION_EXCEPTION_HEADER;
import static org.openremote.model.http.BadRequestException.VIOLATION_EXCEPTION_HEADER;
public class TenantResourceImpl extends ManagerWebResource implements TenantResource {
@@ -163,10 +163,10 @@ protected ConstraintViolationReport isIllegalMasterRealmDeletion(String realm) {
ResourceBundle validationMessages = getContainer().getService(I18NService.class).getValidationMessages();
List<ConstraintViolation> violations = new ArrayList<>();
violations.add(new ConstraintViolation(
ConstraintViolation.Type.PARAMETER,
validationMessages.getString("Tenant.masterDeleted")
));
ConstraintViolation violation = new ConstraintViolation();
violation.setConstraintType(ConstraintViolation.Type.PARAMETER);
violation.setMessage(validationMessages.getString("Tenant.masterDeleted"));
violations.add(violation);
ConstraintViolationReport report = new ConstraintViolationReport();
report.setParameterViolations(violations.toArray(new ConstraintViolation[violations.size()]));
return report;
@@ -180,19 +180,17 @@ protected ConstraintViolationReport isIllegalMasterRealmMutation(String realm, T
List<ConstraintViolation> violations = new ArrayList<>();
if (tenant.getEnabled() == null || !tenant.getEnabled()) {
ConstraintViolation violation = new ConstraintViolation(
ConstraintViolation.Type.PARAMETER,
"Tenant.enabled",
validationMessages.getString("Tenant.masterDisabled")
);
ConstraintViolation violation = new ConstraintViolation();
violation.setConstraintType(ConstraintViolation.Type.PARAMETER);
violation.setPath("Tenant.enabled");
violation.setMessage(validationMessages.getString("Tenant.masterDisabled"));
violations.add(violation);
}
if (tenant.getRealm() == null || !tenant.getRealm().equals(MASTER_REALM)) {
ConstraintViolation violation = new ConstraintViolation(
ConstraintViolation.Type.PARAMETER,
"Tenant.realm",
validationMessages.getString("Tenant.masterRealmChanged")
);
ConstraintViolation violation = new ConstraintViolation();
violation.setConstraintType(ConstraintViolation.Type.PARAMETER);
violation.setPath("Tenant.realm");
violation.setMessage(validationMessages.getString("Tenant.masterRealmChanged"));
violations.add(violation);
}
if (violations.size() > 0) {
@@ -41,7 +41,7 @@
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static org.openremote.model.Constants.MASTER_REALM;
import static org.openremote.model.http.ConstraintViolationReport.VIOLATION_EXCEPTION_HEADER;
import static org.openremote.model.http.BadRequestException.VIOLATION_EXCEPTION_HEADER;
public class UserResourceImpl extends ManagerWebResource implements UserResource {
@@ -210,10 +210,10 @@ protected ConstraintViolationReport isIllegalMasterAdminUserDeletion(RequestPara
ResourceBundle validationMessages = getContainer().getService(I18NService.class).getValidationMessages();
List<ConstraintViolation> violations = new ArrayList<>();
violations.add(new ConstraintViolation(
ConstraintViolation.Type.PARAMETER,
validationMessages.getString("User.masterAdminDeleted")
));
ConstraintViolation violation = new ConstraintViolation();
violation.setConstraintType(ConstraintViolation.Type.PARAMETER);
violation.setMessage(validationMessages.getString("User.masterAdminDeleted"));
violations.add(violation);
ConstraintViolationReport report = new ConstraintViolationReport();
report.setParameterViolations(violations.toArray(new ConstraintViolation[violations.size()]));
return report;
@@ -231,11 +231,10 @@ protected ConstraintViolationReport isIllegalMasterAdminUserMutation(RequestPara
List<ConstraintViolation> violations = new ArrayList<>();
if (user.getEnabled() == null || !user.getEnabled()) {
ConstraintViolation violation = new ConstraintViolation(
ConstraintViolation.Type.PARAMETER,
"User.enabled",
validationMessages.getString("User.masterAdminDisabled")
);
ConstraintViolation violation = new ConstraintViolation();
violation.setConstraintType(ConstraintViolation.Type.PARAMETER);
violation.setPath("User.enabled");
violation.setMessage(validationMessages.getString("User.masterAdminDisabled"));
violations.add(violation);
}
if (violations.size() > 0) {
@@ -24,6 +24,8 @@
@JsType
public class BadRequestException extends RequestException {
public static final String VIOLATION_EXCEPTION_HEADER = "validation-exception";
protected ConstraintViolationReport constraintViolationReport;
public BadRequestException(int statusCode, ConstraintViolationReport constraintViolationReport) {
Oops, something went wrong.

0 comments on commit 5371583

Please sign in to comment.