Showing
66 changed files
with
477 additions
and
148 deletions
@@ -26,12 +26,12 @@ import org.springframework.web.bind.annotation.ResponseBody; | @@ -26,12 +26,12 @@ import org.springframework.web.bind.annotation.ResponseBody; | ||
26 | import org.springframework.web.bind.annotation.RestController; | 26 | import org.springframework.web.bind.annotation.RestController; |
27 | import org.thingsboard.rule.engine.api.MailService; | 27 | import org.thingsboard.rule.engine.api.MailService; |
28 | import org.thingsboard.rule.engine.api.SmsService; | 28 | import org.thingsboard.rule.engine.api.SmsService; |
29 | -import org.thingsboard.server.common.data.sms.config.TestSmsRequest; | ||
30 | import org.thingsboard.server.common.data.AdminSettings; | 29 | import org.thingsboard.server.common.data.AdminSettings; |
31 | import org.thingsboard.server.common.data.UpdateMessage; | 30 | import org.thingsboard.server.common.data.UpdateMessage; |
32 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 31 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
33 | import org.thingsboard.server.common.data.id.TenantId; | 32 | import org.thingsboard.server.common.data.id.TenantId; |
34 | import org.thingsboard.server.common.data.security.model.SecuritySettings; | 33 | import org.thingsboard.server.common.data.security.model.SecuritySettings; |
34 | +import org.thingsboard.server.common.data.sms.config.TestSmsRequest; | ||
35 | import org.thingsboard.server.dao.settings.AdminSettingsService; | 35 | import org.thingsboard.server.dao.settings.AdminSettingsService; |
36 | import org.thingsboard.server.queue.util.TbCoreComponent; | 36 | import org.thingsboard.server.queue.util.TbCoreComponent; |
37 | import org.thingsboard.server.service.security.permission.Operation; | 37 | import org.thingsboard.server.service.security.permission.Operation; |
@@ -88,6 +88,7 @@ public class AdminController extends BaseController { | @@ -88,6 +88,7 @@ public class AdminController extends BaseController { | ||
88 | } else if (adminSettings.getKey().equals("sms")) { | 88 | } else if (adminSettings.getKey().equals("sms")) { |
89 | smsService.updateSmsConfiguration(); | 89 | smsService.updateSmsConfiguration(); |
90 | } | 90 | } |
91 | + | ||
91 | return adminSettings; | 92 | return adminSettings; |
92 | } catch (Exception e) { | 93 | } catch (Exception e) { |
93 | throw handleException(e); | 94 | throw handleException(e); |
@@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.relation.EntityRelation; | @@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.relation.EntityRelation; | ||
34 | import org.thingsboard.server.common.data.relation.EntityRelationInfo; | 34 | import org.thingsboard.server.common.data.relation.EntityRelationInfo; |
35 | import org.thingsboard.server.common.data.relation.EntityRelationsQuery; | 35 | import org.thingsboard.server.common.data.relation.EntityRelationsQuery; |
36 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 36 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
37 | +import org.thingsboard.server.dao.service.ConstraintValidator; | ||
37 | import org.thingsboard.server.queue.util.TbCoreComponent; | 38 | import org.thingsboard.server.queue.util.TbCoreComponent; |
38 | import org.thingsboard.server.service.security.permission.Operation; | 39 | import org.thingsboard.server.service.security.permission.Operation; |
39 | 40 | ||
@@ -63,6 +64,7 @@ public class EntityRelationController extends BaseController { | @@ -63,6 +64,7 @@ public class EntityRelationController extends BaseController { | ||
63 | if (relation.getTypeGroup() == null) { | 64 | if (relation.getTypeGroup() == null) { |
64 | relation.setTypeGroup(RelationTypeGroup.COMMON); | 65 | relation.setTypeGroup(RelationTypeGroup.COMMON); |
65 | } | 66 | } |
67 | + ConstraintValidator.validateFields(relation); | ||
66 | relationService.saveRelation(getTenantId(), relation); | 68 | relationService.saveRelation(getTenantId(), relation); |
67 | 69 | ||
68 | logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(), | 70 | logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(), |
@@ -48,7 +48,6 @@ import org.thingsboard.server.common.data.EntityType; | @@ -48,7 +48,6 @@ import org.thingsboard.server.common.data.EntityType; | ||
48 | import org.thingsboard.server.common.data.TenantProfile; | 48 | import org.thingsboard.server.common.data.TenantProfile; |
49 | import org.thingsboard.server.common.data.audit.ActionType; | 49 | import org.thingsboard.server.common.data.audit.ActionType; |
50 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 50 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
51 | -import org.thingsboard.server.common.data.id.CustomerId; | ||
52 | import org.thingsboard.server.common.data.id.DeviceId; | 51 | import org.thingsboard.server.common.data.id.DeviceId; |
53 | import org.thingsboard.server.common.data.id.EntityId; | 52 | import org.thingsboard.server.common.data.id.EntityId; |
54 | import org.thingsboard.server.common.data.id.EntityIdFactory; | 53 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
@@ -73,6 +72,7 @@ import org.thingsboard.server.common.data.kv.StringDataEntry; | @@ -73,6 +72,7 @@ import org.thingsboard.server.common.data.kv.StringDataEntry; | ||
73 | import org.thingsboard.server.common.data.kv.TsKvEntry; | 72 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
74 | import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; | 73 | import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; |
75 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; | 74 | import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
75 | +import org.thingsboard.server.dao.service.ConstraintValidator; | ||
76 | import org.thingsboard.server.dao.timeseries.TimeseriesService; | 76 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
77 | import org.thingsboard.server.queue.util.TbCoreComponent; | 77 | import org.thingsboard.server.queue.util.TbCoreComponent; |
78 | import org.thingsboard.server.service.security.AccessValidator; | 78 | import org.thingsboard.server.service.security.AccessValidator; |
@@ -138,7 +138,11 @@ public class TelemetryController extends BaseController { | @@ -138,7 +138,11 @@ public class TelemetryController extends BaseController { | ||
138 | @ResponseBody | 138 | @ResponseBody |
139 | public DeferredResult<ResponseEntity> getAttributeKeys( | 139 | public DeferredResult<ResponseEntity> getAttributeKeys( |
140 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr) throws ThingsboardException { | 140 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr) throws ThingsboardException { |
141 | - return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, this::getAttributeKeysCallback); | 141 | + try { |
142 | + return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, this::getAttributeKeysCallback); | ||
143 | + } catch (Exception e) { | ||
144 | + throw handleException(e); | ||
145 | + } | ||
142 | } | 146 | } |
143 | 147 | ||
144 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 148 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -147,8 +151,12 @@ public class TelemetryController extends BaseController { | @@ -147,8 +151,12 @@ public class TelemetryController extends BaseController { | ||
147 | public DeferredResult<ResponseEntity> getAttributeKeysByScope( | 151 | public DeferredResult<ResponseEntity> getAttributeKeysByScope( |
148 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr | 152 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr |
149 | , @PathVariable("scope") String scope) throws ThingsboardException { | 153 | , @PathVariable("scope") String scope) throws ThingsboardException { |
150 | - return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, | ||
151 | - (result, tenantId, entityId) -> getAttributeKeysCallback(result, tenantId, entityId, scope)); | 154 | + try { |
155 | + return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, | ||
156 | + (result, tenantId, entityId) -> getAttributeKeysCallback(result, tenantId, entityId, scope)); | ||
157 | + } catch (Exception e) { | ||
158 | + throw handleException(e); | ||
159 | + } | ||
152 | } | 160 | } |
153 | 161 | ||
154 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 162 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -157,9 +165,13 @@ public class TelemetryController extends BaseController { | @@ -157,9 +165,13 @@ public class TelemetryController extends BaseController { | ||
157 | public DeferredResult<ResponseEntity> getAttributes( | 165 | public DeferredResult<ResponseEntity> getAttributes( |
158 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, | 166 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, |
159 | @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { | 167 | @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { |
160 | - SecurityUser user = getCurrentUser(); | ||
161 | - return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, | ||
162 | - (result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, null, keysStr)); | 168 | + try { |
169 | + SecurityUser user = getCurrentUser(); | ||
170 | + return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, | ||
171 | + (result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, null, keysStr)); | ||
172 | + } catch (Exception e) { | ||
173 | + throw handleException(e); | ||
174 | + } | ||
163 | } | 175 | } |
164 | 176 | ||
165 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 177 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -169,9 +181,13 @@ public class TelemetryController extends BaseController { | @@ -169,9 +181,13 @@ public class TelemetryController extends BaseController { | ||
169 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, | 181 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, |
170 | @PathVariable("scope") String scope, | 182 | @PathVariable("scope") String scope, |
171 | @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { | 183 | @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { |
172 | - SecurityUser user = getCurrentUser(); | ||
173 | - return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, | ||
174 | - (result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, scope, keysStr)); | 184 | + try { |
185 | + SecurityUser user = getCurrentUser(); | ||
186 | + return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, | ||
187 | + (result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, scope, keysStr)); | ||
188 | + } catch (Exception e) { | ||
189 | + throw handleException(e); | ||
190 | + } | ||
175 | } | 191 | } |
176 | 192 | ||
177 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 193 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -179,8 +195,12 @@ public class TelemetryController extends BaseController { | @@ -179,8 +195,12 @@ public class TelemetryController extends BaseController { | ||
179 | @ResponseBody | 195 | @ResponseBody |
180 | public DeferredResult<ResponseEntity> getTimeseriesKeys( | 196 | public DeferredResult<ResponseEntity> getTimeseriesKeys( |
181 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr) throws ThingsboardException { | 197 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr) throws ThingsboardException { |
182 | - return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, | ||
183 | - (result, tenantId, entityId) -> Futures.addCallback(tsService.findAllLatest(tenantId, entityId), getTsKeysToResponseCallback(result), MoreExecutors.directExecutor())); | 198 | + try { |
199 | + return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, | ||
200 | + (result, tenantId, entityId) -> Futures.addCallback(tsService.findAllLatest(tenantId, entityId), getTsKeysToResponseCallback(result), MoreExecutors.directExecutor())); | ||
201 | + } catch (Exception e) { | ||
202 | + throw handleException(e); | ||
203 | + } | ||
184 | } | 204 | } |
185 | 205 | ||
186 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 206 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -190,10 +210,14 @@ public class TelemetryController extends BaseController { | @@ -190,10 +210,14 @@ public class TelemetryController extends BaseController { | ||
190 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, | 210 | @PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, |
191 | @RequestParam(name = "keys", required = false) String keysStr, | 211 | @RequestParam(name = "keys", required = false) String keysStr, |
192 | @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException { | 212 | @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException { |
193 | - SecurityUser user = getCurrentUser(); | 213 | + try { |
214 | + SecurityUser user = getCurrentUser(); | ||
194 | 215 | ||
195 | - return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, | ||
196 | - (result, tenantId, entityId) -> getLatestTimeseriesValuesCallback(result, user, entityId, keysStr, useStrictDataTypes)); | 216 | + return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, |
217 | + (result, tenantId, entityId) -> getLatestTimeseriesValuesCallback(result, user, entityId, keysStr, useStrictDataTypes)); | ||
218 | + } catch (Exception e) { | ||
219 | + throw handleException(e); | ||
220 | + } | ||
197 | } | 221 | } |
198 | 222 | ||
199 | 223 | ||
@@ -211,15 +235,19 @@ public class TelemetryController extends BaseController { | @@ -211,15 +235,19 @@ public class TelemetryController extends BaseController { | ||
211 | @RequestParam(name = "agg", defaultValue = "NONE") String aggStr, | 235 | @RequestParam(name = "agg", defaultValue = "NONE") String aggStr, |
212 | @RequestParam(name = "orderBy", defaultValue = "DESC") String orderBy, | 236 | @RequestParam(name = "orderBy", defaultValue = "DESC") String orderBy, |
213 | @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException { | 237 | @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException { |
214 | - return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, | ||
215 | - (result, tenantId, entityId) -> { | ||
216 | - // If interval is 0, convert this to a NONE aggregation, which is probably what the user really wanted | ||
217 | - Aggregation agg = interval == 0L ? Aggregation.valueOf(Aggregation.NONE.name()) : Aggregation.valueOf(aggStr); | ||
218 | - List<ReadTsKvQuery> queries = toKeysList(keys).stream().map(key -> new BaseReadTsKvQuery(key, startTs, endTs, interval, limit, agg, orderBy)) | ||
219 | - .collect(Collectors.toList()); | ||
220 | - | ||
221 | - Futures.addCallback(tsService.findAll(tenantId, entityId, queries), getTsKvListCallback(result, useStrictDataTypes), MoreExecutors.directExecutor()); | ||
222 | - }); | 238 | + try { |
239 | + return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, | ||
240 | + (result, tenantId, entityId) -> { | ||
241 | + // If interval is 0, convert this to a NONE aggregation, which is probably what the user really wanted | ||
242 | + Aggregation agg = interval == 0L ? Aggregation.valueOf(Aggregation.NONE.name()) : Aggregation.valueOf(aggStr); | ||
243 | + List<ReadTsKvQuery> queries = toKeysList(keys).stream().map(key -> new BaseReadTsKvQuery(key, startTs, endTs, interval, limit, agg, orderBy)) | ||
244 | + .collect(Collectors.toList()); | ||
245 | + | ||
246 | + Futures.addCallback(tsService.findAll(tenantId, entityId, queries), getTsKvListCallback(result, useStrictDataTypes), MoreExecutors.directExecutor()); | ||
247 | + }); | ||
248 | + } catch (Exception e) { | ||
249 | + throw handleException(e); | ||
250 | + } | ||
223 | } | 251 | } |
224 | 252 | ||
225 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 253 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -227,8 +255,12 @@ public class TelemetryController extends BaseController { | @@ -227,8 +255,12 @@ public class TelemetryController extends BaseController { | ||
227 | @ResponseBody | 255 | @ResponseBody |
228 | public DeferredResult<ResponseEntity> saveDeviceAttributes(@PathVariable("deviceId") String deviceIdStr, @PathVariable("scope") String scope, | 256 | public DeferredResult<ResponseEntity> saveDeviceAttributes(@PathVariable("deviceId") String deviceIdStr, @PathVariable("scope") String scope, |
229 | @RequestBody JsonNode request) throws ThingsboardException { | 257 | @RequestBody JsonNode request) throws ThingsboardException { |
230 | - EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr); | ||
231 | - return saveAttributes(getTenantId(), entityId, scope, request); | 258 | + try { |
259 | + EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr); | ||
260 | + return saveAttributes(getTenantId(), entityId, scope, request); | ||
261 | + } catch (Exception e) { | ||
262 | + throw handleException(e); | ||
263 | + } | ||
232 | } | 264 | } |
233 | 265 | ||
234 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 266 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -237,8 +269,12 @@ public class TelemetryController extends BaseController { | @@ -237,8 +269,12 @@ public class TelemetryController extends BaseController { | ||
237 | public DeferredResult<ResponseEntity> saveEntityAttributesV1(@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, | 269 | public DeferredResult<ResponseEntity> saveEntityAttributesV1(@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, |
238 | @PathVariable("scope") String scope, | 270 | @PathVariable("scope") String scope, |
239 | @RequestBody JsonNode request) throws ThingsboardException { | 271 | @RequestBody JsonNode request) throws ThingsboardException { |
240 | - EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
241 | - return saveAttributes(getTenantId(), entityId, scope, request); | 272 | + try { |
273 | + EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
274 | + return saveAttributes(getTenantId(), entityId, scope, request); | ||
275 | + } catch (Exception e) { | ||
276 | + throw handleException(e); | ||
277 | + } | ||
242 | } | 278 | } |
243 | 279 | ||
244 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 280 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -247,8 +283,12 @@ public class TelemetryController extends BaseController { | @@ -247,8 +283,12 @@ public class TelemetryController extends BaseController { | ||
247 | public DeferredResult<ResponseEntity> saveEntityAttributesV2(@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, | 283 | public DeferredResult<ResponseEntity> saveEntityAttributesV2(@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, |
248 | @PathVariable("scope") String scope, | 284 | @PathVariable("scope") String scope, |
249 | @RequestBody JsonNode request) throws ThingsboardException { | 285 | @RequestBody JsonNode request) throws ThingsboardException { |
250 | - EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
251 | - return saveAttributes(getTenantId(), entityId, scope, request); | 286 | + try { |
287 | + EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
288 | + return saveAttributes(getTenantId(), entityId, scope, request); | ||
289 | + } catch (Exception e) { | ||
290 | + throw handleException(e); | ||
291 | + } | ||
252 | } | 292 | } |
253 | 293 | ||
254 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 294 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -257,8 +297,12 @@ public class TelemetryController extends BaseController { | @@ -257,8 +297,12 @@ public class TelemetryController extends BaseController { | ||
257 | public DeferredResult<ResponseEntity> saveEntityTelemetry(@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, | 297 | public DeferredResult<ResponseEntity> saveEntityTelemetry(@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, |
258 | @PathVariable("scope") String scope, | 298 | @PathVariable("scope") String scope, |
259 | @RequestBody String requestBody) throws ThingsboardException { | 299 | @RequestBody String requestBody) throws ThingsboardException { |
260 | - EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
261 | - return saveTelemetry(getTenantId(), entityId, requestBody, 0L); | 300 | + try { |
301 | + EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
302 | + return saveTelemetry(getTenantId(), entityId, requestBody, 0L); | ||
303 | + } catch (Exception e) { | ||
304 | + throw handleException(e); | ||
305 | + } | ||
262 | } | 306 | } |
263 | 307 | ||
264 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 308 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -267,8 +311,12 @@ public class TelemetryController extends BaseController { | @@ -267,8 +311,12 @@ public class TelemetryController extends BaseController { | ||
267 | public DeferredResult<ResponseEntity> saveEntityTelemetryWithTTL(@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, | 311 | public DeferredResult<ResponseEntity> saveEntityTelemetryWithTTL(@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, |
268 | @PathVariable("scope") String scope, @PathVariable("ttl") Long ttl, | 312 | @PathVariable("scope") String scope, @PathVariable("ttl") Long ttl, |
269 | @RequestBody String requestBody) throws ThingsboardException { | 313 | @RequestBody String requestBody) throws ThingsboardException { |
270 | - EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
271 | - return saveTelemetry(getTenantId(), entityId, requestBody, ttl); | 314 | + try { |
315 | + EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
316 | + return saveTelemetry(getTenantId(), entityId, requestBody, ttl); | ||
317 | + } catch (Exception e) { | ||
318 | + throw handleException(e); | ||
319 | + } | ||
272 | } | 320 | } |
273 | 321 | ||
274 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 322 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -280,8 +328,12 @@ public class TelemetryController extends BaseController { | @@ -280,8 +328,12 @@ public class TelemetryController extends BaseController { | ||
280 | @RequestParam(name = "startTs", required = false) Long startTs, | 328 | @RequestParam(name = "startTs", required = false) Long startTs, |
281 | @RequestParam(name = "endTs", required = false) Long endTs, | 329 | @RequestParam(name = "endTs", required = false) Long endTs, |
282 | @RequestParam(name = "rewriteLatestIfDeleted", defaultValue = "false") boolean rewriteLatestIfDeleted) throws ThingsboardException { | 330 | @RequestParam(name = "rewriteLatestIfDeleted", defaultValue = "false") boolean rewriteLatestIfDeleted) throws ThingsboardException { |
283 | - EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
284 | - return deleteTimeseries(entityId, keysStr, deleteAllDataForKeys, startTs, endTs, rewriteLatestIfDeleted); | 331 | + try { |
332 | + EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
333 | + return deleteTimeseries(entityId, keysStr, deleteAllDataForKeys, startTs, endTs, rewriteLatestIfDeleted); | ||
334 | + } catch (Exception e) { | ||
335 | + throw handleException(e); | ||
336 | + } | ||
285 | } | 337 | } |
286 | 338 | ||
287 | private DeferredResult<ResponseEntity> deleteTimeseries(EntityId entityIdStr, String keysStr, boolean deleteAllDataForKeys, | 339 | private DeferredResult<ResponseEntity> deleteTimeseries(EntityId entityIdStr, String keysStr, boolean deleteAllDataForKeys, |
@@ -335,8 +387,12 @@ public class TelemetryController extends BaseController { | @@ -335,8 +387,12 @@ public class TelemetryController extends BaseController { | ||
335 | public DeferredResult<ResponseEntity> deleteEntityAttributes(@PathVariable("deviceId") String deviceIdStr, | 387 | public DeferredResult<ResponseEntity> deleteEntityAttributes(@PathVariable("deviceId") String deviceIdStr, |
336 | @PathVariable("scope") String scope, | 388 | @PathVariable("scope") String scope, |
337 | @RequestParam(name = "keys") String keysStr) throws ThingsboardException { | 389 | @RequestParam(name = "keys") String keysStr) throws ThingsboardException { |
338 | - EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr); | ||
339 | - return deleteAttributes(entityId, scope, keysStr); | 390 | + try { |
391 | + EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr); | ||
392 | + return deleteAttributes(entityId, scope, keysStr); | ||
393 | + } catch (Exception e) { | ||
394 | + throw handleException(e); | ||
395 | + } | ||
340 | } | 396 | } |
341 | 397 | ||
342 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 398 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
@@ -345,8 +401,12 @@ public class TelemetryController extends BaseController { | @@ -345,8 +401,12 @@ public class TelemetryController extends BaseController { | ||
345 | public DeferredResult<ResponseEntity> deleteEntityAttributes(@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, | 401 | public DeferredResult<ResponseEntity> deleteEntityAttributes(@PathVariable("entityType") String entityType, @PathVariable("entityId") String entityIdStr, |
346 | @PathVariable("scope") String scope, | 402 | @PathVariable("scope") String scope, |
347 | @RequestParam(name = "keys") String keysStr) throws ThingsboardException { | 403 | @RequestParam(name = "keys") String keysStr) throws ThingsboardException { |
348 | - EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
349 | - return deleteAttributes(entityId, scope, keysStr); | 404 | + try { |
405 | + EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); | ||
406 | + return deleteAttributes(entityId, scope, keysStr); | ||
407 | + } catch (Exception e) { | ||
408 | + throw handleException(e); | ||
409 | + } | ||
350 | } | 410 | } |
351 | 411 | ||
352 | private DeferredResult<ResponseEntity> deleteAttributes(EntityId entityIdSrc, String scope, String keysStr) throws ThingsboardException { | 412 | private DeferredResult<ResponseEntity> deleteAttributes(EntityId entityIdSrc, String scope, String keysStr) throws ThingsboardException { |
@@ -392,6 +452,7 @@ public class TelemetryController extends BaseController { | @@ -392,6 +452,7 @@ public class TelemetryController extends BaseController { | ||
392 | } | 452 | } |
393 | if (json.isObject()) { | 453 | if (json.isObject()) { |
394 | List<AttributeKvEntry> attributes = extractRequestAttributes(json); | 454 | List<AttributeKvEntry> attributes = extractRequestAttributes(json); |
455 | + attributes.forEach(ConstraintValidator::validateFields); | ||
395 | if (attributes.isEmpty()) { | 456 | if (attributes.isEmpty()) { |
396 | return getImmediateDeferredResult("No attributes data found in request body!", HttpStatus.BAD_REQUEST); | 457 | return getImmediateDeferredResult("No attributes data found in request body!", HttpStatus.BAD_REQUEST); |
397 | } | 458 | } |
@@ -17,30 +17,36 @@ package org.thingsboard.server.common.data; | @@ -17,30 +17,36 @@ package org.thingsboard.server.common.data; | ||
17 | 17 | ||
18 | import lombok.EqualsAndHashCode; | 18 | import lombok.EqualsAndHashCode; |
19 | import org.thingsboard.server.common.data.id.UUIDBased; | 19 | import org.thingsboard.server.common.data.id.UUIDBased; |
20 | +import org.thingsboard.server.common.data.validation.Length; | ||
20 | import org.thingsboard.server.common.data.validation.NoXss; | 21 | import org.thingsboard.server.common.data.validation.NoXss; |
21 | 22 | ||
22 | @EqualsAndHashCode(callSuper = true) | 23 | @EqualsAndHashCode(callSuper = true) |
23 | public abstract class ContactBased<I extends UUIDBased> extends SearchTextBasedWithAdditionalInfo<I> implements HasName { | 24 | public abstract class ContactBased<I extends UUIDBased> extends SearchTextBasedWithAdditionalInfo<I> implements HasName { |
24 | - | 25 | + |
25 | private static final long serialVersionUID = 5047448057830660988L; | 26 | private static final long serialVersionUID = 5047448057830660988L; |
26 | 27 | ||
28 | + @Length(fieldName = "country") | ||
27 | @NoXss | 29 | @NoXss |
28 | protected String country; | 30 | protected String country; |
31 | + @Length(fieldName = "state") | ||
29 | @NoXss | 32 | @NoXss |
30 | protected String state; | 33 | protected String state; |
34 | + @Length(fieldName = "city") | ||
31 | @NoXss | 35 | @NoXss |
32 | protected String city; | 36 | protected String city; |
33 | @NoXss | 37 | @NoXss |
34 | protected String address; | 38 | protected String address; |
35 | @NoXss | 39 | @NoXss |
36 | protected String address2; | 40 | protected String address2; |
41 | + @Length(fieldName = "zip or postal code") | ||
37 | @NoXss | 42 | @NoXss |
38 | protected String zip; | 43 | protected String zip; |
44 | + @Length(fieldName = "phone") | ||
39 | @NoXss | 45 | @NoXss |
40 | protected String phone; | 46 | protected String phone; |
41 | @NoXss | 47 | @NoXss |
42 | protected String email; | 48 | protected String email; |
43 | - | 49 | + |
44 | public ContactBased() { | 50 | public ContactBased() { |
45 | super(); | 51 | super(); |
46 | } | 52 | } |
@@ -48,7 +54,7 @@ public abstract class ContactBased<I extends UUIDBased> extends SearchTextBasedW | @@ -48,7 +54,7 @@ public abstract class ContactBased<I extends UUIDBased> extends SearchTextBasedW | ||
48 | public ContactBased(I id) { | 54 | public ContactBased(I id) { |
49 | super(id); | 55 | super(id); |
50 | } | 56 | } |
51 | - | 57 | + |
52 | public ContactBased(ContactBased<I> contact) { | 58 | public ContactBased(ContactBased<I> contact) { |
53 | super(contact); | 59 | super(contact); |
54 | this.country = contact.getCountry(); | 60 | this.country = contact.getCountry(); |
@@ -20,13 +20,15 @@ import com.fasterxml.jackson.annotation.JsonProperty; | @@ -20,13 +20,15 @@ import com.fasterxml.jackson.annotation.JsonProperty; | ||
20 | import com.fasterxml.jackson.annotation.JsonProperty.Access; | 20 | import com.fasterxml.jackson.annotation.JsonProperty.Access; |
21 | import org.thingsboard.server.common.data.id.CustomerId; | 21 | import org.thingsboard.server.common.data.id.CustomerId; |
22 | import org.thingsboard.server.common.data.id.TenantId; | 22 | import org.thingsboard.server.common.data.id.TenantId; |
23 | +import org.thingsboard.server.common.data.validation.Length; | ||
23 | import org.thingsboard.server.common.data.validation.NoXss; | 24 | import org.thingsboard.server.common.data.validation.NoXss; |
24 | 25 | ||
25 | public class Customer extends ContactBased<CustomerId> implements HasTenantId { | 26 | public class Customer extends ContactBased<CustomerId> implements HasTenantId { |
26 | - | 27 | + |
27 | private static final long serialVersionUID = -1599722990298929275L; | 28 | private static final long serialVersionUID = -1599722990298929275L; |
28 | 29 | ||
29 | @NoXss | 30 | @NoXss |
31 | + @Length(fieldName = "title") | ||
30 | private String title; | 32 | private String title; |
31 | private TenantId tenantId; | 33 | private TenantId tenantId; |
32 | 34 | ||
@@ -37,7 +39,7 @@ public class Customer extends ContactBased<CustomerId> implements HasTenantId { | @@ -37,7 +39,7 @@ public class Customer extends ContactBased<CustomerId> implements HasTenantId { | ||
37 | public Customer(CustomerId id) { | 39 | public Customer(CustomerId id) { |
38 | super(id); | 40 | super(id); |
39 | } | 41 | } |
40 | - | 42 | + |
41 | public Customer(Customer customer) { | 43 | public Customer(Customer customer) { |
42 | super(customer); | 44 | super(customer); |
43 | this.tenantId = customer.getTenantId(); | 45 | this.tenantId = customer.getTenantId(); |
@@ -51,7 +53,7 @@ public class Customer extends ContactBased<CustomerId> implements HasTenantId { | @@ -51,7 +53,7 @@ public class Customer extends ContactBased<CustomerId> implements HasTenantId { | ||
51 | public void setTenantId(TenantId tenantId) { | 53 | public void setTenantId(TenantId tenantId) { |
52 | this.tenantId = tenantId; | 54 | this.tenantId = tenantId; |
53 | } | 55 | } |
54 | - | 56 | + |
55 | public String getTitle() { | 57 | public String getTitle() { |
56 | return title; | 58 | return title; |
57 | } | 59 | } |
@@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; | @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; | ||
19 | import org.thingsboard.server.common.data.id.CustomerId; | 19 | import org.thingsboard.server.common.data.id.CustomerId; |
20 | import org.thingsboard.server.common.data.id.DashboardId; | 20 | import org.thingsboard.server.common.data.id.DashboardId; |
21 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
22 | +import org.thingsboard.server.common.data.validation.Length; | ||
22 | import org.thingsboard.server.common.data.validation.NoXss; | 23 | import org.thingsboard.server.common.data.validation.NoXss; |
23 | 24 | ||
24 | import javax.validation.Valid; | 25 | import javax.validation.Valid; |
@@ -29,6 +30,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | @@ -29,6 +30,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa | ||
29 | 30 | ||
30 | private TenantId tenantId; | 31 | private TenantId tenantId; |
31 | @NoXss | 32 | @NoXss |
33 | + @Length(fieldName = "title") | ||
32 | private String title; | 34 | private String title; |
33 | private String image; | 35 | private String image; |
34 | @Valid | 36 | @Valid |
@@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.id.DeviceId; | @@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.id.DeviceId; | ||
25 | import org.thingsboard.server.common.data.id.DeviceProfileId; | 25 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
26 | import org.thingsboard.server.common.data.id.OtaPackageId; | 26 | import org.thingsboard.server.common.data.id.OtaPackageId; |
27 | import org.thingsboard.server.common.data.id.TenantId; | 27 | import org.thingsboard.server.common.data.id.TenantId; |
28 | +import org.thingsboard.server.common.data.validation.Length; | ||
28 | import org.thingsboard.server.common.data.validation.NoXss; | 29 | import org.thingsboard.server.common.data.validation.NoXss; |
29 | 30 | ||
30 | import java.io.ByteArrayInputStream; | 31 | import java.io.ByteArrayInputStream; |
@@ -39,10 +40,13 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen | @@ -39,10 +40,13 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen | ||
39 | private TenantId tenantId; | 40 | private TenantId tenantId; |
40 | private CustomerId customerId; | 41 | private CustomerId customerId; |
41 | @NoXss | 42 | @NoXss |
43 | + @Length(fieldName = "name") | ||
42 | private String name; | 44 | private String name; |
43 | @NoXss | 45 | @NoXss |
46 | + @Length(fieldName = "type") | ||
44 | private String type; | 47 | private String type; |
45 | @NoXss | 48 | @NoXss |
49 | + @Length(fieldName = "label") | ||
46 | private String label; | 50 | private String label; |
47 | private DeviceProfileId deviceProfileId; | 51 | private DeviceProfileId deviceProfileId; |
48 | private transient DeviceData deviceData; | 52 | private transient DeviceData deviceData; |
@@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.id.DeviceProfileId; | @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.id.DeviceProfileId; | ||
26 | import org.thingsboard.server.common.data.id.OtaPackageId; | 26 | import org.thingsboard.server.common.data.id.OtaPackageId; |
27 | import org.thingsboard.server.common.data.id.RuleChainId; | 27 | import org.thingsboard.server.common.data.id.RuleChainId; |
28 | import org.thingsboard.server.common.data.id.TenantId; | 28 | import org.thingsboard.server.common.data.id.TenantId; |
29 | +import org.thingsboard.server.common.data.validation.Length; | ||
29 | import org.thingsboard.server.common.data.validation.NoXss; | 30 | import org.thingsboard.server.common.data.validation.NoXss; |
30 | 31 | ||
31 | import javax.validation.Valid; | 32 | import javax.validation.Valid; |
@@ -41,6 +42,7 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | @@ -41,6 +42,7 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H | ||
41 | 42 | ||
42 | private TenantId tenantId; | 43 | private TenantId tenantId; |
43 | @NoXss | 44 | @NoXss |
45 | + @Length(fieldName = "name") | ||
44 | private String name; | 46 | private String name; |
45 | @NoXss | 47 | @NoXss |
46 | private String description; | 48 | private String description; |
@@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.id.EntityId; | @@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.id.EntityId; | ||
23 | import org.thingsboard.server.common.data.id.EntityViewId; | 23 | import org.thingsboard.server.common.data.id.EntityViewId; |
24 | import org.thingsboard.server.common.data.id.TenantId; | 24 | import org.thingsboard.server.common.data.id.TenantId; |
25 | import org.thingsboard.server.common.data.objects.TelemetryEntityView; | 25 | import org.thingsboard.server.common.data.objects.TelemetryEntityView; |
26 | +import org.thingsboard.server.common.data.validation.Length; | ||
26 | import org.thingsboard.server.common.data.validation.NoXss; | 27 | import org.thingsboard.server.common.data.validation.NoXss; |
27 | 28 | ||
28 | /** | 29 | /** |
@@ -41,8 +42,10 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId> | @@ -41,8 +42,10 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId> | ||
41 | private TenantId tenantId; | 42 | private TenantId tenantId; |
42 | private CustomerId customerId; | 43 | private CustomerId customerId; |
43 | @NoXss | 44 | @NoXss |
45 | + @Length(fieldName = "name") | ||
44 | private String name; | 46 | private String name; |
45 | @NoXss | 47 | @NoXss |
48 | + @Length(fieldName = "type") | ||
46 | private String type; | 49 | private String type; |
47 | private TelemetryEntityView keys; | 50 | private TelemetryEntityView keys; |
48 | private long startTimeMs; | 51 | private long startTimeMs; |
@@ -19,11 +19,12 @@ import com.fasterxml.jackson.annotation.JsonIgnore; | @@ -19,11 +19,12 @@ import com.fasterxml.jackson.annotation.JsonIgnore; | ||
19 | import lombok.Data; | 19 | import lombok.Data; |
20 | import lombok.EqualsAndHashCode; | 20 | import lombok.EqualsAndHashCode; |
21 | import lombok.extern.slf4j.Slf4j; | 21 | import lombok.extern.slf4j.Slf4j; |
22 | -import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; | ||
23 | -import org.thingsboard.server.common.data.ota.OtaPackageType; | ||
24 | import org.thingsboard.server.common.data.id.DeviceProfileId; | 22 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
25 | import org.thingsboard.server.common.data.id.OtaPackageId; | 23 | import org.thingsboard.server.common.data.id.OtaPackageId; |
26 | import org.thingsboard.server.common.data.id.TenantId; | 24 | import org.thingsboard.server.common.data.id.TenantId; |
25 | +import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; | ||
26 | +import org.thingsboard.server.common.data.ota.OtaPackageType; | ||
27 | +import org.thingsboard.server.common.data.validation.Length; | ||
27 | 28 | ||
28 | @Slf4j | 29 | @Slf4j |
29 | @Data | 30 | @Data |
@@ -35,10 +36,14 @@ public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackage | @@ -35,10 +36,14 @@ public class OtaPackageInfo extends SearchTextBasedWithAdditionalInfo<OtaPackage | ||
35 | private TenantId tenantId; | 36 | private TenantId tenantId; |
36 | private DeviceProfileId deviceProfileId; | 37 | private DeviceProfileId deviceProfileId; |
37 | private OtaPackageType type; | 38 | private OtaPackageType type; |
39 | + @Length(fieldName = "title") | ||
38 | private String title; | 40 | private String title; |
41 | + @Length(fieldName = "version") | ||
39 | private String version; | 42 | private String version; |
43 | + @Length(fieldName = "url") | ||
40 | private String url; | 44 | private String url; |
41 | private boolean hasData; | 45 | private boolean hasData; |
46 | + @Length(fieldName = "file name") | ||
42 | private String fileName; | 47 | private String fileName; |
43 | private String contentType; | 48 | private String contentType; |
44 | private ChecksumAlgorithm checksumAlgorithm; | 49 | private ChecksumAlgorithm checksumAlgorithm; |
@@ -19,6 +19,7 @@ import lombok.Data; | @@ -19,6 +19,7 @@ import lombok.Data; | ||
19 | import lombok.EqualsAndHashCode; | 19 | import lombok.EqualsAndHashCode; |
20 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
21 | import org.thingsboard.server.common.data.id.TbResourceId; | 21 | import org.thingsboard.server.common.data.id.TbResourceId; |
22 | +import org.thingsboard.server.common.data.validation.Length; | ||
22 | import org.thingsboard.server.common.data.validation.NoXss; | 23 | import org.thingsboard.server.common.data.validation.NoXss; |
23 | 24 | ||
24 | @Slf4j | 25 | @Slf4j |
@@ -29,6 +30,7 @@ public class TbResource extends TbResourceInfo { | @@ -29,6 +30,7 @@ public class TbResource extends TbResourceInfo { | ||
29 | private static final long serialVersionUID = 7379609705527272306L; | 30 | private static final long serialVersionUID = 7379609705527272306L; |
30 | 31 | ||
31 | @NoXss | 32 | @NoXss |
33 | + @Length(fieldName = "file name") | ||
32 | private String fileName; | 34 | private String fileName; |
33 | 35 | ||
34 | private String data; | 36 | private String data; |
@@ -21,6 +21,7 @@ import lombok.EqualsAndHashCode; | @@ -21,6 +21,7 @@ import lombok.EqualsAndHashCode; | ||
21 | import lombok.extern.slf4j.Slf4j; | 21 | import lombok.extern.slf4j.Slf4j; |
22 | import org.thingsboard.server.common.data.id.TbResourceId; | 22 | import org.thingsboard.server.common.data.id.TbResourceId; |
23 | import org.thingsboard.server.common.data.id.TenantId; | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | +import org.thingsboard.server.common.data.validation.Length; | ||
24 | import org.thingsboard.server.common.data.validation.NoXss; | 25 | import org.thingsboard.server.common.data.validation.NoXss; |
25 | 26 | ||
26 | @Slf4j | 27 | @Slf4j |
@@ -32,6 +33,7 @@ public class TbResourceInfo extends SearchTextBased<TbResourceId> implements Has | @@ -32,6 +33,7 @@ public class TbResourceInfo extends SearchTextBased<TbResourceId> implements Has | ||
32 | 33 | ||
33 | private TenantId tenantId; | 34 | private TenantId tenantId; |
34 | @NoXss | 35 | @NoXss |
36 | + @Length(fieldName = "title") | ||
35 | private String title; | 37 | private String title; |
36 | private ResourceType resourceType; | 38 | private ResourceType resourceType; |
37 | private String resourceKey; | 39 | private String resourceKey; |
@@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; | @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; | ||
20 | import lombok.EqualsAndHashCode; | 20 | import lombok.EqualsAndHashCode; |
21 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
22 | import org.thingsboard.server.common.data.id.TenantProfileId; | 22 | import org.thingsboard.server.common.data.id.TenantProfileId; |
23 | +import org.thingsboard.server.common.data.validation.Length; | ||
23 | import org.thingsboard.server.common.data.validation.NoXss; | 24 | import org.thingsboard.server.common.data.validation.NoXss; |
24 | 25 | ||
25 | @EqualsAndHashCode(callSuper = true) | 26 | @EqualsAndHashCode(callSuper = true) |
@@ -27,8 +28,10 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId { | @@ -27,8 +28,10 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId { | ||
27 | 28 | ||
28 | private static final long serialVersionUID = 8057243243859922101L; | 29 | private static final long serialVersionUID = 8057243243859922101L; |
29 | 30 | ||
31 | + @Length(fieldName = "title") | ||
30 | @NoXss | 32 | @NoXss |
31 | private String title; | 33 | private String title; |
34 | + @Length(fieldName = "region") | ||
32 | @NoXss | 35 | @NoXss |
33 | private String region; | 36 | private String region; |
34 | private TenantProfileId tenantProfileId; | 37 | private TenantProfileId tenantProfileId; |
@@ -40,7 +43,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId { | @@ -40,7 +43,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId { | ||
40 | public Tenant(TenantId id) { | 43 | public Tenant(TenantId id) { |
41 | super(id); | 44 | super(id); |
42 | } | 45 | } |
43 | - | 46 | + |
44 | public Tenant(Tenant tenant) { | 47 | public Tenant(Tenant tenant) { |
45 | super(tenant); | 48 | super(tenant); |
46 | this.title = tenant.getTitle(); | 49 | this.title = tenant.getTitle(); |
@@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j; | @@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j; | ||
23 | import org.thingsboard.server.common.data.id.TenantProfileId; | 23 | import org.thingsboard.server.common.data.id.TenantProfileId; |
24 | import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; | 24 | import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; |
25 | import org.thingsboard.server.common.data.tenant.profile.TenantProfileData; | 25 | import org.thingsboard.server.common.data.tenant.profile.TenantProfileData; |
26 | +import org.thingsboard.server.common.data.validation.Length; | ||
26 | import org.thingsboard.server.common.data.validation.NoXss; | 27 | import org.thingsboard.server.common.data.validation.NoXss; |
27 | 28 | ||
28 | import java.io.ByteArrayInputStream; | 29 | import java.io.ByteArrayInputStream; |
@@ -37,6 +38,7 @@ import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalIn | @@ -37,6 +38,7 @@ import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalIn | ||
37 | public class TenantProfile extends SearchTextBased<TenantProfileId> implements HasName { | 38 | public class TenantProfile extends SearchTextBased<TenantProfileId> implements HasName { |
38 | 39 | ||
39 | @NoXss | 40 | @NoXss |
41 | + @Length(fieldName = "name") | ||
40 | private String name; | 42 | private String name; |
41 | @NoXss | 43 | @NoXss |
42 | private String description; | 44 | private String description; |
@@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.id.EntityId; | @@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.id.EntityId; | ||
23 | import org.thingsboard.server.common.data.id.TenantId; | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | import org.thingsboard.server.common.data.id.UserId; | 24 | import org.thingsboard.server.common.data.id.UserId; |
25 | import org.thingsboard.server.common.data.security.Authority; | 25 | import org.thingsboard.server.common.data.security.Authority; |
26 | - | 26 | +import org.thingsboard.server.common.data.validation.Length; |
27 | import org.thingsboard.server.common.data.validation.NoXss; | 27 | import org.thingsboard.server.common.data.validation.NoXss; |
28 | 28 | ||
29 | @EqualsAndHashCode(callSuper = true) | 29 | @EqualsAndHashCode(callSuper = true) |
@@ -36,8 +36,10 @@ public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements H | @@ -36,8 +36,10 @@ public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements H | ||
36 | private String email; | 36 | private String email; |
37 | private Authority authority; | 37 | private Authority authority; |
38 | @NoXss | 38 | @NoXss |
39 | + @Length(fieldName = "firs name") | ||
39 | private String firstName; | 40 | private String firstName; |
40 | @NoXss | 41 | @NoXss |
42 | + @Length(fieldName = "last name") | ||
41 | private String lastName; | 43 | private String lastName; |
42 | 44 | ||
43 | public User() { | 45 | public User() { |
@@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.id.AlarmId; | @@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.id.AlarmId; | ||
28 | import org.thingsboard.server.common.data.id.CustomerId; | 28 | import org.thingsboard.server.common.data.id.CustomerId; |
29 | import org.thingsboard.server.common.data.id.EntityId; | 29 | import org.thingsboard.server.common.data.id.EntityId; |
30 | import org.thingsboard.server.common.data.id.TenantId; | 30 | import org.thingsboard.server.common.data.id.TenantId; |
31 | +import org.thingsboard.server.common.data.validation.Length; | ||
31 | 32 | ||
32 | import java.util.List; | 33 | import java.util.List; |
33 | 34 | ||
@@ -41,6 +42,7 @@ public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId, Ha | @@ -41,6 +42,7 @@ public class Alarm extends BaseData<AlarmId> implements HasName, HasTenantId, Ha | ||
41 | 42 | ||
42 | private TenantId tenantId; | 43 | private TenantId tenantId; |
43 | private CustomerId customerId; | 44 | private CustomerId customerId; |
45 | + @Length(fieldName = "type") | ||
44 | private String type; | 46 | private String type; |
45 | private EntityId originator; | 47 | private EntityId originator; |
46 | private AlarmSeverity severity; | 48 | private AlarmSeverity severity; |
@@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data.edge; | 16 | package org.thingsboard.server.common.data.edge; |
17 | 17 | ||
18 | -import com.fasterxml.jackson.databind.JsonNode; | ||
19 | import lombok.EqualsAndHashCode; | 18 | import lombok.EqualsAndHashCode; |
20 | import lombok.Getter; | 19 | import lombok.Getter; |
21 | import lombok.Setter; | 20 | import lombok.Setter; |
@@ -28,6 +27,7 @@ import org.thingsboard.server.common.data.id.CustomerId; | @@ -28,6 +27,7 @@ import org.thingsboard.server.common.data.id.CustomerId; | ||
28 | import org.thingsboard.server.common.data.id.EdgeId; | 27 | import org.thingsboard.server.common.data.id.EdgeId; |
29 | import org.thingsboard.server.common.data.id.RuleChainId; | 28 | import org.thingsboard.server.common.data.id.RuleChainId; |
30 | import org.thingsboard.server.common.data.id.TenantId; | 29 | import org.thingsboard.server.common.data.id.TenantId; |
30 | +import org.thingsboard.server.common.data.validation.Length; | ||
31 | 31 | ||
32 | @EqualsAndHashCode(callSuper = true) | 32 | @EqualsAndHashCode(callSuper = true) |
33 | @ToString | 33 | @ToString |
@@ -40,8 +40,11 @@ public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements H | @@ -40,8 +40,11 @@ public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements H | ||
40 | private TenantId tenantId; | 40 | private TenantId tenantId; |
41 | private CustomerId customerId; | 41 | private CustomerId customerId; |
42 | private RuleChainId rootRuleChainId; | 42 | private RuleChainId rootRuleChainId; |
43 | + @Length(fieldName = "name") | ||
43 | private String name; | 44 | private String name; |
45 | + @Length(fieldName = "type") | ||
44 | private String type; | 46 | private String type; |
47 | + @Length(fieldName = "label") | ||
45 | private String label; | 48 | private String label; |
46 | private String routingKey; | 49 | private String routingKey; |
47 | private String secret; | 50 | private String secret; |
@@ -15,8 +15,7 @@ | @@ -15,8 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data.kv; | 16 | package org.thingsboard.server.common.data.kv; |
17 | 17 | ||
18 | -import com.fasterxml.jackson.databind.JsonNode; | ||
19 | - | 18 | +import javax.validation.Valid; |
20 | import java.util.Optional; | 19 | import java.util.Optional; |
21 | 20 | ||
22 | /** | 21 | /** |
@@ -25,6 +24,7 @@ import java.util.Optional; | @@ -25,6 +24,7 @@ import java.util.Optional; | ||
25 | public class BaseAttributeKvEntry implements AttributeKvEntry { | 24 | public class BaseAttributeKvEntry implements AttributeKvEntry { |
26 | 25 | ||
27 | private final long lastUpdateTs; | 26 | private final long lastUpdateTs; |
27 | + @Valid | ||
28 | private final KvEntry kv; | 28 | private final KvEntry kv; |
29 | 29 | ||
30 | public BaseAttributeKvEntry(KvEntry kv, long lastUpdateTs) { | 30 | public BaseAttributeKvEntry(KvEntry kv, long lastUpdateTs) { |
@@ -15,11 +15,14 @@ | @@ -15,11 +15,14 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data.kv; | 16 | package org.thingsboard.server.common.data.kv; |
17 | 17 | ||
18 | +import org.thingsboard.server.common.data.validation.Length; | ||
19 | + | ||
18 | import java.util.Objects; | 20 | import java.util.Objects; |
19 | import java.util.Optional; | 21 | import java.util.Optional; |
20 | 22 | ||
21 | public abstract class BasicKvEntry implements KvEntry { | 23 | public abstract class BasicKvEntry implements KvEntry { |
22 | 24 | ||
25 | + @Length(fieldName = "attribute key") | ||
23 | private final String key; | 26 | private final String key; |
24 | 27 | ||
25 | protected BasicKvEntry(String key) { | 28 | protected BasicKvEntry(String key) { |
@@ -21,6 +21,7 @@ import java.util.Optional; | @@ -21,6 +21,7 @@ import java.util.Optional; | ||
21 | public class StringDataEntry extends BasicKvEntry { | 21 | public class StringDataEntry extends BasicKvEntry { |
22 | 22 | ||
23 | private static final long serialVersionUID = 1L; | 23 | private static final long serialVersionUID = 1L; |
24 | + | ||
24 | private final String value; | 25 | private final String value; |
25 | 26 | ||
26 | public StringDataEntry(String key, String value) { | 27 | public StringDataEntry(String key, String value) { |
@@ -16,15 +16,12 @@ | @@ -16,15 +16,12 @@ | ||
16 | package org.thingsboard.server.common.data.relation; | 16 | package org.thingsboard.server.common.data.relation; |
17 | 17 | ||
18 | import com.fasterxml.jackson.annotation.JsonIgnore; | 18 | import com.fasterxml.jackson.annotation.JsonIgnore; |
19 | -import com.fasterxml.jackson.core.JsonProcessingException; | ||
20 | import com.fasterxml.jackson.databind.JsonNode; | 19 | import com.fasterxml.jackson.databind.JsonNode; |
21 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
22 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
23 | import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; | 21 | import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; |
24 | import org.thingsboard.server.common.data.id.EntityId; | 22 | import org.thingsboard.server.common.data.id.EntityId; |
23 | +import org.thingsboard.server.common.data.validation.Length; | ||
25 | 24 | ||
26 | -import java.io.ByteArrayInputStream; | ||
27 | -import java.io.IOException; | ||
28 | import java.io.Serializable; | 25 | import java.io.Serializable; |
29 | 26 | ||
30 | @Slf4j | 27 | @Slf4j |
@@ -38,6 +35,7 @@ public class EntityRelation implements Serializable { | @@ -38,6 +35,7 @@ public class EntityRelation implements Serializable { | ||
38 | 35 | ||
39 | private EntityId from; | 36 | private EntityId from; |
40 | private EntityId to; | 37 | private EntityId to; |
38 | + @Length(fieldName = "type") | ||
41 | private String type; | 39 | private String type; |
42 | private RelationTypeGroup typeGroup; | 40 | private RelationTypeGroup typeGroup; |
43 | private transient JsonNode additionalInfo; | 41 | private transient JsonNode additionalInfo; |
@@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; | @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; | ||
26 | import org.thingsboard.server.common.data.id.RuleChainId; | 26 | import org.thingsboard.server.common.data.id.RuleChainId; |
27 | import org.thingsboard.server.common.data.id.RuleNodeId; | 27 | import org.thingsboard.server.common.data.id.RuleNodeId; |
28 | import org.thingsboard.server.common.data.id.TenantId; | 28 | import org.thingsboard.server.common.data.id.TenantId; |
29 | +import org.thingsboard.server.common.data.validation.Length; | ||
29 | import org.thingsboard.server.common.data.validation.NoXss; | 30 | import org.thingsboard.server.common.data.validation.NoXss; |
30 | 31 | ||
31 | @Data | 32 | @Data |
@@ -37,6 +38,7 @@ public class RuleChain extends SearchTextBasedWithAdditionalInfo<RuleChainId> im | @@ -37,6 +38,7 @@ public class RuleChain extends SearchTextBasedWithAdditionalInfo<RuleChainId> im | ||
37 | 38 | ||
38 | private TenantId tenantId; | 39 | private TenantId tenantId; |
39 | @NoXss | 40 | @NoXss |
41 | + @Length(fieldName = "name") | ||
40 | private String name; | 42 | private String name; |
41 | private RuleChainType type; | 43 | private RuleChainType type; |
42 | private RuleNodeId firstRuleNodeId; | 44 | private RuleNodeId firstRuleNodeId; |
@@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.HasName; | @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.HasName; | ||
24 | import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; | 24 | import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; |
25 | import org.thingsboard.server.common.data.id.RuleChainId; | 25 | import org.thingsboard.server.common.data.id.RuleChainId; |
26 | import org.thingsboard.server.common.data.id.RuleNodeId; | 26 | import org.thingsboard.server.common.data.id.RuleNodeId; |
27 | +import org.thingsboard.server.common.data.validation.Length; | ||
27 | 28 | ||
28 | @Data | 29 | @Data |
29 | @EqualsAndHashCode(callSuper = true) | 30 | @EqualsAndHashCode(callSuper = true) |
@@ -33,7 +34,9 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl | @@ -33,7 +34,9 @@ public class RuleNode extends SearchTextBasedWithAdditionalInfo<RuleNodeId> impl | ||
33 | private static final long serialVersionUID = -5656679015121235465L; | 34 | private static final long serialVersionUID = -5656679015121235465L; |
34 | 35 | ||
35 | private RuleChainId ruleChainId; | 36 | private RuleChainId ruleChainId; |
37 | + @Length(fieldName = "type") | ||
36 | private String type; | 38 | private String type; |
39 | + @Length(fieldName = "name") | ||
37 | private String name; | 40 | private String name; |
38 | private boolean debugMode; | 41 | private boolean debugMode; |
39 | private transient JsonNode configuration; | 42 | private transient JsonNode configuration; |
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data.validation; | ||
17 | + | ||
18 | +import javax.validation.Constraint; | ||
19 | +import javax.validation.Payload; | ||
20 | +import java.lang.annotation.ElementType; | ||
21 | +import java.lang.annotation.Retention; | ||
22 | +import java.lang.annotation.RetentionPolicy; | ||
23 | +import java.lang.annotation.Target; | ||
24 | + | ||
25 | +@Retention(RetentionPolicy.RUNTIME) | ||
26 | +@Target(ElementType.FIELD) | ||
27 | +@Constraint(validatedBy = {}) | ||
28 | +public @interface Length { | ||
29 | + String message() default "length of {fieldName} should be equals or less than {max}"; | ||
30 | + | ||
31 | + String fieldName(); | ||
32 | + | ||
33 | + int max() default 255; | ||
34 | + | ||
35 | + Class<?>[] groups() default {}; | ||
36 | + | ||
37 | + Class<? extends Payload>[] payload() default {}; | ||
38 | +} |
@@ -19,10 +19,9 @@ import org.thingsboard.server.common.data.HasTenantId; | @@ -19,10 +19,9 @@ import org.thingsboard.server.common.data.HasTenantId; | ||
19 | import org.thingsboard.server.common.data.SearchTextBased; | 19 | import org.thingsboard.server.common.data.SearchTextBased; |
20 | import org.thingsboard.server.common.data.id.TenantId; | 20 | import org.thingsboard.server.common.data.id.TenantId; |
21 | import org.thingsboard.server.common.data.id.WidgetsBundleId; | 21 | import org.thingsboard.server.common.data.id.WidgetsBundleId; |
22 | +import org.thingsboard.server.common.data.validation.Length; | ||
22 | import org.thingsboard.server.common.data.validation.NoXss; | 23 | import org.thingsboard.server.common.data.validation.NoXss; |
23 | 24 | ||
24 | -import java.util.Arrays; | ||
25 | - | ||
26 | public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements HasTenantId { | 25 | public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements HasTenantId { |
27 | 26 | ||
28 | private static final long serialVersionUID = -7627368878362410489L; | 27 | private static final long serialVersionUID = -7627368878362410489L; |
@@ -31,6 +30,7 @@ public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements H | @@ -31,6 +30,7 @@ public class WidgetsBundle extends SearchTextBased<WidgetsBundleId> implements H | ||
31 | @NoXss | 30 | @NoXss |
32 | private String alias; | 31 | private String alias; |
33 | @NoXss | 32 | @NoXss |
33 | + @Length(fieldName = "title") | ||
34 | private String title; | 34 | private String title; |
35 | private String image; | 35 | private String image; |
36 | @NoXss | 36 | @NoXss |
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.service; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.hibernate.validator.HibernateValidator; | ||
20 | +import org.hibernate.validator.HibernateValidatorConfiguration; | ||
21 | +import org.hibernate.validator.cfg.ConstraintMapping; | ||
22 | +import org.thingsboard.server.common.data.validation.Length; | ||
23 | +import org.thingsboard.server.common.data.validation.NoXss; | ||
24 | + | ||
25 | +import javax.validation.ConstraintViolation; | ||
26 | +import javax.validation.Validation; | ||
27 | +import javax.validation.ValidationException; | ||
28 | +import javax.validation.Validator; | ||
29 | +import java.util.List; | ||
30 | +import java.util.Set; | ||
31 | +import java.util.stream.Collectors; | ||
32 | + | ||
33 | +@Slf4j | ||
34 | +public class ConstraintValidator { | ||
35 | + | ||
36 | + private static Validator fieldsValidator; | ||
37 | + | ||
38 | + static { | ||
39 | + initializeValidators(); | ||
40 | + } | ||
41 | + | ||
42 | + public static void validateFields(Object data) { | ||
43 | + Set<ConstraintViolation<Object>> constraintsViolations = fieldsValidator.validate(data); | ||
44 | + List<String> validationErrors = constraintsViolations.stream() | ||
45 | + .map(ConstraintViolation::getMessage) | ||
46 | + .distinct() | ||
47 | + .collect(Collectors.toList()); | ||
48 | + if (!validationErrors.isEmpty()) { | ||
49 | + throw new ValidationException("Validation error: " + String.join(", ", validationErrors)); | ||
50 | + } | ||
51 | + } | ||
52 | + | ||
53 | + private static void initializeValidators() { | ||
54 | + HibernateValidatorConfiguration validatorConfiguration = Validation.byProvider(HibernateValidator.class).configure(); | ||
55 | + | ||
56 | + ConstraintMapping constraintMapping = validatorConfiguration.createConstraintMapping(); | ||
57 | + constraintMapping.constraintDefinition(NoXss.class).validatedBy(NoXssValidator.class); | ||
58 | + constraintMapping.constraintDefinition(Length.class).validatedBy(StringLengthValidator.class); | ||
59 | + validatorConfiguration.addMapping(constraintMapping); | ||
60 | + | ||
61 | + fieldsValidator = validatorConfiguration.buildValidatorFactory().getValidator(); | ||
62 | + } | ||
63 | +} |
@@ -17,51 +17,32 @@ package org.thingsboard.server.dao.service; | @@ -17,51 +17,32 @@ package org.thingsboard.server.dao.service; | ||
17 | 17 | ||
18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
20 | -import org.hibernate.validator.HibernateValidator; | ||
21 | -import org.hibernate.validator.HibernateValidatorConfiguration; | ||
22 | -import org.hibernate.validator.cfg.ConstraintMapping; | ||
23 | import org.thingsboard.server.common.data.BaseData; | 20 | import org.thingsboard.server.common.data.BaseData; |
24 | import org.thingsboard.server.common.data.EntityType; | 21 | import org.thingsboard.server.common.data.EntityType; |
25 | import org.thingsboard.server.common.data.id.TenantId; | 22 | import org.thingsboard.server.common.data.id.TenantId; |
26 | -import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; | ||
27 | -import org.thingsboard.server.common.data.validation.NoXss; | ||
28 | import org.thingsboard.server.dao.TenantEntityDao; | 23 | import org.thingsboard.server.dao.TenantEntityDao; |
29 | import org.thingsboard.server.dao.TenantEntityWithDataDao; | 24 | import org.thingsboard.server.dao.TenantEntityWithDataDao; |
30 | import org.thingsboard.server.dao.exception.DataValidationException; | 25 | import org.thingsboard.server.dao.exception.DataValidationException; |
31 | 26 | ||
32 | -import javax.validation.ConstraintViolation; | ||
33 | -import javax.validation.Validation; | ||
34 | -import javax.validation.Validator; | ||
35 | import java.util.HashSet; | 27 | import java.util.HashSet; |
36 | import java.util.Iterator; | 28 | import java.util.Iterator; |
37 | -import java.util.List; | ||
38 | import java.util.Set; | 29 | import java.util.Set; |
39 | import java.util.function.Function; | 30 | import java.util.function.Function; |
40 | import java.util.regex.Matcher; | 31 | import java.util.regex.Matcher; |
41 | import java.util.regex.Pattern; | 32 | import java.util.regex.Pattern; |
42 | -import java.util.stream.Collectors; | ||
43 | 33 | ||
44 | @Slf4j | 34 | @Slf4j |
45 | public abstract class DataValidator<D extends BaseData<?>> { | 35 | public abstract class DataValidator<D extends BaseData<?>> { |
46 | private static final Pattern EMAIL_PATTERN = | 36 | private static final Pattern EMAIL_PATTERN = |
47 | Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$", Pattern.CASE_INSENSITIVE); | 37 | Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$", Pattern.CASE_INSENSITIVE); |
48 | 38 | ||
49 | - private static Validator fieldsValidator; | ||
50 | - | ||
51 | - static { | ||
52 | - initializeFieldsValidator(); | ||
53 | - } | ||
54 | - | ||
55 | public void validate(D data, Function<D, TenantId> tenantIdFunction) { | 39 | public void validate(D data, Function<D, TenantId> tenantIdFunction) { |
56 | try { | 40 | try { |
57 | if (data == null) { | 41 | if (data == null) { |
58 | throw new DataValidationException("Data object can't be null!"); | 42 | throw new DataValidationException("Data object can't be null!"); |
59 | } | 43 | } |
60 | 44 | ||
61 | - List<String> validationErrors = validateFields(data); | ||
62 | - if (!validationErrors.isEmpty()) { | ||
63 | - throw new IllegalArgumentException("Validation error: " + String.join(", ", validationErrors)); | ||
64 | - } | 45 | + ConstraintValidator.validateFields(data); |
65 | 46 | ||
66 | TenantId tenantId = tenantIdFunction.apply(data); | 47 | TenantId tenantId = tenantIdFunction.apply(data); |
67 | validateDataImpl(tenantId, data); | 48 | validateDataImpl(tenantId, data); |
@@ -104,14 +85,6 @@ public abstract class DataValidator<D extends BaseData<?>> { | @@ -104,14 +85,6 @@ public abstract class DataValidator<D extends BaseData<?>> { | ||
104 | return emailMatcher.matches(); | 85 | return emailMatcher.matches(); |
105 | } | 86 | } |
106 | 87 | ||
107 | - private List<String> validateFields(D data) { | ||
108 | - Set<ConstraintViolation<D>> constraintsViolations = fieldsValidator.validate(data); | ||
109 | - return constraintsViolations.stream() | ||
110 | - .map(ConstraintViolation::getMessage) | ||
111 | - .distinct() | ||
112 | - .collect(Collectors.toList()); | ||
113 | - } | ||
114 | - | ||
115 | protected void validateNumberOfEntitiesPerTenant(TenantId tenantId, | 88 | protected void validateNumberOfEntitiesPerTenant(TenantId tenantId, |
116 | TenantEntityDao tenantEntityDao, | 89 | TenantEntityDao tenantEntityDao, |
117 | long maxEntities, | 90 | long maxEntities, |
@@ -126,10 +99,10 @@ public abstract class DataValidator<D extends BaseData<?>> { | @@ -126,10 +99,10 @@ public abstract class DataValidator<D extends BaseData<?>> { | ||
126 | } | 99 | } |
127 | 100 | ||
128 | protected void validateMaxSumDataSizePerTenant(TenantId tenantId, | 101 | protected void validateMaxSumDataSizePerTenant(TenantId tenantId, |
129 | - TenantEntityWithDataDao dataDao, | ||
130 | - long maxSumDataSize, | ||
131 | - long currentDataSize, | ||
132 | - EntityType entityType) { | 102 | + TenantEntityWithDataDao dataDao, |
103 | + long maxSumDataSize, | ||
104 | + long currentDataSize, | ||
105 | + EntityType entityType) { | ||
133 | if (maxSumDataSize > 0) { | 106 | if (maxSumDataSize > 0) { |
134 | if (dataDao.sumDataSizeByTenantId(tenantId) + currentDataSize > maxSumDataSize) { | 107 | if (dataDao.sumDataSizeByTenantId(tenantId) + currentDataSize > maxSumDataSize) { |
135 | throw new DataValidationException(String.format("Failed to create the %s, files size limit is exhausted %d bytes!", | 108 | throw new DataValidationException(String.format("Failed to create the %s, files size limit is exhausted %d bytes!", |
@@ -156,12 +129,4 @@ public abstract class DataValidator<D extends BaseData<?>> { | @@ -156,12 +129,4 @@ public abstract class DataValidator<D extends BaseData<?>> { | ||
156 | } | 129 | } |
157 | } | 130 | } |
158 | 131 | ||
159 | - private static void initializeFieldsValidator() { | ||
160 | - HibernateValidatorConfiguration validatorConfiguration = Validation.byProvider(HibernateValidator.class).configure(); | ||
161 | - ConstraintMapping constraintMapping = validatorConfiguration.createConstraintMapping(); | ||
162 | - constraintMapping.constraintDefinition(NoXss.class).validatedBy(NoXssValidator.class); | ||
163 | - validatorConfiguration.addMapping(constraintMapping); | ||
164 | - | ||
165 | - fieldsValidator = validatorConfiguration.buildValidatorFactory().getValidator(); | ||
166 | - } | ||
167 | } | 132 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.service; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.thingsboard.server.common.data.StringUtils; | ||
20 | +import org.thingsboard.server.common.data.validation.Length; | ||
21 | + | ||
22 | +import javax.validation.ConstraintValidator; | ||
23 | +import javax.validation.ConstraintValidatorContext; | ||
24 | + | ||
25 | +@Slf4j | ||
26 | +public class StringLengthValidator implements ConstraintValidator<Length, String> { | ||
27 | + private int max; | ||
28 | + | ||
29 | + @Override | ||
30 | + public boolean isValid(String value, ConstraintValidatorContext context) { | ||
31 | + if (StringUtils.isEmpty(value)) { | ||
32 | + return true; | ||
33 | + } | ||
34 | + return value.trim().length() <= max; | ||
35 | + } | ||
36 | + | ||
37 | + @Override | ||
38 | + public void initialize(Length constraintAnnotation) { | ||
39 | + this.max = constraintAnnotation.max(); | ||
40 | + } | ||
41 | +} |
@@ -36,6 +36,9 @@ | @@ -36,6 +36,9 @@ | ||
36 | <mat-error *ngIf="attributeFormGroup.get('key').hasError('required')"> | 36 | <mat-error *ngIf="attributeFormGroup.get('key').hasError('required')"> |
37 | {{ 'attribute.key-required' | translate }} | 37 | {{ 'attribute.key-required' | translate }} |
38 | </mat-error> | 38 | </mat-error> |
39 | + <mat-error *ngIf="attributeFormGroup.get('key').hasError('maxlength')"> | ||
40 | + {{ 'attribute.key-max-length' | translate }} | ||
41 | + </mat-error> | ||
39 | </mat-form-field> | 42 | </mat-form-field> |
40 | <tb-value-input | 43 | <tb-value-input |
41 | formControlName="value" | 44 | formControlName="value" |
@@ -56,7 +56,7 @@ export class AddAttributeDialogComponent extends DialogComponent<AddAttributeDia | @@ -56,7 +56,7 @@ export class AddAttributeDialogComponent extends DialogComponent<AddAttributeDia | ||
56 | 56 | ||
57 | ngOnInit(): void { | 57 | ngOnInit(): void { |
58 | this.attributeFormGroup = this.fb.group({ | 58 | this.attributeFormGroup = this.fb.group({ |
59 | - key: ['', [Validators.required]], | 59 | + key: ['', [Validators.required, Validators.maxLength(255)]], |
60 | value: [null, [Validators.required]] | 60 | value: [null, [Validators.required]] |
61 | }); | 61 | }); |
62 | } | 62 | } |
@@ -36,15 +36,15 @@ export abstract class ContactBasedComponent<T extends ContactBased<HasId>> exten | @@ -36,15 +36,15 @@ export abstract class ContactBasedComponent<T extends ContactBased<HasId>> exten | ||
36 | 36 | ||
37 | buildForm(entity: T): FormGroup { | 37 | buildForm(entity: T): FormGroup { |
38 | const entityForm = this.buildEntityForm(entity); | 38 | const entityForm = this.buildEntityForm(entity); |
39 | - entityForm.addControl('country', this.fb.control(entity ? entity.country : '', [])); | ||
40 | - entityForm.addControl('city', this.fb.control(entity ? entity.city : '', [])); | ||
41 | - entityForm.addControl('state', this.fb.control(entity ? entity.state : '', [])); | 39 | + entityForm.addControl('country', this.fb.control(entity ? entity.country : '', [Validators.maxLength(255)])); |
40 | + entityForm.addControl('city', this.fb.control(entity ? entity.city : '', [Validators.maxLength(255)])); | ||
41 | + entityForm.addControl('state', this.fb.control(entity ? entity.state : '', [Validators.maxLength(255)])); | ||
42 | entityForm.addControl('zip', this.fb.control(entity ? entity.zip : '', | 42 | entityForm.addControl('zip', this.fb.control(entity ? entity.zip : '', |
43 | this.zipValidators(entity ? entity.country : '') | 43 | this.zipValidators(entity ? entity.country : '') |
44 | )); | 44 | )); |
45 | entityForm.addControl('address', this.fb.control(entity ? entity.address : '', [])); | 45 | entityForm.addControl('address', this.fb.control(entity ? entity.address : '', [])); |
46 | entityForm.addControl('address2', this.fb.control(entity ? entity.address2 : '', [])); | 46 | entityForm.addControl('address2', this.fb.control(entity ? entity.address2 : '', [])); |
47 | - entityForm.addControl('phone', this.fb.control(entity ? entity.phone : '', [])); | 47 | + entityForm.addControl('phone', this.fb.control(entity ? entity.phone : '', [Validators.maxLength(255)])); |
48 | entityForm.addControl('email', this.fb.control(entity ? entity.email : '', [Validators.email])); | 48 | entityForm.addControl('email', this.fb.control(entity ? entity.email : '', [Validators.email])); |
49 | return entityForm; | 49 | return entityForm; |
50 | } | 50 | } |
@@ -41,6 +41,9 @@ | @@ -41,6 +41,9 @@ | ||
41 | <mat-error *ngIf="deviceProfileDetailsFormGroup.get('name').hasError('required')"> | 41 | <mat-error *ngIf="deviceProfileDetailsFormGroup.get('name').hasError('required')"> |
42 | {{ 'device-profile.name-required' | translate }} | 42 | {{ 'device-profile.name-required' | translate }} |
43 | </mat-error> | 43 | </mat-error> |
44 | + <mat-error *ngIf="deviceProfileDetailsFormGroup.get('name').hasError('maxlength')"> | ||
45 | + {{ 'device-profile.name-max-length' | translate }} | ||
46 | + </mat-error> | ||
44 | </mat-form-field> | 47 | </mat-form-field> |
45 | <tb-rule-chain-autocomplete | 48 | <tb-rule-chain-autocomplete |
46 | labelText="device-profile.default-rule-chain" | 49 | labelText="device-profile.default-rule-chain" |
@@ -105,7 +105,7 @@ export class AddDeviceProfileDialogComponent extends | @@ -105,7 +105,7 @@ export class AddDeviceProfileDialogComponent extends | ||
105 | super(store, router, dialogRef); | 105 | super(store, router, dialogRef); |
106 | this.deviceProfileDetailsFormGroup = this.fb.group( | 106 | this.deviceProfileDetailsFormGroup = this.fb.group( |
107 | { | 107 | { |
108 | - name: [data.deviceProfileName, [Validators.required]], | 108 | + name: [data.deviceProfileName, [Validators.required, Validators.maxLength(255)]], |
109 | type: [DeviceProfileType.DEFAULT, [Validators.required]], | 109 | type: [DeviceProfileType.DEFAULT, [Validators.required]], |
110 | image: [null, []], | 110 | image: [null, []], |
111 | defaultRuleChainId: [null, []], | 111 | defaultRuleChainId: [null, []], |
@@ -54,6 +54,9 @@ | @@ -54,6 +54,9 @@ | ||
54 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> | 54 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> |
55 | {{ 'device-profile.name-required' | translate }} | 55 | {{ 'device-profile.name-required' | translate }} |
56 | </mat-error> | 56 | </mat-error> |
57 | + <mat-error *ngIf="entityForm.get('name').hasError('maxlength')"> | ||
58 | + {{ 'device-profile.name-max-length' | translate }} | ||
59 | + </mat-error> | ||
57 | </mat-form-field> | 60 | </mat-form-field> |
58 | <tb-rule-chain-autocomplete | 61 | <tb-rule-chain-autocomplete |
59 | labelText="device-profile.default-rule-chain" | 62 | labelText="device-profile.default-rule-chain" |
@@ -102,7 +102,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { | @@ -102,7 +102,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { | ||
102 | }; | 102 | }; |
103 | const form = this.fb.group( | 103 | const form = this.fb.group( |
104 | { | 104 | { |
105 | - name: [entity ? entity.name : '', [Validators.required]], | 105 | + name: [entity ? entity.name : '', [Validators.required, Validators.maxLength(255)]], |
106 | type: [entity ? entity.type : null, [Validators.required]], | 106 | type: [entity ? entity.type : null, [Validators.required]], |
107 | image: [entity ? entity.image : null], | 107 | image: [entity ? entity.image : null], |
108 | transportType: [entity ? entity.transportType : null, [Validators.required]], | 108 | transportType: [entity ? entity.transportType : null, [Validators.required]], |
@@ -48,6 +48,9 @@ | @@ -48,6 +48,9 @@ | ||
48 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> | 48 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> |
49 | {{ 'tenant-profile.name-required' | translate }} | 49 | {{ 'tenant-profile.name-required' | translate }} |
50 | </mat-error> | 50 | </mat-error> |
51 | + <mat-error *ngIf="entityForm.get('name').hasError('maxlength')"> | ||
52 | + {{ 'tenant-profile.name-max-length' | translate }} | ||
53 | + </mat-error> | ||
51 | </mat-form-field> | 54 | </mat-form-field> |
52 | <div fxLayout="column"> | 55 | <div fxLayout="column"> |
53 | <mat-checkbox class="hinted-checkbox" formControlName="isolatedTbCore"> | 56 | <mat-checkbox class="hinted-checkbox" formControlName="isolatedTbCore"> |
@@ -58,7 +58,7 @@ export class TenantProfileComponent extends EntityComponent<TenantProfile> { | @@ -58,7 +58,7 @@ export class TenantProfileComponent extends EntityComponent<TenantProfile> { | ||
58 | buildForm(entity: TenantProfile): FormGroup { | 58 | buildForm(entity: TenantProfile): FormGroup { |
59 | return this.fb.group( | 59 | return this.fb.group( |
60 | { | 60 | { |
61 | - name: [entity ? entity.name : '', [Validators.required]], | 61 | + name: [entity ? entity.name : '', [Validators.required, Validators.maxLength(255)]], |
62 | isolatedTbCore: [entity ? entity.isolatedTbCore : false, []], | 62 | isolatedTbCore: [entity ? entity.isolatedTbCore : false, []], |
63 | isolatedTbRuleEngine: [entity ? entity.isolatedTbRuleEngine : false, []], | 63 | isolatedTbRuleEngine: [entity ? entity.isolatedTbRuleEngine : false, []], |
64 | profileData: [entity && !this.isAdd ? entity.profileData : { | 64 | profileData: [entity && !this.isAdd ? entity.profileData : { |
@@ -44,10 +44,16 @@ | @@ -44,10 +44,16 @@ | ||
44 | <mat-error *ngIf="deviceWizardFormGroup.get('name').hasError('required')"> | 44 | <mat-error *ngIf="deviceWizardFormGroup.get('name').hasError('required')"> |
45 | {{ 'device.name-required' | translate }} | 45 | {{ 'device.name-required' | translate }} |
46 | </mat-error> | 46 | </mat-error> |
47 | + <mat-error *ngIf="deviceWizardFormGroup.get('name').hasError('maxlength')"> | ||
48 | + {{ 'device.name-max-length' | translate }} | ||
49 | + </mat-error> | ||
47 | </mat-form-field> | 50 | </mat-form-field> |
48 | <mat-form-field class="mat-block"> | 51 | <mat-form-field class="mat-block"> |
49 | <mat-label translate>device.label</mat-label> | 52 | <mat-label translate>device.label</mat-label> |
50 | <input matInput formControlName="label"> | 53 | <input matInput formControlName="label"> |
54 | + <mat-error *ngIf="deviceWizardFormGroup.get('label').hasError('maxlength')"> | ||
55 | + {{ 'device.label-max-length' | translate }} | ||
56 | + </mat-error> | ||
51 | </mat-form-field> | 57 | </mat-form-field> |
52 | <div fxLayout="row" fxLayoutGap="16px"> | 58 | <div fxLayout="row" fxLayoutGap="16px"> |
53 | <mat-radio-group fxLayout="column" formControlName="addProfileType" fxLayoutAlign="space-around"> | 59 | <mat-radio-group fxLayout="column" formControlName="addProfileType" fxLayoutAlign="space-around"> |
@@ -105,8 +105,8 @@ export class DeviceWizardDialogComponent extends | @@ -105,8 +105,8 @@ export class DeviceWizardDialogComponent extends | ||
105 | private fb: FormBuilder) { | 105 | private fb: FormBuilder) { |
106 | super(store, router, dialogRef); | 106 | super(store, router, dialogRef); |
107 | this.deviceWizardFormGroup = this.fb.group({ | 107 | this.deviceWizardFormGroup = this.fb.group({ |
108 | - name: ['', Validators.required], | ||
109 | - label: [''], | 108 | + name: ['', [Validators.required, Validators.maxLength(255)]], |
109 | + label: ['', Validators.maxLength(255)], | ||
110 | gateway: [false], | 110 | gateway: [false], |
111 | overwriteActivityTime: [false], | 111 | overwriteActivityTime: [false], |
112 | addProfileType: [0], | 112 | addProfileType: [0], |
@@ -56,6 +56,9 @@ | @@ -56,6 +56,9 @@ | ||
56 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> | 56 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> |
57 | {{ 'resource.title-required' | translate }} | 57 | {{ 'resource.title-required' | translate }} |
58 | </mat-error> | 58 | </mat-error> |
59 | + <mat-error *ngIf="entityForm.get('title').hasError('maxlength')"> | ||
60 | + {{ 'resource.title-max-length' | translate }} | ||
61 | + </mat-error> | ||
59 | </mat-form-field> | 62 | </mat-form-field> |
60 | <tb-file-input *ngIf="isAdd" | 63 | <tb-file-input *ngIf="isAdd" |
61 | formControlName="data" | 64 | formControlName="data" |
@@ -29,7 +29,7 @@ import { | @@ -29,7 +29,7 @@ import { | ||
29 | ResourceTypeMIMETypes, | 29 | ResourceTypeMIMETypes, |
30 | ResourceTypeTranslationMap | 30 | ResourceTypeTranslationMap |
31 | } from '@shared/models/resource.models'; | 31 | } from '@shared/models/resource.models'; |
32 | -import { pairwise, startWith, takeUntil } from 'rxjs/operators'; | 32 | +import {filter, pairwise, startWith, takeUntil} from 'rxjs/operators'; |
33 | import { ActionNotificationShow } from "@core/notification/notification.actions"; | 33 | import { ActionNotificationShow } from "@core/notification/notification.actions"; |
34 | 34 | ||
35 | @Component({ | 35 | @Component({ |
@@ -56,16 +56,14 @@ export class ResourcesLibraryComponent extends EntityComponent<Resource> impleme | @@ -56,16 +56,14 @@ export class ResourcesLibraryComponent extends EntityComponent<Resource> impleme | ||
56 | super.ngOnInit(); | 56 | super.ngOnInit(); |
57 | this.entityForm.get('resourceType').valueChanges.pipe( | 57 | this.entityForm.get('resourceType').valueChanges.pipe( |
58 | startWith(ResourceType.LWM2M_MODEL), | 58 | startWith(ResourceType.LWM2M_MODEL), |
59 | - pairwise(), | 59 | + filter(() => this.isAdd), |
60 | takeUntil(this.destroy$) | 60 | takeUntil(this.destroy$) |
61 | - ).subscribe(([previousType, type]) => { | ||
62 | - if (previousType === this.resourceType.LWM2M_MODEL) { | ||
63 | - this.entityForm.get('title').setValidators(Validators.required); | ||
64 | - this.entityForm.get('title').updateValueAndValidity({emitEvent: false}); | ||
65 | - } | 61 | + ).subscribe((type) => { |
66 | if (type === this.resourceType.LWM2M_MODEL) { | 62 | if (type === this.resourceType.LWM2M_MODEL) { |
67 | - this.entityForm.get('title').clearValidators(); | ||
68 | - this.entityForm.get('title').updateValueAndValidity({emitEvent: false}); | 63 | + this.entityForm.get('title').disable({emitEvent: false}); |
64 | + this.entityForm.patchValue({title: ''}, {emitEvent: false}); | ||
65 | + } else { | ||
66 | + this.entityForm.get('title').enable({emitEvent: false}) | ||
69 | } | 67 | } |
70 | this.entityForm.patchValue({ | 68 | this.entityForm.patchValue({ |
71 | data: null, | 69 | data: null, |
@@ -91,11 +89,8 @@ export class ResourcesLibraryComponent extends EntityComponent<Resource> impleme | @@ -91,11 +89,8 @@ export class ResourcesLibraryComponent extends EntityComponent<Resource> impleme | ||
91 | buildForm(entity: Resource): FormGroup { | 89 | buildForm(entity: Resource): FormGroup { |
92 | const form = this.fb.group( | 90 | const form = this.fb.group( |
93 | { | 91 | { |
94 | - title: [entity ? entity.title : '', []], | ||
95 | - resourceType: [{ | ||
96 | - value: entity?.resourceType ? entity.resourceType : ResourceType.LWM2M_MODEL, | ||
97 | - disabled: !this.isAdd | ||
98 | - }, [Validators.required]], | 92 | + title: [entity ? entity.title : "", [Validators.required, Validators.maxLength(255)]], |
93 | + resourceType: [entity?.resourceType ? entity.resourceType : ResourceType.LWM2M_MODEL, [Validators.required]], | ||
99 | fileName: [entity ? entity.fileName : null, [Validators.required]], | 94 | fileName: [entity ? entity.fileName : null, [Validators.required]], |
100 | } | 95 | } |
101 | ); | 96 | ); |
@@ -76,6 +76,9 @@ | @@ -76,6 +76,9 @@ | ||
76 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> | 76 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> |
77 | {{ 'asset.name-required' | translate }} | 77 | {{ 'asset.name-required' | translate }} |
78 | </mat-error> | 78 | </mat-error> |
79 | + <mat-error *ngIf="entityForm.get('name').hasError('maxlength')"> | ||
80 | + {{ 'asset.name-max-length' | translate }} | ||
81 | + </mat-error> | ||
79 | </mat-form-field> | 82 | </mat-form-field> |
80 | <tb-entity-subtype-autocomplete | 83 | <tb-entity-subtype-autocomplete |
81 | formControlName="type" | 84 | formControlName="type" |
@@ -86,6 +89,9 @@ | @@ -86,6 +89,9 @@ | ||
86 | <mat-form-field class="mat-block"> | 89 | <mat-form-field class="mat-block"> |
87 | <mat-label translate>asset.label</mat-label> | 90 | <mat-label translate>asset.label</mat-label> |
88 | <input matInput formControlName="label"> | 91 | <input matInput formControlName="label"> |
92 | + <mat-error *ngIf="entityForm.get('label').hasError('maxlength')"> | ||
93 | + {{ 'asset.label-max-length' | translate }} | ||
94 | + </mat-error> | ||
89 | </mat-form-field> | 95 | </mat-form-field> |
90 | <div formGroupName="additionalInfo"> | 96 | <div formGroupName="additionalInfo"> |
91 | <mat-form-field class="mat-block"> | 97 | <mat-form-field class="mat-block"> |
@@ -65,9 +65,9 @@ export class AssetComponent extends EntityComponent<AssetInfo> { | @@ -65,9 +65,9 @@ export class AssetComponent extends EntityComponent<AssetInfo> { | ||
65 | buildForm(entity: AssetInfo): FormGroup { | 65 | buildForm(entity: AssetInfo): FormGroup { |
66 | return this.fb.group( | 66 | return this.fb.group( |
67 | { | 67 | { |
68 | - name: [entity ? entity.name : '', [Validators.required]], | ||
69 | - type: [entity ? entity.type : null, [Validators.required]], | ||
70 | - label: [entity ? entity.label : ''], | 68 | + name: [entity ? entity.name : '', [Validators.required, Validators.maxLength(255)]], |
69 | + type: [entity ? entity.type : null, [Validators.required, Validators.maxLength(255)]], | ||
70 | + label: [entity ? entity.label : '', Validators.maxLength(255)], | ||
71 | additionalInfo: this.fb.group( | 71 | additionalInfo: this.fb.group( |
72 | { | 72 | { |
73 | description: [entity && entity.additionalInfo ? entity.additionalInfo.description : ''], | 73 | description: [entity && entity.additionalInfo ? entity.additionalInfo.description : ''], |
@@ -73,6 +73,9 @@ | @@ -73,6 +73,9 @@ | ||
73 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> | 73 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> |
74 | {{ 'customer.title-required' | translate }} | 74 | {{ 'customer.title-required' | translate }} |
75 | </mat-error> | 75 | </mat-error> |
76 | + <mat-error *ngIf="entityForm.get('title').hasError('maxlength')"> | ||
77 | + {{ 'customer.title-max-length' | translate }} | ||
78 | + </mat-error> | ||
76 | </mat-form-field> | 79 | </mat-form-field> |
77 | <div formGroupName="additionalInfo" fxLayout="column"> | 80 | <div formGroupName="additionalInfo" fxLayout="column"> |
78 | <mat-form-field class="mat-block"> | 81 | <mat-form-field class="mat-block"> |
@@ -57,7 +57,7 @@ export class CustomerComponent extends ContactBasedComponent<Customer> { | @@ -57,7 +57,7 @@ export class CustomerComponent extends ContactBasedComponent<Customer> { | ||
57 | buildEntityForm(entity: Customer): FormGroup { | 57 | buildEntityForm(entity: Customer): FormGroup { |
58 | return this.fb.group( | 58 | return this.fb.group( |
59 | { | 59 | { |
60 | - title: [entity ? entity.title : '', [Validators.required]], | 60 | + title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]], |
61 | additionalInfo: this.fb.group( | 61 | additionalInfo: this.fb.group( |
62 | { | 62 | { |
63 | description: [entity && entity.additionalInfo ? entity.additionalInfo.description : ''], | 63 | description: [entity && entity.additionalInfo ? entity.additionalInfo.description : ''], |
@@ -104,6 +104,9 @@ | @@ -104,6 +104,9 @@ | ||
104 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> | 104 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> |
105 | {{ 'dashboard.title-required' | translate }} | 105 | {{ 'dashboard.title-required' | translate }} |
106 | </mat-error> | 106 | </mat-error> |
107 | + <mat-error *ngIf="entityForm.get('title').hasError('maxlength')"> | ||
108 | + {{ 'dashboard.title-max-length' | translate }} | ||
109 | + </mat-error> | ||
107 | </mat-form-field> | 110 | </mat-form-field> |
108 | <tb-image-input fxFlex | 111 | <tb-image-input fxFlex |
109 | label="{{'dashboard.image' | translate}}" | 112 | label="{{'dashboard.image' | translate}}" |
@@ -79,7 +79,7 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> { | @@ -79,7 +79,7 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> { | ||
79 | this.updateFields(entity); | 79 | this.updateFields(entity); |
80 | return this.fb.group( | 80 | return this.fb.group( |
81 | { | 81 | { |
82 | - title: [entity ? entity.title : '', [Validators.required]], | 82 | + title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]], |
83 | image: [entity ? entity.image : null], | 83 | image: [entity ? entity.image : null], |
84 | configuration: this.fb.group( | 84 | configuration: this.fb.group( |
85 | { | 85 | { |
@@ -89,6 +89,9 @@ | @@ -89,6 +89,9 @@ | ||
89 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> | 89 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> |
90 | {{ 'device.name-required' | translate }} | 90 | {{ 'device.name-required' | translate }} |
91 | </mat-error> | 91 | </mat-error> |
92 | + <mat-error *ngIf="entityForm.get('name').hasError('maxlength')"> | ||
93 | + {{ 'device.name-max-length' | translate }} | ||
94 | + </mat-error> | ||
92 | </mat-form-field> | 95 | </mat-form-field> |
93 | <tb-device-profile-autocomplete | 96 | <tb-device-profile-autocomplete |
94 | [selectDefaultProfile]="isAdd" | 97 | [selectDefaultProfile]="isAdd" |
@@ -100,6 +103,9 @@ | @@ -100,6 +103,9 @@ | ||
100 | <mat-form-field class="mat-block"> | 103 | <mat-form-field class="mat-block"> |
101 | <mat-label translate>device.label</mat-label> | 104 | <mat-label translate>device.label</mat-label> |
102 | <input matInput formControlName="label"> | 105 | <input matInput formControlName="label"> |
106 | + <mat-error *ngIf="entityForm.get('label').hasError('maxlength')"> | ||
107 | + {{ 'device.label-max-length' | translate }} | ||
108 | + </mat-error> | ||
103 | </mat-form-field> | 109 | </mat-form-field> |
104 | <tb-ota-package-autocomplete | 110 | <tb-ota-package-autocomplete |
105 | [useFullEntityId]="true" | 111 | [useFullEntityId]="true" |
@@ -81,11 +81,11 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> { | @@ -81,11 +81,11 @@ export class DeviceComponent extends EntityComponent<DeviceInfo> { | ||
81 | buildForm(entity: DeviceInfo): FormGroup { | 81 | buildForm(entity: DeviceInfo): FormGroup { |
82 | const form = this.fb.group( | 82 | const form = this.fb.group( |
83 | { | 83 | { |
84 | - name: [entity ? entity.name : '', [Validators.required]], | 84 | + name: [entity ? entity.name : '', [Validators.required, Validators.maxLength(255)]], |
85 | deviceProfileId: [entity ? entity.deviceProfileId : null, [Validators.required]], | 85 | deviceProfileId: [entity ? entity.deviceProfileId : null, [Validators.required]], |
86 | firmwareId: [entity ? entity.firmwareId : null], | 86 | firmwareId: [entity ? entity.firmwareId : null], |
87 | softwareId: [entity ? entity.softwareId : null], | 87 | softwareId: [entity ? entity.softwareId : null], |
88 | - label: [entity ? entity.label : ''], | 88 | + label: [entity ? entity.label : '', [Validators.maxLength(255)]], |
89 | deviceData: [entity ? entity.deviceData : null, [Validators.required]], | 89 | deviceData: [entity ? entity.deviceData : null, [Validators.required]], |
90 | additionalInfo: this.fb.group( | 90 | additionalInfo: this.fb.group( |
91 | { | 91 | { |
@@ -126,6 +126,9 @@ | @@ -126,6 +126,9 @@ | ||
126 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> | 126 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> |
127 | {{ 'edge.name-required' | translate }} | 127 | {{ 'edge.name-required' | translate }} |
128 | </mat-error> | 128 | </mat-error> |
129 | + <mat-error *ngIf="entityForm.get('name').hasError('maxlength')"> | ||
130 | + {{ 'edge.name-max-length' | translate }} | ||
131 | + </mat-error> | ||
129 | </mat-form-field> | 132 | </mat-form-field> |
130 | <tb-entity-subtype-autocomplete | 133 | <tb-entity-subtype-autocomplete |
131 | formControlName="type" | 134 | formControlName="type" |
@@ -140,6 +143,9 @@ | @@ -140,6 +143,9 @@ | ||
140 | <mat-error *ngIf="entityForm.get('edgeLicenseKey').hasError('required')"> | 143 | <mat-error *ngIf="entityForm.get('edgeLicenseKey').hasError('required')"> |
141 | {{ 'edge.edge-license-key-required' | translate }} | 144 | {{ 'edge.edge-license-key-required' | translate }} |
142 | </mat-error> | 145 | </mat-error> |
146 | + <mat-error *ngIf="entityForm.get('type').hasError('maxlength')"> | ||
147 | + {{ 'edge.type-max-length' | translate }} | ||
148 | + </mat-error> | ||
143 | </mat-form-field> | 149 | </mat-form-field> |
144 | </div> | 150 | </div> |
145 | <div [fxShow]="edgeScope !== 'customer_user'"> | 151 | <div [fxShow]="edgeScope !== 'customer_user'"> |
@@ -179,6 +185,9 @@ | @@ -179,6 +185,9 @@ | ||
179 | <mat-form-field class="mat-block"> | 185 | <mat-form-field class="mat-block"> |
180 | <mat-label translate>edge.label</mat-label> | 186 | <mat-label translate>edge.label</mat-label> |
181 | <input matInput formControlName="label"> | 187 | <input matInput formControlName="label"> |
188 | + <mat-error *ngIf="entityForm.get('label').hasError('maxlength')"> | ||
189 | + {{ 'edge.label-max-length' | translate }} | ||
190 | + </mat-error> | ||
182 | </mat-form-field> | 191 | </mat-form-field> |
183 | <div formGroupName="additionalInfo" fxLayout="column"> | 192 | <div formGroupName="additionalInfo" fxLayout="column"> |
184 | <mat-form-field class="mat-block"> | 193 | <mat-form-field class="mat-block"> |
@@ -69,9 +69,9 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> { | @@ -69,9 +69,9 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> { | ||
69 | buildForm(entity: EdgeInfo): FormGroup { | 69 | buildForm(entity: EdgeInfo): FormGroup { |
70 | const form = this.fb.group( | 70 | const form = this.fb.group( |
71 | { | 71 | { |
72 | - name: [entity ? entity.name : '', [Validators.required]], | ||
73 | - type: [entity?.type ? entity.type : 'default', [Validators.required]], | ||
74 | - label: [entity ? entity.label : ''], | 72 | + name: [entity ? entity.name : '', [Validators.required, Validators.maxLength(255)]], |
73 | + type: [entity?.type ? entity.type : 'default', [Validators.required, Validators.maxLength(255)]], | ||
74 | + label: [entity ? entity.label : '', Validators.maxLength(255)], | ||
75 | cloudEndpoint: [null, [Validators.required]], | 75 | cloudEndpoint: [null, [Validators.required]], |
76 | edgeLicenseKey: ['', [Validators.required]], | 76 | edgeLicenseKey: ['', [Validators.required]], |
77 | routingKey: this.fb.control({value: entity ? entity.routingKey : null, disabled: true}), | 77 | routingKey: this.fb.control({value: entity ? entity.routingKey : null, disabled: true}), |
@@ -76,6 +76,9 @@ | @@ -76,6 +76,9 @@ | ||
76 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> | 76 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> |
77 | {{ 'entity-view.name-required' | translate }} | 77 | {{ 'entity-view.name-required' | translate }} |
78 | </mat-error> | 78 | </mat-error> |
79 | + <mat-error *ngIf="entityForm.get('name').hasError('maxlength')"> | ||
80 | + {{ 'entity-view.name-max-length' | translate }} | ||
81 | + </mat-error> | ||
79 | </mat-form-field> | 82 | </mat-form-field> |
80 | <tb-entity-subtype-autocomplete | 83 | <tb-entity-subtype-autocomplete |
81 | formControlName="type" | 84 | formControlName="type" |
@@ -80,8 +80,8 @@ export class EntityViewComponent extends EntityComponent<EntityViewInfo> { | @@ -80,8 +80,8 @@ export class EntityViewComponent extends EntityComponent<EntityViewInfo> { | ||
80 | buildForm(entity: EntityViewInfo): FormGroup { | 80 | buildForm(entity: EntityViewInfo): FormGroup { |
81 | return this.fb.group( | 81 | return this.fb.group( |
82 | { | 82 | { |
83 | - name: [entity ? entity.name : '', [Validators.required]], | ||
84 | - type: [entity ? entity.type : null, [Validators.required]], | 83 | + name: [entity ? entity.name : '', [Validators.required, Validators.maxLength(255)]], |
84 | + type: [entity ? entity.type : null, Validators.required], | ||
85 | entityId: [entity ? entity.entityId : null, [Validators.required]], | 85 | entityId: [entity ? entity.entityId : null, [Validators.required]], |
86 | startTimeMs: [entity ? entity.startTimeMs : null], | 86 | startTimeMs: [entity ? entity.startTimeMs : null], |
87 | endTimeMs: [entity ? entity.endTimeMs : null], | 87 | endTimeMs: [entity ? entity.endTimeMs : null], |
@@ -65,6 +65,9 @@ | @@ -65,6 +65,9 @@ | ||
65 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> | 65 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> |
66 | {{ 'ota-update.title-required' | translate }} | 66 | {{ 'ota-update.title-required' | translate }} |
67 | </mat-error> | 67 | </mat-error> |
68 | + <mat-error *ngIf="entityForm.get('title').hasError('maxlength')"> | ||
69 | + {{ 'ota-update.title-max-length' | translate }} | ||
70 | + </mat-error> | ||
68 | </mat-form-field> | 71 | </mat-form-field> |
69 | <mat-form-field class="mat-block" fxFlex> | 72 | <mat-form-field class="mat-block" fxFlex> |
70 | <mat-label translate>ota-update.version</mat-label> | 73 | <mat-label translate>ota-update.version</mat-label> |
@@ -72,6 +75,9 @@ | @@ -72,6 +75,9 @@ | ||
72 | <mat-error *ngIf="entityForm.get('version').hasError('required')"> | 75 | <mat-error *ngIf="entityForm.get('version').hasError('required')"> |
73 | {{ 'ota-update.version-required' | translate }} | 76 | {{ 'ota-update.version-required' | translate }} |
74 | </mat-error> | 77 | </mat-error> |
78 | + <mat-error *ngIf="entityForm.get('version').hasError('maxlength')"> | ||
79 | + {{ 'ota-update.version-max-length' | translate }} | ||
80 | + </mat-error> | ||
75 | </mat-form-field> | 81 | </mat-form-field> |
76 | </div> | 82 | </div> |
77 | <tb-device-profile-autocomplete | 83 | <tb-device-profile-autocomplete |
@@ -111,7 +117,8 @@ | @@ -111,7 +117,8 @@ | ||
111 | </mat-checkbox> | 117 | </mat-checkbox> |
112 | </section> | 118 | </section> |
113 | <div fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayoutGap.sm="8px" | 119 | <div fxLayout="row" fxLayoutGap.gt-xs="8px" fxLayoutGap.sm="8px" |
114 | - fxLayout.xs="column" fxLayout.md="column" *ngIf="!(isAdd && this.entityForm.get('generateChecksum').value)"> | 120 | + fxLayout.xs="column" fxLayout.md="column" |
121 | + *ngIf="!(isAdd && this.entityForm.get('generateChecksum').value)"> | ||
115 | <mat-form-field class="mat-block" fxFlex="33"> | 122 | <mat-form-field class="mat-block" fxFlex="33"> |
116 | <mat-label translate>ota-update.checksum-algorithm</mat-label> | 123 | <mat-label translate>ota-update.checksum-algorithm</mat-label> |
117 | <mat-select formControlName="checksumAlgorithm"> | 124 | <mat-select formControlName="checksumAlgorithm"> |
@@ -149,7 +156,8 @@ | @@ -149,7 +156,8 @@ | ||
149 | <input matInput formControlName="url" | 156 | <input matInput formControlName="url" |
150 | type="text" | 157 | type="text" |
151 | [required]="entityForm.get('isURL').value"> | 158 | [required]="entityForm.get('isURL').value"> |
152 | - <mat-error *ngIf="entityForm.get('url').hasError('required') || entityForm.get('url').hasError('pattern')" translate> | 159 | + <mat-error *ngIf="entityForm.get('url').hasError('required') || entityForm.get('url').hasError('pattern')" |
160 | + translate> | ||
153 | ota-update.direct-url-required | 161 | ota-update.direct-url-required |
154 | </mat-error> | 162 | </mat-error> |
155 | </mat-form-field> | 163 | </mat-form-field> |
@@ -84,6 +84,9 @@ | @@ -84,6 +84,9 @@ | ||
84 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> | 84 | <mat-error *ngIf="entityForm.get('name').hasError('required')"> |
85 | {{ 'rulechain.name-required' | translate }} | 85 | {{ 'rulechain.name-required' | translate }} |
86 | </mat-error> | 86 | </mat-error> |
87 | + <mat-error *ngIf="entityForm.get('name').hasError('maxlength')"> | ||
88 | + {{ 'rulechain.name-max-length' | translate }} | ||
89 | + </mat-error> | ||
87 | </mat-form-field> | 90 | </mat-form-field> |
88 | <mat-checkbox fxFlex formControlName="debugMode" style="padding-bottom: 16px;"> | 91 | <mat-checkbox fxFlex formControlName="debugMode" style="padding-bottom: 16px;"> |
89 | {{ 'rulechain.debug-mode' | translate }} | 92 | {{ 'rulechain.debug-mode' | translate }} |
@@ -57,7 +57,7 @@ export class RuleChainComponent extends EntityComponent<RuleChain> { | @@ -57,7 +57,7 @@ export class RuleChainComponent extends EntityComponent<RuleChain> { | ||
57 | buildForm(entity: RuleChain): FormGroup { | 57 | buildForm(entity: RuleChain): FormGroup { |
58 | return this.fb.group( | 58 | return this.fb.group( |
59 | { | 59 | { |
60 | - name: [entity ? entity.name : '', [Validators.required]], | 60 | + name: [entity ? entity.name : '', [Validators.required, Validators.maxLength(255)]], |
61 | debugMode: [entity ? entity.debugMode : false], | 61 | debugMode: [entity ? entity.debugMode : false], |
62 | additionalInfo: this.fb.group( | 62 | additionalInfo: this.fb.group( |
63 | { | 63 | { |
@@ -48,6 +48,9 @@ | @@ -48,6 +48,9 @@ | ||
48 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> | 48 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> |
49 | {{ 'tenant.title-required' | translate }} | 49 | {{ 'tenant.title-required' | translate }} |
50 | </mat-error> | 50 | </mat-error> |
51 | + <mat-error *ngIf="entityForm.get('title').hasError('maxlength')"> | ||
52 | + {{ 'tenant.title-max-length' | translate }} | ||
53 | + </mat-error> | ||
51 | </mat-form-field> | 54 | </mat-form-field> |
52 | <tb-tenant-profile-autocomplete | 55 | <tb-tenant-profile-autocomplete |
53 | [selectDefaultProfile]="isAdd" | 56 | [selectDefaultProfile]="isAdd" |
@@ -51,7 +51,7 @@ export class TenantComponent extends ContactBasedComponent<TenantInfo> { | @@ -51,7 +51,7 @@ export class TenantComponent extends ContactBasedComponent<TenantInfo> { | ||
51 | buildEntityForm(entity: TenantInfo): FormGroup { | 51 | buildEntityForm(entity: TenantInfo): FormGroup { |
52 | return this.fb.group( | 52 | return this.fb.group( |
53 | { | 53 | { |
54 | - title: [entity ? entity.title : '', [Validators.required]], | 54 | + title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]], |
55 | tenantProfileId: [entity ? entity.tenantProfileId : null, [Validators.required]], | 55 | tenantProfileId: [entity ? entity.tenantProfileId : null, [Validators.required]], |
56 | additionalInfo: this.fb.group( | 56 | additionalInfo: this.fb.group( |
57 | { | 57 | { |
@@ -44,6 +44,9 @@ | @@ -44,6 +44,9 @@ | ||
44 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> | 44 | <mat-error *ngIf="entityForm.get('title').hasError('required')"> |
45 | {{ 'widgets-bundle.title-required' | translate }} | 45 | {{ 'widgets-bundle.title-required' | translate }} |
46 | </mat-error> | 46 | </mat-error> |
47 | + <mat-error *ngIf="entityForm.get('title').hasError('maxlength')"> | ||
48 | + {{ 'widgets-bundle.title-max-length' | translate }} | ||
49 | + </mat-error> | ||
47 | </mat-form-field> | 50 | </mat-form-field> |
48 | <tb-image-input fxFlex | 51 | <tb-image-input fxFlex |
49 | label="{{'widgets-bundle.image-preview' | translate}}" | 52 | label="{{'widgets-bundle.image-preview' | translate}}" |
@@ -47,7 +47,7 @@ export class WidgetsBundleComponent extends EntityComponent<WidgetsBundle> { | @@ -47,7 +47,7 @@ export class WidgetsBundleComponent extends EntityComponent<WidgetsBundle> { | ||
47 | buildForm(entity: WidgetsBundle): FormGroup { | 47 | buildForm(entity: WidgetsBundle): FormGroup { |
48 | return this.fb.group( | 48 | return this.fb.group( |
49 | { | 49 | { |
50 | - title: [entity ? entity.title : '', [Validators.required]], | 50 | + title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]], |
51 | image: [entity ? entity.image : ''], | 51 | image: [entity ? entity.image : ''], |
52 | description: [entity ? entity.description : '', Validators.maxLength(255)] | 52 | description: [entity ? entity.description : '', Validators.maxLength(255)] |
53 | } | 53 | } |
@@ -28,10 +28,16 @@ | @@ -28,10 +28,16 @@ | ||
28 | <mat-form-field class="mat-block"> | 28 | <mat-form-field class="mat-block"> |
29 | <mat-label translate>contact.city</mat-label> | 29 | <mat-label translate>contact.city</mat-label> |
30 | <input matInput formControlName="city"> | 30 | <input matInput formControlName="city"> |
31 | + <mat-error *ngIf="parentForm.get('city').hasError('maxlength')"> | ||
32 | + {{ 'contact.city-max-length' | translate }} | ||
33 | + </mat-error> | ||
31 | </mat-form-field> | 34 | </mat-form-field> |
32 | <mat-form-field class="mat-block"> | 35 | <mat-form-field class="mat-block"> |
33 | <mat-label translate>contact.state</mat-label> | 36 | <mat-label translate>contact.state</mat-label> |
34 | <input matInput formControlName="state"> | 37 | <input matInput formControlName="state"> |
38 | + <mat-error *ngIf="parentForm.get('state').hasError('maxlength')"> | ||
39 | + {{ 'contact.state-max-length' | translate }} | ||
40 | + </mat-error> | ||
35 | </mat-form-field> | 41 | </mat-form-field> |
36 | <mat-form-field class="mat-block"> | 42 | <mat-form-field class="mat-block"> |
37 | <mat-label translate>contact.postal-code</mat-label> | 43 | <mat-label translate>contact.postal-code</mat-label> |
@@ -52,6 +58,9 @@ | @@ -52,6 +58,9 @@ | ||
52 | <mat-form-field class="mat-block"> | 58 | <mat-form-field class="mat-block"> |
53 | <mat-label translate>contact.phone</mat-label> | 59 | <mat-label translate>contact.phone</mat-label> |
54 | <input matInput formControlName="phone"> | 60 | <input matInput formControlName="phone"> |
61 | + <mat-error *ngIf="parentForm.get('phone').hasError('maxlength')"> | ||
62 | + {{ 'contact.phone-max-length' | translate }} | ||
63 | + </mat-error> | ||
55 | </mat-form-field> | 64 | </mat-form-field> |
56 | <mat-form-field class="mat-block"> | 65 | <mat-form-field class="mat-block"> |
57 | <mat-label translate>contact.email</mat-label> | 66 | <mat-label translate>contact.email</mat-label> |
@@ -40,4 +40,7 @@ | @@ -40,4 +40,7 @@ | ||
40 | <mat-error *ngIf="subTypeFormGroup.get('subType').hasError('required')"> | 40 | <mat-error *ngIf="subTypeFormGroup.get('subType').hasError('required')"> |
41 | {{ entitySubtypeRequiredText | translate }} | 41 | {{ entitySubtypeRequiredText | translate }} |
42 | </mat-error> | 42 | </mat-error> |
43 | + <mat-error *ngIf="subTypeFormGroup.get('subType').hasError('maxlength')"> | ||
44 | + {{ entitySubtypeMaxLength | translate }} | ||
45 | + </mat-error> | ||
43 | </mat-form-field> | 46 | </mat-form-field> |
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | /// | 15 | /// |
16 | 16 | ||
17 | import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; | 17 | import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; |
18 | -import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; | 18 | +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; |
19 | import { Observable, of, Subscription, throwError } from 'rxjs'; | 19 | import { Observable, of, Subscription, throwError } from 'rxjs'; |
20 | import { | 20 | import { |
21 | catchError, | 21 | catchError, |
@@ -58,9 +58,11 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | @@ -58,9 +58,11 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | ||
58 | entityType: EntityType; | 58 | entityType: EntityType; |
59 | 59 | ||
60 | private requiredValue: boolean; | 60 | private requiredValue: boolean; |
61 | + | ||
61 | get required(): boolean { | 62 | get required(): boolean { |
62 | return this.requiredValue; | 63 | return this.requiredValue; |
63 | } | 64 | } |
65 | + | ||
64 | @Input() | 66 | @Input() |
65 | set required(value: boolean) { | 67 | set required(value: boolean) { |
66 | this.requiredValue = coerceBooleanProperty(value); | 68 | this.requiredValue = coerceBooleanProperty(value); |
@@ -74,6 +76,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | @@ -74,6 +76,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | ||
74 | selectEntitySubtypeText: string; | 76 | selectEntitySubtypeText: string; |
75 | entitySubtypeText: string; | 77 | entitySubtypeText: string; |
76 | entitySubtypeRequiredText: string; | 78 | entitySubtypeRequiredText: string; |
79 | + entitySubtypeMaxLength: string; | ||
77 | 80 | ||
78 | filteredSubTypes: Observable<Array<string>>; | 81 | filteredSubTypes: Observable<Array<string>>; |
79 | 82 | ||
@@ -96,7 +99,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | @@ -96,7 +99,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | ||
96 | private entityViewService: EntityViewService, | 99 | private entityViewService: EntityViewService, |
97 | private fb: FormBuilder) { | 100 | private fb: FormBuilder) { |
98 | this.subTypeFormGroup = this.fb.group({ | 101 | this.subTypeFormGroup = this.fb.group({ |
99 | - subType: [null] | 102 | + subType: [null, Validators.maxLength(255)] |
100 | }); | 103 | }); |
101 | } | 104 | } |
102 | 105 | ||
@@ -114,6 +117,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | @@ -114,6 +117,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | ||
114 | this.selectEntitySubtypeText = 'asset.select-asset-type'; | 117 | this.selectEntitySubtypeText = 'asset.select-asset-type'; |
115 | this.entitySubtypeText = 'asset.asset-type'; | 118 | this.entitySubtypeText = 'asset.asset-type'; |
116 | this.entitySubtypeRequiredText = 'asset.asset-type-required'; | 119 | this.entitySubtypeRequiredText = 'asset.asset-type-required'; |
120 | + this.entitySubtypeMaxLength = 'asset.asset-type-max-length'; | ||
117 | this.broadcastSubscription = this.broadcast.on('assetSaved', () => { | 121 | this.broadcastSubscription = this.broadcast.on('assetSaved', () => { |
118 | this.subTypes = null; | 122 | this.subTypes = null; |
119 | }); | 123 | }); |
@@ -122,6 +126,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | @@ -122,6 +126,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | ||
122 | this.selectEntitySubtypeText = 'device.select-device-type'; | 126 | this.selectEntitySubtypeText = 'device.select-device-type'; |
123 | this.entitySubtypeText = 'device.device-type'; | 127 | this.entitySubtypeText = 'device.device-type'; |
124 | this.entitySubtypeRequiredText = 'device.device-type-required'; | 128 | this.entitySubtypeRequiredText = 'device.device-type-required'; |
129 | + this.entitySubtypeMaxLength = 'device.device-type-max-length'; | ||
125 | this.broadcastSubscription = this.broadcast.on('deviceSaved', () => { | 130 | this.broadcastSubscription = this.broadcast.on('deviceSaved', () => { |
126 | this.subTypes = null; | 131 | this.subTypes = null; |
127 | }); | 132 | }); |
@@ -130,6 +135,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | @@ -130,6 +135,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | ||
130 | this.selectEntitySubtypeText = 'edge.select-edge-type'; | 135 | this.selectEntitySubtypeText = 'edge.select-edge-type'; |
131 | this.entitySubtypeText = 'edge.edge-type'; | 136 | this.entitySubtypeText = 'edge.edge-type'; |
132 | this.entitySubtypeRequiredText = 'edge.edge-type-required'; | 137 | this.entitySubtypeRequiredText = 'edge.edge-type-required'; |
138 | + this.entitySubtypeMaxLength = 'edge.type-max-length'; | ||
133 | this.broadcastSubscription = this.broadcast.on('edgeSaved', () => { | 139 | this.broadcastSubscription = this.broadcast.on('edgeSaved', () => { |
134 | this.subTypes = null; | 140 | this.subTypes = null; |
135 | }); | 141 | }); |
@@ -138,6 +144,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | @@ -138,6 +144,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | ||
138 | this.selectEntitySubtypeText = 'entity-view.select-entity-view-type'; | 144 | this.selectEntitySubtypeText = 'entity-view.select-entity-view-type'; |
139 | this.entitySubtypeText = 'entity-view.entity-view-type'; | 145 | this.entitySubtypeText = 'entity-view.entity-view-type'; |
140 | this.entitySubtypeRequiredText = 'entity-view.entity-view-type-required'; | 146 | this.entitySubtypeRequiredText = 'entity-view.entity-view-type-required'; |
147 | + this.entitySubtypeMaxLength = 'entity-view.type-max-length' | ||
141 | this.broadcastSubscription = this.broadcast.on('entityViewSaved', () => { | 148 | this.broadcastSubscription = this.broadcast.on('entityViewSaved', () => { |
142 | this.subTypes = null; | 149 | this.subTypes = null; |
143 | }); | 150 | }); |
@@ -149,7 +156,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | @@ -149,7 +156,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | ||
149 | debounceTime(150), | 156 | debounceTime(150), |
150 | distinctUntilChanged(), | 157 | distinctUntilChanged(), |
151 | tap(value => { | 158 | tap(value => { |
152 | - this.updateView(value); | 159 | + this.updateView(value); |
153 | }), | 160 | }), |
154 | // startWith<string | EntitySubtype>(''), | 161 | // startWith<string | EntitySubtype>(''), |
155 | map(value => value ? value : ''), | 162 | map(value => value ? value : ''), |
@@ -203,7 +210,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | @@ -203,7 +210,7 @@ export class EntitySubTypeAutocompleteComponent implements ControlValueAccessor, | ||
203 | fetchSubTypes(searchText?: string, strictMatch: boolean = false): Observable<Array<string>> { | 210 | fetchSubTypes(searchText?: string, strictMatch: boolean = false): Observable<Array<string>> { |
204 | this.searchText = searchText; | 211 | this.searchText = searchText; |
205 | return this.getSubTypes().pipe( | 212 | return this.getSubTypes().pipe( |
206 | - map(subTypes => subTypes.filter( subType => { | 213 | + map(subTypes => subTypes.filter(subType => { |
207 | if (strictMatch) { | 214 | if (strictMatch) { |
208 | return searchText ? subType === searchText : false; | 215 | return searchText ? subType === searchText : false; |
209 | } else { | 216 | } else { |
@@ -39,4 +39,7 @@ | @@ -39,4 +39,7 @@ | ||
39 | <mat-error *ngIf="relationTypeFormGroup.get('relationType').hasError('required')"> | 39 | <mat-error *ngIf="relationTypeFormGroup.get('relationType').hasError('required')"> |
40 | {{ 'relation.relation-type-required' | translate }} | 40 | {{ 'relation.relation-type-required' | translate }} |
41 | </mat-error> | 41 | </mat-error> |
42 | + <mat-error *ngIf="relationTypeFormGroup.get('relationType').hasError('maxlength')"> | ||
43 | + {{ 'relation.relation-type-max-length' | translate }} | ||
44 | + </mat-error> | ||
42 | </mat-form-field> | 45 | </mat-form-field> |
@@ -68,7 +68,7 @@ export class RelationTypeAutocompleteComponent implements ControlValueAccessor, | @@ -68,7 +68,7 @@ export class RelationTypeAutocompleteComponent implements ControlValueAccessor, | ||
68 | public translate: TranslateService, | 68 | public translate: TranslateService, |
69 | private fb: FormBuilder) { | 69 | private fb: FormBuilder) { |
70 | this.relationTypeFormGroup = this.fb.group({ | 70 | this.relationTypeFormGroup = this.fb.group({ |
71 | - relationType: [null, this.required ? [Validators.required] : []] | 71 | + relationType: [null, this.required ? [Validators.required, Validators.maxLength(255)] : [Validators.maxLength(255)]] |
72 | }); | 72 | }); |
73 | } | 73 | } |
74 | 74 |
@@ -369,6 +369,7 @@ | @@ -369,6 +369,7 @@ | ||
369 | "management": "Asset management", | 369 | "management": "Asset management", |
370 | "view-assets": "View Assets", | 370 | "view-assets": "View Assets", |
371 | "add": "Add Asset", | 371 | "add": "Add Asset", |
372 | + "asset-type-max-length": "Asset type should be less than 256", | ||
372 | "assign-to-customer": "Assign to customer", | 373 | "assign-to-customer": "Assign to customer", |
373 | "assign-asset-to-customer": "Assign Asset(s) To Customer", | 374 | "assign-asset-to-customer": "Assign Asset(s) To Customer", |
374 | "assign-asset-to-customer-text": "Please select the assets to assign to the customer", | 375 | "assign-asset-to-customer-text": "Please select the assets to assign to the customer", |
@@ -391,6 +392,8 @@ | @@ -391,6 +392,8 @@ | ||
391 | "asset-types": "Asset types", | 392 | "asset-types": "Asset types", |
392 | "name": "Name", | 393 | "name": "Name", |
393 | "name-required": "Name is required.", | 394 | "name-required": "Name is required.", |
395 | + "name-max-length": "Name should be less than 256", | ||
396 | + "label-max-length": "Label should be less than 256", | ||
394 | "description": "Description", | 397 | "description": "Description", |
395 | "type": "Type", | 398 | "type": "Type", |
396 | "type-required": "Type is required.", | 399 | "type-required": "Type is required.", |
@@ -449,6 +452,7 @@ | @@ -449,6 +452,7 @@ | ||
449 | "scope-shared": "Shared attributes", | 452 | "scope-shared": "Shared attributes", |
450 | "add": "Add attribute", | 453 | "add": "Add attribute", |
451 | "key": "Key", | 454 | "key": "Key", |
455 | + "key-max-length": "Key should be less than 256", | ||
452 | "last-update-time": "Last update time", | 456 | "last-update-time": "Last update time", |
453 | "key-required": "Attribute key is required.", | 457 | "key-required": "Attribute key is required.", |
454 | "value": "Value", | 458 | "value": "Value", |
@@ -590,7 +594,10 @@ | @@ -590,7 +594,10 @@ | ||
590 | "address2": "Address 2", | 594 | "address2": "Address 2", |
591 | "phone": "Phone", | 595 | "phone": "Phone", |
592 | "email": "Email", | 596 | "email": "Email", |
593 | - "no-address": "No address" | 597 | + "no-address": "No address", |
598 | + "state-max-length": "State length should be less than 256", | ||
599 | + "phone-max-length": "Phone number should be less than 256", | ||
600 | + "city-max-length": "Specified city should be less than 256" | ||
594 | }, | 601 | }, |
595 | "common": { | 602 | "common": { |
596 | "username": "Username", | 603 | "username": "Username", |
@@ -646,6 +653,7 @@ | @@ -646,6 +653,7 @@ | ||
646 | "manage-dashboards": "Manage dashboards", | 653 | "manage-dashboards": "Manage dashboards", |
647 | "title": "Title", | 654 | "title": "Title", |
648 | "title-required": "Title is required.", | 655 | "title-required": "Title is required.", |
656 | + "title-max-length": "Title should be less than 256", | ||
649 | "description": "Description", | 657 | "description": "Description", |
650 | "details": "Details", | 658 | "details": "Details", |
651 | "events": "Events", | 659 | "events": "Events", |
@@ -700,6 +708,7 @@ | @@ -700,6 +708,7 @@ | ||
700 | "select-widget-subtitle": "List of available widget types", | 708 | "select-widget-subtitle": "List of available widget types", |
701 | "delete": "Delete dashboard", | 709 | "delete": "Delete dashboard", |
702 | "title-required": "Title is required.", | 710 | "title-required": "Title is required.", |
711 | + "title-max-length": "Title should be less than 256", | ||
703 | "description": "Description", | 712 | "description": "Description", |
704 | "details": "Details", | 713 | "details": "Details", |
705 | "dashboard-details": "Dashboard details", | 714 | "dashboard-details": "Dashboard details", |
@@ -886,6 +895,7 @@ | @@ -886,6 +895,7 @@ | ||
886 | "management": "Device management", | 895 | "management": "Device management", |
887 | "view-devices": "View Devices", | 896 | "view-devices": "View Devices", |
888 | "device-alias": "Device alias", | 897 | "device-alias": "Device alias", |
898 | + "device-type-max-length": "Device type should be less than 256", | ||
889 | "aliases": "Device aliases", | 899 | "aliases": "Device aliases", |
890 | "no-alias-matching": "'{{alias}}' not found.", | 900 | "no-alias-matching": "'{{alias}}' not found.", |
891 | "no-aliases-found": "No aliases found.", | 901 | "no-aliases-found": "No aliases found.", |
@@ -998,6 +1008,8 @@ | @@ -998,6 +1008,8 @@ | ||
998 | "device-types": "Device types", | 1008 | "device-types": "Device types", |
999 | "name": "Name", | 1009 | "name": "Name", |
1000 | "name-required": "Name is required.", | 1010 | "name-required": "Name is required.", |
1011 | + "name-max-length": "Name should be less than 256", | ||
1012 | + "label-max-length": "Label should be less than 256", | ||
1001 | "description": "Description", | 1013 | "description": "Description", |
1002 | "label": "Label", | 1014 | "label": "Label", |
1003 | "events": "Events", | 1015 | "events": "Events", |
@@ -1050,6 +1062,7 @@ | @@ -1050,6 +1062,7 @@ | ||
1050 | "set-default": "Make device profile default", | 1062 | "set-default": "Make device profile default", |
1051 | "delete": "Delete device profile", | 1063 | "delete": "Delete device profile", |
1052 | "copyId": "Copy device profile Id", | 1064 | "copyId": "Copy device profile Id", |
1065 | + "name-max-length": "Name should be less than 256", | ||
1053 | "new-device-profile-name": "Device profile name", | 1066 | "new-device-profile-name": "Device profile name", |
1054 | "new-device-profile-name-required": "Device profile name is required.", | 1067 | "new-device-profile-name-required": "Device profile name is required.", |
1055 | "name": "Name", | 1068 | "name": "Name", |
@@ -1401,6 +1414,9 @@ | @@ -1401,6 +1414,9 @@ | ||
1401 | "edge": "Edge", | 1414 | "edge": "Edge", |
1402 | "edge-instances": "Edge instances", | 1415 | "edge-instances": "Edge instances", |
1403 | "edge-file": "Edge file", | 1416 | "edge-file": "Edge file", |
1417 | + "name-max-length": "Name should be less than 256", | ||
1418 | + "label-max-length": "Label should be less than 256", | ||
1419 | + "type-max-length": "Type should be less than 256", | ||
1404 | "management": "Edge management", | 1420 | "management": "Edge management", |
1405 | "no-edges-matching": "No edges matching '{{entity}}' were found.", | 1421 | "no-edges-matching": "No edges matching '{{entity}}' were found.", |
1406 | "rulechain-templates": "Rule chain templates", | 1422 | "rulechain-templates": "Rule chain templates", |
@@ -1741,6 +1757,8 @@ | @@ -1741,6 +1757,8 @@ | ||
1741 | "created-time": "Created time", | 1757 | "created-time": "Created time", |
1742 | "name": "Name", | 1758 | "name": "Name", |
1743 | "name-required": "Name is required.", | 1759 | "name-required": "Name is required.", |
1760 | + "name-max-length": "Name should be less than 256", | ||
1761 | + "type-max-length": "Entity view type should be less than 256", | ||
1744 | "description": "Description", | 1762 | "description": "Description", |
1745 | "events": "Events", | 1763 | "events": "Events", |
1746 | "details": "Details", | 1764 | "details": "Details", |
@@ -2335,12 +2353,14 @@ | @@ -2335,12 +2353,14 @@ | ||
2335 | "selected-package": "{ count, plural, 1 {1 package} other {# packages} } selected", | 2353 | "selected-package": "{ count, plural, 1 {1 package} other {# packages} } selected", |
2336 | "title": "Title", | 2354 | "title": "Title", |
2337 | "title-required": "Title is required.", | 2355 | "title-required": "Title is required.", |
2356 | + "title-max-length": "Title should be less than 256", | ||
2338 | "types": { | 2357 | "types": { |
2339 | "firmware": "Firmware", | 2358 | "firmware": "Firmware", |
2340 | "software": "Software" | 2359 | "software": "Software" |
2341 | }, | 2360 | }, |
2342 | "version": "Version", | 2361 | "version": "Version", |
2343 | "version-required": "Version is required.", | 2362 | "version-required": "Version is required.", |
2363 | + "version-max-length": "Version should be less than 256", | ||
2344 | "warning-after-save-no-edit": "Once the package is uploaded, you will not be able to modify title, version, device profile and package type." | 2364 | "warning-after-save-no-edit": "Once the package is uploaded, you will not be able to modify title, version, device profile and package type." |
2345 | }, | 2365 | }, |
2346 | "position": { | 2366 | "position": { |
@@ -2379,6 +2399,7 @@ | @@ -2379,6 +2399,7 @@ | ||
2379 | "delete": "Delete relation", | 2399 | "delete": "Delete relation", |
2380 | "relation-type": "Relation type", | 2400 | "relation-type": "Relation type", |
2381 | "relation-type-required": "Relation type is required.", | 2401 | "relation-type-required": "Relation type is required.", |
2402 | + "relation-type-max-length": "Relation type should be less than 256", | ||
2382 | "any-relation-type": "Any type", | 2403 | "any-relation-type": "Any type", |
2383 | "add": "Add relation", | 2404 | "add": "Add relation", |
2384 | "edit": "Edit relation", | 2405 | "edit": "Edit relation", |
@@ -2423,7 +2444,8 @@ | @@ -2423,7 +2444,8 @@ | ||
2423 | "selected-resources": "{ count, plural, 1 {1 resource} other {# resources} } selected", | 2444 | "selected-resources": "{ count, plural, 1 {1 resource} other {# resources} } selected", |
2424 | "system": "System", | 2445 | "system": "System", |
2425 | "title": "Title", | 2446 | "title": "Title", |
2426 | - "title-required": "Title is required." | 2447 | + "title-required": "Title is required.", |
2448 | + "title-max-length": "Title should be less than 256" | ||
2427 | }, | 2449 | }, |
2428 | "rulechain": { | 2450 | "rulechain": { |
2429 | "rulechain": "Rule chain", | 2451 | "rulechain": "Rule chain", |
@@ -2432,6 +2454,7 @@ | @@ -2432,6 +2454,7 @@ | ||
2432 | "delete": "Delete rule chain", | 2454 | "delete": "Delete rule chain", |
2433 | "name": "Name", | 2455 | "name": "Name", |
2434 | "name-required": "Name is required.", | 2456 | "name-required": "Name is required.", |
2457 | + "name-max-length": "Name should be less than 256", | ||
2435 | "description": "Description", | 2458 | "description": "Description", |
2436 | "add": "Add Rule Chain", | 2459 | "add": "Add Rule Chain", |
2437 | "set-root": "Make rule chain root", | 2460 | "set-root": "Make rule chain root", |
@@ -2573,6 +2596,7 @@ | @@ -2573,6 +2596,7 @@ | ||
2573 | "add-tenant-text": "Add new tenant", | 2596 | "add-tenant-text": "Add new tenant", |
2574 | "no-tenants-text": "No tenants found", | 2597 | "no-tenants-text": "No tenants found", |
2575 | "tenant-details": "Tenant details", | 2598 | "tenant-details": "Tenant details", |
2599 | + "title-max-length": "Title should be less than 256", | ||
2576 | "delete-tenant-title": "Are you sure you want to delete the tenant '{{tenantTitle}}'?", | 2600 | "delete-tenant-title": "Are you sure you want to delete the tenant '{{tenantTitle}}'?", |
2577 | "delete-tenant-text": "Be careful, after the confirmation the tenant and all related data will become unrecoverable.", | 2601 | "delete-tenant-text": "Be careful, after the confirmation the tenant and all related data will become unrecoverable.", |
2578 | "delete-tenants-title": "Are you sure you want to delete { count, plural, 1 {1 tenant} other {# tenants} }?", | 2602 | "delete-tenants-title": "Are you sure you want to delete { count, plural, 1 {1 tenant} other {# tenants} }?", |
@@ -2602,6 +2626,7 @@ | @@ -2602,6 +2626,7 @@ | ||
2602 | "edit": "Edit tenant profile", | 2626 | "edit": "Edit tenant profile", |
2603 | "tenant-profile-details": "Tenant profile details", | 2627 | "tenant-profile-details": "Tenant profile details", |
2604 | "no-tenant-profiles-text": "No tenant profiles found", | 2628 | "no-tenant-profiles-text": "No tenant profiles found", |
2629 | + "name-max-length": "Name should be less than 256", | ||
2605 | "search": "Search tenant profiles", | 2630 | "search": "Search tenant profiles", |
2606 | "selected-tenant-profiles": "{ count, plural, 1 {1 tenant profile} other {# tenant profiles} } selected", | 2631 | "selected-tenant-profiles": "{ count, plural, 1 {1 tenant profile} other {# tenant profiles} } selected", |
2607 | "no-tenant-profiles-matching": "No tenant profile matching '{{entity}}' were found.", | 2632 | "no-tenant-profiles-matching": "No tenant profile matching '{{entity}}' were found.", |
@@ -2925,6 +2950,7 @@ | @@ -2925,6 +2950,7 @@ | ||
2925 | "delete": "Delete widgets bundle", | 2950 | "delete": "Delete widgets bundle", |
2926 | "title": "Title", | 2951 | "title": "Title", |
2927 | "title-required": "Title is required.", | 2952 | "title-required": "Title is required.", |
2953 | + "title-max-length": "Title should be less than 256", | ||
2928 | "description": "Description", | 2954 | "description": "Description", |
2929 | "image-preview": "Image preview", | 2955 | "image-preview": "Image preview", |
2930 | "add-widgets-bundle-text": "Add new widgets bundle", | 2956 | "add-widgets-bundle-text": "Add new widgets bundle", |