Commit 3d3dd8871044a0733a7016eafc4a2e09f28a26c1
Merge remote-tracking branch 'origin/develop/2.5.1' into feature/edge
Showing
99 changed files
with
1691 additions
and
1091 deletions
Too many changes to show.
To preserve performance only 99 of 283 files are displayed.
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>thingsboard</artifactId> | 24 | <artifactId>thingsboard</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <artifactId>application</artifactId> | 26 | <artifactId>application</artifactId> |
@@ -34,10 +34,15 @@ | @@ -34,10 +34,15 @@ | ||
34 | <properties> | 34 | <properties> |
35 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | 35 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
36 | <main.dir>${basedir}/..</main.dir> | 36 | <main.dir>${basedir}/..</main.dir> |
37 | + <pkg.type>java</pkg.type> | ||
38 | + <pkg.disabled>false</pkg.disabled> | ||
39 | + <pkg.process-resources.phase>process-resources</pkg.process-resources.phase> | ||
40 | + <pkg.package.phase>package</pkg.package.phase> | ||
37 | <pkg.name>thingsboard</pkg.name> | 41 | <pkg.name>thingsboard</pkg.name> |
38 | - <pkg.unixLogFolder>/var/log/${pkg.name}</pkg.unixLogFolder> | ||
39 | - <pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder> | ||
40 | <pkg.win.dist>${project.build.directory}/windows</pkg.win.dist> | 42 | <pkg.win.dist>${project.build.directory}/windows</pkg.win.dist> |
43 | + <pkg.copyInstallScripts>true</pkg.copyInstallScripts> | ||
44 | + <pkg.implementationTitle>ThingsBoard</pkg.implementationTitle> | ||
45 | + <pkg.mainClass>org.thingsboard.server.ThingsboardServerApplication</pkg.mainClass> | ||
41 | </properties> | 46 | </properties> |
42 | 47 | ||
43 | <dependencies> | 48 | <dependencies> |
@@ -313,6 +318,10 @@ | @@ -313,6 +318,10 @@ | ||
313 | <plugins> | 318 | <plugins> |
314 | <plugin> | 319 | <plugin> |
315 | <groupId>org.apache.maven.plugins</groupId> | 320 | <groupId>org.apache.maven.plugins</groupId> |
321 | + <artifactId>maven-compiler-plugin</artifactId> | ||
322 | + </plugin> | ||
323 | + <plugin> | ||
324 | + <groupId>org.apache.maven.plugins</groupId> | ||
316 | <artifactId>maven-surefire-plugin</artifactId> | 325 | <artifactId>maven-surefire-plugin</artifactId> |
317 | <version>${surfire.version}</version> | 326 | <version>${surfire.version}</version> |
318 | <configuration> | 327 | <configuration> |
@@ -327,313 +336,30 @@ | @@ -327,313 +336,30 @@ | ||
327 | <plugin> | 336 | <plugin> |
328 | <groupId>org.apache.maven.plugins</groupId> | 337 | <groupId>org.apache.maven.plugins</groupId> |
329 | <artifactId>maven-resources-plugin</artifactId> | 338 | <artifactId>maven-resources-plugin</artifactId> |
330 | - <executions> | ||
331 | - <execution> | ||
332 | - <id>copy-conf</id> | ||
333 | - <phase>process-resources</phase> | ||
334 | - <goals> | ||
335 | - <goal>copy-resources</goal> | ||
336 | - </goals> | ||
337 | - <configuration> | ||
338 | - <outputDirectory>${project.build.directory}/conf</outputDirectory> | ||
339 | - <resources> | ||
340 | - <resource> | ||
341 | - <directory>src/main/resources</directory> | ||
342 | - <excludes> | ||
343 | - <exclude>logback.xml</exclude> | ||
344 | - </excludes> | ||
345 | - <filtering>false</filtering> | ||
346 | - </resource> | ||
347 | - </resources> | ||
348 | - </configuration> | ||
349 | - </execution> | ||
350 | - <execution> | ||
351 | - <id>copy-service-conf</id> | ||
352 | - <phase>process-resources</phase> | ||
353 | - <goals> | ||
354 | - <goal>copy-resources</goal> | ||
355 | - </goals> | ||
356 | - <configuration> | ||
357 | - <outputDirectory>${project.build.directory}/conf</outputDirectory> | ||
358 | - <resources> | ||
359 | - <resource> | ||
360 | - <directory>src/main/conf</directory> | ||
361 | - <filtering>true</filtering> | ||
362 | - </resource> | ||
363 | - </resources> | ||
364 | - <filters> | ||
365 | - <filter>src/main/filters/unix.properties</filter> | ||
366 | - </filters> | ||
367 | - </configuration> | ||
368 | - </execution> | ||
369 | - <execution> | ||
370 | - <id>copy-win-conf</id> | ||
371 | - <phase>process-resources</phase> | ||
372 | - <goals> | ||
373 | - <goal>copy-resources</goal> | ||
374 | - </goals> | ||
375 | - <configuration> | ||
376 | - <outputDirectory>${pkg.win.dist}/conf</outputDirectory> | ||
377 | - <resources> | ||
378 | - <resource> | ||
379 | - <directory>src/main/resources</directory> | ||
380 | - <excludes> | ||
381 | - <exclude>logback.xml</exclude> | ||
382 | - </excludes> | ||
383 | - <filtering>false</filtering> | ||
384 | - </resource> | ||
385 | - <resource> | ||
386 | - <directory>src/main/conf</directory> | ||
387 | - <excludes> | ||
388 | - <exclude>thingsboard.conf</exclude> | ||
389 | - </excludes> | ||
390 | - <filtering>true</filtering> | ||
391 | - </resource> | ||
392 | - </resources> | ||
393 | - <filters> | ||
394 | - <filter>src/main/filters/windows.properties</filter> | ||
395 | - </filters> | ||
396 | - </configuration> | ||
397 | - </execution> | ||
398 | - <execution> | ||
399 | - <id>copy-control</id> | ||
400 | - <phase>process-resources</phase> | ||
401 | - <goals> | ||
402 | - <goal>copy-resources</goal> | ||
403 | - </goals> | ||
404 | - <configuration> | ||
405 | - <outputDirectory>${project.build.directory}/control</outputDirectory> | ||
406 | - <resources> | ||
407 | - <resource> | ||
408 | - <directory>src/main/scripts/control</directory> | ||
409 | - <filtering>true</filtering> | ||
410 | - </resource> | ||
411 | - </resources> | ||
412 | - <filters> | ||
413 | - <filter>src/main/filters/unix.properties</filter> | ||
414 | - </filters> | ||
415 | - </configuration> | ||
416 | - </execution> | ||
417 | - <execution> | ||
418 | - <id>copy-install</id> | ||
419 | - <phase>process-resources</phase> | ||
420 | - <goals> | ||
421 | - <goal>copy-resources</goal> | ||
422 | - </goals> | ||
423 | - <configuration> | ||
424 | - <outputDirectory>${project.build.directory}/bin/install</outputDirectory> | ||
425 | - <resources> | ||
426 | - <resource> | ||
427 | - <directory>src/main/scripts/install</directory> | ||
428 | - <includes> | ||
429 | - <include>**/*.sh</include> | ||
430 | - <include>**/*.xml</include> | ||
431 | - </includes> | ||
432 | - <filtering>true</filtering> | ||
433 | - </resource> | ||
434 | - </resources> | ||
435 | - <filters> | ||
436 | - <filter>src/main/filters/unix.properties</filter> | ||
437 | - </filters> | ||
438 | - </configuration> | ||
439 | - </execution> | ||
440 | - <execution> | ||
441 | - <id>copy-windows-control</id> | ||
442 | - <phase>process-resources</phase> | ||
443 | - <goals> | ||
444 | - <goal>copy-resources</goal> | ||
445 | - </goals> | ||
446 | - <configuration> | ||
447 | - <outputDirectory>${pkg.win.dist}</outputDirectory> | ||
448 | - <resources> | ||
449 | - <resource> | ||
450 | - <directory>src/main/scripts/windows</directory> | ||
451 | - <filtering>true</filtering> | ||
452 | - </resource> | ||
453 | - </resources> | ||
454 | - <filters> | ||
455 | - <filter>src/main/filters/windows.properties</filter> | ||
456 | - </filters> | ||
457 | - </configuration> | ||
458 | - </execution> | ||
459 | - <execution> | ||
460 | - <id>copy-windows-install</id> | ||
461 | - <phase>process-resources</phase> | ||
462 | - <goals> | ||
463 | - <goal>copy-resources</goal> | ||
464 | - </goals> | ||
465 | - <configuration> | ||
466 | - <outputDirectory>${pkg.win.dist}/install</outputDirectory> | ||
467 | - <resources> | ||
468 | - <resource> | ||
469 | - <directory>src/main/scripts/install</directory> | ||
470 | - <includes> | ||
471 | - <include>logback.xml</include> | ||
472 | - </includes> | ||
473 | - <filtering>true</filtering> | ||
474 | - </resource> | ||
475 | - </resources> | ||
476 | - <filters> | ||
477 | - <filter>src/main/filters/windows.properties</filter> | ||
478 | - </filters> | ||
479 | - </configuration> | ||
480 | - </execution> | ||
481 | - <execution> | ||
482 | - <id>copy-data</id> | ||
483 | - <phase>process-resources</phase> | ||
484 | - <goals> | ||
485 | - <goal>copy-resources</goal> | ||
486 | - </goals> | ||
487 | - <configuration> | ||
488 | - <outputDirectory>${project.build.directory}/data</outputDirectory> | ||
489 | - <resources> | ||
490 | - <resource> | ||
491 | - <directory>src/main/data</directory> | ||
492 | - </resource> | ||
493 | - <resource> | ||
494 | - <directory>../dao/src/main/resources</directory> | ||
495 | - <includes> | ||
496 | - <include>**/*.cql</include> | ||
497 | - <include>**/*.sql</include> | ||
498 | - </includes> | ||
499 | - <filtering>false</filtering> | ||
500 | - </resource> | ||
501 | - </resources> | ||
502 | - </configuration> | ||
503 | - </execution> | ||
504 | - </executions> | ||
505 | </plugin> | 339 | </plugin> |
506 | <plugin> | 340 | <plugin> |
507 | <groupId>org.apache.maven.plugins</groupId> | 341 | <groupId>org.apache.maven.plugins</groupId> |
508 | <artifactId>maven-dependency-plugin</artifactId> | 342 | <artifactId>maven-dependency-plugin</artifactId> |
509 | - <executions> | ||
510 | - <execution> | ||
511 | - <id>copy-winsw-service</id> | ||
512 | - <phase>package</phase> | ||
513 | - <goals> | ||
514 | - <goal>copy</goal> | ||
515 | - </goals> | ||
516 | - <configuration> | ||
517 | - <artifactItems> | ||
518 | - <artifactItem> | ||
519 | - <groupId>com.sun.winsw</groupId> | ||
520 | - <artifactId>winsw</artifactId> | ||
521 | - <classifier>bin</classifier> | ||
522 | - <type>exe</type> | ||
523 | - <destFileName>service.exe</destFileName> | ||
524 | - </artifactItem> | ||
525 | - </artifactItems> | ||
526 | - <outputDirectory>${pkg.win.dist}</outputDirectory> | ||
527 | - </configuration> | ||
528 | - </execution> | ||
529 | - </executions> | ||
530 | </plugin> | 343 | </plugin> |
531 | <plugin> | 344 | <plugin> |
532 | <groupId>org.apache.maven.plugins</groupId> | 345 | <groupId>org.apache.maven.plugins</groupId> |
533 | <artifactId>maven-jar-plugin</artifactId> | 346 | <artifactId>maven-jar-plugin</artifactId> |
534 | - <configuration> | ||
535 | - <excludes> | ||
536 | - <exclude>**/logback.xml</exclude> | ||
537 | - </excludes> | ||
538 | - <archive> | ||
539 | - <manifestEntries> | ||
540 | - <Implementation-Title>ThingsBoard</Implementation-Title> | ||
541 | - <Implementation-Version>${project.version}</Implementation-Version> | ||
542 | - </manifestEntries> | ||
543 | - </archive> | ||
544 | - </configuration> | ||
545 | </plugin> | 347 | </plugin> |
546 | <plugin> | 348 | <plugin> |
547 | <groupId>org.springframework.boot</groupId> | 349 | <groupId>org.springframework.boot</groupId> |
548 | <artifactId>spring-boot-maven-plugin</artifactId> | 350 | <artifactId>spring-boot-maven-plugin</artifactId> |
549 | - <configuration> | ||
550 | - <mainClass>org.thingsboard.server.ThingsboardServerApplication</mainClass> | ||
551 | - <classifier>boot</classifier> | ||
552 | - <layout>ZIP</layout> | ||
553 | - <executable>true</executable> | ||
554 | - <excludeDevtools>true</excludeDevtools> | ||
555 | - <embeddedLaunchScriptProperties> | ||
556 | - <confFolder>${pkg.installFolder}/conf</confFolder> | ||
557 | - <logFolder>${pkg.unixLogFolder}</logFolder> | ||
558 | - <logFilename>${pkg.name}.out</logFilename> | ||
559 | - <initInfoProvides>${pkg.name}</initInfoProvides> | ||
560 | - </embeddedLaunchScriptProperties> | ||
561 | - </configuration> | ||
562 | - <executions> | ||
563 | - <execution> | ||
564 | - <goals> | ||
565 | - <goal>repackage</goal> | ||
566 | - </goals> | ||
567 | - </execution> | ||
568 | - </executions> | ||
569 | </plugin> | 351 | </plugin> |
570 | <plugin> | 352 | <plugin> |
571 | <groupId>org.thingsboard</groupId> | 353 | <groupId>org.thingsboard</groupId> |
572 | <artifactId>gradle-maven-plugin</artifactId> | 354 | <artifactId>gradle-maven-plugin</artifactId> |
573 | - <configuration> | ||
574 | - <tasks> | ||
575 | - <task>build</task> | ||
576 | - <task>buildDeb</task> | ||
577 | - <task>buildRpm</task> | ||
578 | - </tasks> | ||
579 | - <args> | ||
580 | - <arg>-PprojectBuildDir=${project.build.directory}</arg> | ||
581 | - <arg>-PprojectVersion=${project.version}</arg> | ||
582 | - <arg>-PmainJar=${project.build.directory}/${project.build.finalName}-boot.${project.packaging} | ||
583 | - </arg> | ||
584 | - <arg>-PpkgName=${pkg.name}</arg> | ||
585 | - <arg>-PpkgInstallFolder=${pkg.installFolder}</arg> | ||
586 | - <arg>-PpkgLogFolder=${pkg.unixLogFolder}</arg> | ||
587 | - </args> | ||
588 | - </configuration> | ||
589 | - <executions> | ||
590 | - <execution> | ||
591 | - <phase>package</phase> | ||
592 | - <goals> | ||
593 | - <goal>invoke</goal> | ||
594 | - </goals> | ||
595 | - </execution> | ||
596 | - </executions> | ||
597 | </plugin> | 355 | </plugin> |
598 | <plugin> | 356 | <plugin> |
599 | <groupId>org.apache.maven.plugins</groupId> | 357 | <groupId>org.apache.maven.plugins</groupId> |
600 | <artifactId>maven-assembly-plugin</artifactId> | 358 | <artifactId>maven-assembly-plugin</artifactId> |
601 | - <configuration> | ||
602 | - <finalName>${pkg.name}</finalName> | ||
603 | - <descriptors> | ||
604 | - <descriptor>src/main/assembly/windows.xml</descriptor> | ||
605 | - </descriptors> | ||
606 | - </configuration> | ||
607 | - <executions> | ||
608 | - <execution> | ||
609 | - <id>assembly</id> | ||
610 | - <phase>package</phase> | ||
611 | - <goals> | ||
612 | - <goal>single</goal> | ||
613 | - </goals> | ||
614 | - </execution> | ||
615 | - </executions> | ||
616 | </plugin> | 359 | </plugin> |
617 | <plugin> | 360 | <plugin> |
618 | <groupId>org.apache.maven.plugins</groupId> | 361 | <groupId>org.apache.maven.plugins</groupId> |
619 | <artifactId>maven-install-plugin</artifactId> | 362 | <artifactId>maven-install-plugin</artifactId> |
620 | - <configuration> | ||
621 | - <file>${project.build.directory}/${pkg.name}.deb</file> | ||
622 | - <artifactId>${project.artifactId}</artifactId> | ||
623 | - <groupId>${project.groupId}</groupId> | ||
624 | - <version>${project.version}</version> | ||
625 | - <classifier>deb</classifier> | ||
626 | - <packaging>deb</packaging> | ||
627 | - </configuration> | ||
628 | - <executions> | ||
629 | - <execution> | ||
630 | - <id>install-deb</id> | ||
631 | - <phase>package</phase> | ||
632 | - <goals> | ||
633 | - <goal>install-file</goal> | ||
634 | - </goals> | ||
635 | - </execution> | ||
636 | - </executions> | ||
637 | </plugin> | 363 | </plugin> |
638 | <plugin> | 364 | <plugin> |
639 | <groupId>org.xolstice.maven.plugins</groupId> | 365 | <groupId>org.xolstice.maven.plugins</groupId> |
@@ -16,50 +16,85 @@ | @@ -16,50 +16,85 @@ | ||
16 | 16 | ||
17 | -- call create_partition_ts_kv_table(); | 17 | -- call create_partition_ts_kv_table(); |
18 | 18 | ||
19 | -CREATE OR REPLACE PROCEDURE create_partition_ts_kv_table() LANGUAGE plpgsql AS $$ | 19 | +CREATE OR REPLACE PROCEDURE create_partition_ts_kv_table() |
20 | + LANGUAGE plpgsql AS | ||
21 | +$$ | ||
20 | 22 | ||
21 | BEGIN | 23 | BEGIN |
22 | - ALTER TABLE ts_kv | ||
23 | - RENAME TO ts_kv_old; | ||
24 | - ALTER TABLE ts_kv_old | ||
25 | - RENAME CONSTRAINT ts_kv_pkey TO ts_kv_pkey_old; | ||
26 | - CREATE TABLE IF NOT EXISTS ts_kv | ||
27 | - ( | ||
28 | - LIKE ts_kv_old | ||
29 | - ) | ||
30 | - PARTITION BY RANGE (ts); | ||
31 | - ALTER TABLE ts_kv | ||
32 | - DROP COLUMN entity_type; | ||
33 | - ALTER TABLE ts_kv | ||
34 | - ALTER COLUMN entity_id TYPE uuid USING entity_id::uuid; | ||
35 | - ALTER TABLE ts_kv | ||
36 | - ALTER COLUMN key TYPE integer USING key::integer; | ||
37 | - ALTER TABLE ts_kv | ||
38 | - ADD CONSTRAINT ts_kv_pkey PRIMARY KEY (entity_id, key, ts); | 24 | + ALTER TABLE ts_kv |
25 | + DROP CONSTRAINT IF EXISTS ts_kv_unq_key; | ||
26 | + ALTER TABLE ts_kv | ||
27 | + DROP CONSTRAINT IF EXISTS ts_kv_pkey; | ||
28 | + ALTER TABLE ts_kv | ||
29 | + ADD CONSTRAINT ts_kv_pkey PRIMARY KEY (entity_type, entity_id, key, ts); | ||
30 | + ALTER TABLE ts_kv | ||
31 | + RENAME TO ts_kv_old; | ||
32 | + ALTER TABLE ts_kv_old | ||
33 | + RENAME CONSTRAINT ts_kv_pkey TO ts_kv_pkey_old; | ||
34 | + CREATE TABLE IF NOT EXISTS ts_kv | ||
35 | + ( | ||
36 | + LIKE ts_kv_old | ||
37 | + ) | ||
38 | + PARTITION BY RANGE (ts); | ||
39 | + ALTER TABLE ts_kv | ||
40 | + DROP COLUMN entity_type; | ||
41 | + ALTER TABLE ts_kv | ||
42 | + ALTER COLUMN entity_id TYPE uuid USING entity_id::uuid; | ||
43 | + ALTER TABLE ts_kv | ||
44 | + ALTER COLUMN key TYPE integer USING key::integer; | ||
45 | + ALTER TABLE ts_kv | ||
46 | + ADD CONSTRAINT ts_kv_pkey PRIMARY KEY (entity_id, key, ts); | ||
47 | + CREATE TABLE IF NOT EXISTS ts_kv_indefinite PARTITION OF ts_kv DEFAULT; | ||
39 | END; | 48 | END; |
40 | $$; | 49 | $$; |
41 | 50 | ||
42 | -- call create_new_ts_kv_latest_table(); | 51 | -- call create_new_ts_kv_latest_table(); |
43 | 52 | ||
44 | -CREATE OR REPLACE PROCEDURE create_new_ts_kv_latest_table() LANGUAGE plpgsql AS $$ | 53 | +CREATE OR REPLACE PROCEDURE create_new_ts_kv_latest_table() |
54 | + LANGUAGE plpgsql AS | ||
55 | +$$ | ||
45 | 56 | ||
46 | BEGIN | 57 | BEGIN |
47 | - ALTER TABLE ts_kv_latest | ||
48 | - RENAME TO ts_kv_latest_old; | ||
49 | - ALTER TABLE ts_kv_latest_old | ||
50 | - RENAME CONSTRAINT ts_kv_latest_pkey TO ts_kv_latest_pkey_old; | ||
51 | - CREATE TABLE IF NOT EXISTS ts_kv_latest | ||
52 | - ( | ||
53 | - LIKE ts_kv_latest_old | ||
54 | - ); | ||
55 | - ALTER TABLE ts_kv_latest | ||
56 | - DROP COLUMN entity_type; | ||
57 | - ALTER TABLE ts_kv_latest | ||
58 | - ALTER COLUMN entity_id TYPE uuid USING entity_id::uuid; | ||
59 | - ALTER TABLE ts_kv_latest | ||
60 | - ALTER COLUMN key TYPE integer USING key::integer; | ||
61 | - ALTER TABLE ts_kv_latest | ||
62 | - ADD CONSTRAINT ts_kv_latest_pkey PRIMARY KEY (entity_id, key); | 58 | + IF NOT EXISTS(SELECT FROM pg_tables WHERE schemaname = 'public' AND tablename = 'ts_kv_latest_old') THEN |
59 | + ALTER TABLE ts_kv_latest | ||
60 | + DROP CONSTRAINT IF EXISTS ts_kv_latest_unq_key; | ||
61 | + ALTER TABLE ts_kv_latest | ||
62 | + DROP CONSTRAINT IF EXISTS ts_kv_latest_pkey; | ||
63 | + ALTER TABLE ts_kv_latest | ||
64 | + ADD CONSTRAINT ts_kv_latest_pkey PRIMARY KEY (entity_type, entity_id, key); | ||
65 | + ALTER TABLE ts_kv_latest | ||
66 | + RENAME TO ts_kv_latest_old; | ||
67 | + ALTER TABLE ts_kv_latest_old | ||
68 | + RENAME CONSTRAINT ts_kv_latest_pkey TO ts_kv_latest_pkey_old; | ||
69 | + CREATE TABLE IF NOT EXISTS ts_kv_latest | ||
70 | + ( | ||
71 | + LIKE ts_kv_latest_old | ||
72 | + ); | ||
73 | + ALTER TABLE ts_kv_latest | ||
74 | + DROP COLUMN entity_type; | ||
75 | + ALTER TABLE ts_kv_latest | ||
76 | + ALTER COLUMN entity_id TYPE uuid USING entity_id::uuid; | ||
77 | + ALTER TABLE ts_kv_latest | ||
78 | + ALTER COLUMN key TYPE integer USING key::integer; | ||
79 | + ALTER TABLE ts_kv_latest | ||
80 | + ADD CONSTRAINT ts_kv_latest_pkey PRIMARY KEY (entity_id, key); | ||
81 | + ELSE | ||
82 | + RAISE NOTICE 'ts_kv_latest_old table already exists!'; | ||
83 | + IF NOT EXISTS(SELECT FROM pg_tables WHERE schemaname = 'public' AND tablename = 'ts_kv_latest') THEN | ||
84 | + CREATE TABLE IF NOT EXISTS ts_kv_latest | ||
85 | + ( | ||
86 | + entity_id uuid NOT NULL, | ||
87 | + key int NOT NULL, | ||
88 | + ts bigint NOT NULL, | ||
89 | + bool_v boolean, | ||
90 | + str_v varchar(10000000), | ||
91 | + long_v bigint, | ||
92 | + dbl_v double precision, | ||
93 | + json_v json, | ||
94 | + CONSTRAINT ts_kv_latest_pkey PRIMARY KEY (entity_id, key) | ||
95 | + ); | ||
96 | + END IF; | ||
97 | + END IF; | ||
63 | END; | 98 | END; |
64 | $$; | 99 | $$; |
65 | 100 | ||
@@ -93,8 +128,9 @@ BEGIN | @@ -93,8 +128,9 @@ BEGIN | ||
93 | RETURN QUERY SELECT SUBSTRING(year_date.year, 1, 4) AS partition_date, | 128 | RETURN QUERY SELECT SUBSTRING(year_date.year, 1, 4) AS partition_date, |
94 | (extract(epoch from (year_date.year)::timestamp) * 1000)::bigint AS from_ts, | 129 | (extract(epoch from (year_date.year)::timestamp) * 1000)::bigint AS from_ts, |
95 | (extract(epoch from (year_date.year::date + INTERVAL '1 YEAR')::timestamp) * | 130 | (extract(epoch from (year_date.year::date + INTERVAL '1 YEAR')::timestamp) * |
96 | - 1000)::bigint AS to_ts | ||
97 | - FROM (SELECT DISTINCT TO_CHAR(TO_TIMESTAMP(ts / 1000), 'YYYY_01_01') AS year FROM ts_kv_old) AS year_date; | 131 | + 1000)::bigint AS to_ts |
132 | + FROM (SELECT DISTINCT TO_CHAR(TO_TIMESTAMP(ts / 1000), 'YYYY_01_01') AS year | ||
133 | + FROM ts_kv_old) AS year_date; | ||
98 | ELSE | 134 | ELSE |
99 | RAISE EXCEPTION 'Failed to parse partitioning property: % !', partition_type; | 135 | RAISE EXCEPTION 'Failed to parse partitioning property: % !', partition_type; |
100 | END CASE; | 136 | END CASE; |
@@ -103,13 +139,16 @@ $$ LANGUAGE plpgsql; | @@ -103,13 +139,16 @@ $$ LANGUAGE plpgsql; | ||
103 | 139 | ||
104 | -- call create_partitions(); | 140 | -- call create_partitions(); |
105 | 141 | ||
106 | -CREATE OR REPLACE PROCEDURE create_partitions(IN partition_type varchar) LANGUAGE plpgsql AS $$ | 142 | +CREATE OR REPLACE PROCEDURE create_partitions(IN partition_type varchar) |
143 | + LANGUAGE plpgsql AS | ||
144 | +$$ | ||
107 | 145 | ||
108 | DECLARE | 146 | DECLARE |
109 | partition_date varchar; | 147 | partition_date varchar; |
110 | from_ts bigint; | 148 | from_ts bigint; |
111 | to_ts bigint; | 149 | to_ts bigint; |
112 | - partitions_cursor CURSOR FOR SELECT * FROM get_partitions_data(partition_type); | 150 | + partitions_cursor CURSOR FOR SELECT * |
151 | + FROM get_partitions_data(partition_type); | ||
113 | BEGIN | 152 | BEGIN |
114 | OPEN partitions_cursor; | 153 | OPEN partitions_cursor; |
115 | LOOP | 154 | LOOP |
@@ -127,21 +166,25 @@ $$; | @@ -127,21 +166,25 @@ $$; | ||
127 | 166 | ||
128 | -- call create_ts_kv_dictionary_table(); | 167 | -- call create_ts_kv_dictionary_table(); |
129 | 168 | ||
130 | -CREATE OR REPLACE PROCEDURE create_ts_kv_dictionary_table() LANGUAGE plpgsql AS $$ | 169 | +CREATE OR REPLACE PROCEDURE create_ts_kv_dictionary_table() |
170 | + LANGUAGE plpgsql AS | ||
171 | +$$ | ||
131 | 172 | ||
132 | BEGIN | 173 | BEGIN |
133 | - CREATE TABLE IF NOT EXISTS ts_kv_dictionary | ||
134 | - ( | ||
135 | - key varchar(255) NOT NULL, | ||
136 | - key_id serial UNIQUE, | ||
137 | - CONSTRAINT ts_key_id_pkey PRIMARY KEY (key) | ||
138 | - ); | 174 | + CREATE TABLE IF NOT EXISTS ts_kv_dictionary |
175 | + ( | ||
176 | + key varchar(255) NOT NULL, | ||
177 | + key_id serial UNIQUE, | ||
178 | + CONSTRAINT ts_key_id_pkey PRIMARY KEY (key) | ||
179 | + ); | ||
139 | END; | 180 | END; |
140 | $$; | 181 | $$; |
141 | 182 | ||
142 | -- call insert_into_dictionary(); | 183 | -- call insert_into_dictionary(); |
143 | 184 | ||
144 | -CREATE OR REPLACE PROCEDURE insert_into_dictionary() LANGUAGE plpgsql AS $$ | 185 | +CREATE OR REPLACE PROCEDURE insert_into_dictionary() |
186 | + LANGUAGE plpgsql AS | ||
187 | +$$ | ||
145 | 188 | ||
146 | DECLARE | 189 | DECLARE |
147 | insert_record RECORD; | 190 | insert_record RECORD; |
@@ -164,31 +207,89 @@ BEGIN | @@ -164,31 +207,89 @@ BEGIN | ||
164 | END; | 207 | END; |
165 | $$; | 208 | $$; |
166 | 209 | ||
167 | --- call insert_into_ts_kv(); | 210 | +CREATE OR REPLACE FUNCTION to_uuid(IN entity_id varchar, OUT uuid_id uuid) AS |
211 | +$$ | ||
212 | +BEGIN | ||
213 | + uuid_id := substring(entity_id, 8, 8) || '-' || substring(entity_id, 4, 4) || '-1' || substring(entity_id, 1, 3) || | ||
214 | + '-' || substring(entity_id, 16, 4) || '-' || substring(entity_id, 20, 12); | ||
215 | +END; | ||
216 | +$$ LANGUAGE plpgsql; | ||
168 | 217 | ||
169 | -CREATE OR REPLACE PROCEDURE insert_into_ts_kv() LANGUAGE plpgsql AS $$ | ||
170 | -DECLARE | ||
171 | - insert_size CONSTANT integer := 10000; | ||
172 | - insert_counter integer DEFAULT 0; | ||
173 | - insert_record RECORD; | ||
174 | - insert_cursor CURSOR FOR SELECT CONCAT(entity_id_uuid_first_part, '-', entity_id_uuid_second_part, '-1', entity_id_uuid_third_part, '-', entity_id_uuid_fourth_part, '-', entity_id_uuid_fifth_part)::uuid AS entity_id, | 218 | +CREATE OR REPLACE PROCEDURE insert_into_ts_kv(IN path_to_file varchar) |
219 | + LANGUAGE plpgsql AS | ||
220 | +$$ | ||
221 | +BEGIN | ||
222 | + EXECUTE format('COPY (SELECT to_uuid(entity_id) AS entity_id, | ||
175 | ts_kv_records.key AS key, | 223 | ts_kv_records.key AS key, |
176 | ts_kv_records.ts AS ts, | 224 | ts_kv_records.ts AS ts, |
177 | ts_kv_records.bool_v AS bool_v, | 225 | ts_kv_records.bool_v AS bool_v, |
178 | ts_kv_records.str_v AS str_v, | 226 | ts_kv_records.str_v AS str_v, |
179 | ts_kv_records.long_v AS long_v, | 227 | ts_kv_records.long_v AS long_v, |
180 | ts_kv_records.dbl_v AS dbl_v | 228 | ts_kv_records.dbl_v AS dbl_v |
181 | - FROM (SELECT SUBSTRING(entity_id, 8, 8) AS entity_id_uuid_first_part, | ||
182 | - SUBSTRING(entity_id, 4, 4) AS entity_id_uuid_second_part, | ||
183 | - SUBSTRING(entity_id, 1, 3) AS entity_id_uuid_third_part, | ||
184 | - SUBSTRING(entity_id, 16, 4) AS entity_id_uuid_fourth_part, | ||
185 | - SUBSTRING(entity_id, 20) AS entity_id_uuid_fifth_part, | 229 | + FROM (SELECT entity_id AS entity_id, |
230 | + key_id AS key, | ||
231 | + ts, | ||
232 | + bool_v, | ||
233 | + str_v, | ||
234 | + long_v, | ||
235 | + dbl_v | ||
236 | + FROM ts_kv_old | ||
237 | + INNER JOIN ts_kv_dictionary ON (ts_kv_old.key = ts_kv_dictionary.key)) AS ts_kv_records) TO %L;', | ||
238 | + path_to_file); | ||
239 | + EXECUTE format('COPY ts_kv FROM %L', path_to_file); | ||
240 | +END | ||
241 | +$$; | ||
242 | + | ||
243 | +-- call insert_into_ts_kv_latest(); | ||
244 | + | ||
245 | +CREATE OR REPLACE PROCEDURE insert_into_ts_kv_latest(IN path_to_file varchar) | ||
246 | + LANGUAGE plpgsql AS | ||
247 | +$$ | ||
248 | +BEGIN | ||
249 | + EXECUTE format('COPY (SELECT to_uuid(entity_id) AS entity_id, | ||
250 | + ts_kv_latest_records.key AS key, | ||
251 | + ts_kv_latest_records.ts AS ts, | ||
252 | + ts_kv_latest_records.bool_v AS bool_v, | ||
253 | + ts_kv_latest_records.str_v AS str_v, | ||
254 | + ts_kv_latest_records.long_v AS long_v, | ||
255 | + ts_kv_latest_records.dbl_v AS dbl_v | ||
256 | + FROM (SELECT entity_id AS entity_id, | ||
186 | key_id AS key, | 257 | key_id AS key, |
187 | ts, | 258 | ts, |
188 | bool_v, | 259 | bool_v, |
189 | str_v, | 260 | str_v, |
190 | long_v, | 261 | long_v, |
191 | dbl_v | 262 | dbl_v |
263 | + FROM ts_kv_latest_old | ||
264 | + INNER JOIN ts_kv_dictionary ON (ts_kv_latest_old.key = ts_kv_dictionary.key)) AS ts_kv_latest_records) TO %L;', | ||
265 | + path_to_file); | ||
266 | + EXECUTE format('COPY ts_kv_latest FROM %L', path_to_file); | ||
267 | +END; | ||
268 | +$$; | ||
269 | + | ||
270 | +-- call insert_into_ts_kv_cursor(); | ||
271 | + | ||
272 | +CREATE OR REPLACE PROCEDURE insert_into_ts_kv_cursor() | ||
273 | + LANGUAGE plpgsql AS | ||
274 | +$$ | ||
275 | +DECLARE | ||
276 | + insert_size CONSTANT integer := 10000; | ||
277 | + insert_counter integer DEFAULT 0; | ||
278 | + insert_record RECORD; | ||
279 | + insert_cursor CURSOR FOR SELECT to_uuid(entity_id) AS entity_id, | ||
280 | + ts_kv_records.key AS key, | ||
281 | + ts_kv_records.ts AS ts, | ||
282 | + ts_kv_records.bool_v AS bool_v, | ||
283 | + ts_kv_records.str_v AS str_v, | ||
284 | + ts_kv_records.long_v AS long_v, | ||
285 | + ts_kv_records.dbl_v AS dbl_v | ||
286 | + FROM (SELECT entity_id AS entity_id, | ||
287 | + key_id AS key, | ||
288 | + ts, | ||
289 | + bool_v, | ||
290 | + str_v, | ||
291 | + long_v, | ||
292 | + dbl_v | ||
192 | FROM ts_kv_old | 293 | FROM ts_kv_old |
193 | INNER JOIN ts_kv_dictionary ON (ts_kv_old.key = ts_kv_dictionary.key)) AS ts_kv_records; | 294 | INNER JOIN ts_kv_dictionary ON (ts_kv_old.key = ts_kv_dictionary.key)) AS ts_kv_records; |
194 | BEGIN | 295 | BEGIN |
@@ -211,26 +312,24 @@ BEGIN | @@ -211,26 +312,24 @@ BEGIN | ||
211 | END; | 312 | END; |
212 | $$; | 313 | $$; |
213 | 314 | ||
214 | --- call insert_into_ts_kv_latest(); | 315 | +-- call insert_into_ts_kv_latest_cursor(); |
215 | 316 | ||
216 | -CREATE OR REPLACE PROCEDURE insert_into_ts_kv_latest() LANGUAGE plpgsql AS $$ | 317 | +CREATE OR REPLACE PROCEDURE insert_into_ts_kv_latest_cursor() |
318 | + LANGUAGE plpgsql AS | ||
319 | +$$ | ||
217 | DECLARE | 320 | DECLARE |
218 | insert_size CONSTANT integer := 10000; | 321 | insert_size CONSTANT integer := 10000; |
219 | insert_counter integer DEFAULT 0; | 322 | insert_counter integer DEFAULT 0; |
220 | insert_record RECORD; | 323 | insert_record RECORD; |
221 | - insert_cursor CURSOR FOR SELECT CONCAT(entity_id_uuid_first_part, '-', entity_id_uuid_second_part, '-1', entity_id_uuid_third_part, '-', entity_id_uuid_fourth_part, '-', entity_id_uuid_fifth_part)::uuid AS entity_id, | ||
222 | - ts_kv_latest_records.key AS key, | ||
223 | - ts_kv_latest_records.ts AS ts, | ||
224 | - ts_kv_latest_records.bool_v AS bool_v, | ||
225 | - ts_kv_latest_records.str_v AS str_v, | ||
226 | - ts_kv_latest_records.long_v AS long_v, | ||
227 | - ts_kv_latest_records.dbl_v AS dbl_v | ||
228 | - FROM (SELECT SUBSTRING(entity_id, 8, 8) AS entity_id_uuid_first_part, | ||
229 | - SUBSTRING(entity_id, 4, 4) AS entity_id_uuid_second_part, | ||
230 | - SUBSTRING(entity_id, 1, 3) AS entity_id_uuid_third_part, | ||
231 | - SUBSTRING(entity_id, 16, 4) AS entity_id_uuid_fourth_part, | ||
232 | - SUBSTRING(entity_id, 20) AS entity_id_uuid_fifth_part, | ||
233 | - key_id AS key, | 324 | + insert_cursor CURSOR FOR SELECT to_uuid(entity_id) AS entity_id, |
325 | + ts_kv_latest_records.key AS key, | ||
326 | + ts_kv_latest_records.ts AS ts, | ||
327 | + ts_kv_latest_records.bool_v AS bool_v, | ||
328 | + ts_kv_latest_records.str_v AS str_v, | ||
329 | + ts_kv_latest_records.long_v AS long_v, | ||
330 | + ts_kv_latest_records.dbl_v AS dbl_v | ||
331 | + FROM (SELECT entity_id AS entity_id, | ||
332 | + key_id AS key, | ||
234 | ts, | 333 | ts, |
235 | bool_v, | 334 | bool_v, |
236 | str_v, | 335 | str_v, |
@@ -258,4 +357,3 @@ BEGIN | @@ -258,4 +357,3 @@ BEGIN | ||
258 | END; | 357 | END; |
259 | $$; | 358 | $$; |
260 | 359 | ||
261 | - |
@@ -96,51 +96,36 @@ BEGIN | @@ -96,51 +96,36 @@ BEGIN | ||
96 | END; | 96 | END; |
97 | $$; | 97 | $$; |
98 | 98 | ||
99 | --- call insert_into_ts_kv(); | 99 | +CREATE OR REPLACE FUNCTION to_uuid(IN entity_id varchar, OUT uuid_id uuid) AS |
100 | +$$ | ||
101 | +BEGIN | ||
102 | + uuid_id := substring(entity_id, 8, 8) || '-' || substring(entity_id, 4, 4) || '-1' || substring(entity_id, 1, 3) || | ||
103 | + '-' || substring(entity_id, 16, 4) || '-' || substring(entity_id, 20, 12); | ||
104 | +END; | ||
105 | +$$ LANGUAGE plpgsql; | ||
100 | 106 | ||
101 | -CREATE OR REPLACE PROCEDURE insert_into_ts_kv() LANGUAGE plpgsql AS $$ | 107 | +-- call insert_into_ts_kv(); |
102 | 108 | ||
103 | -DECLARE | ||
104 | - insert_size CONSTANT integer := 10000; | ||
105 | - insert_counter integer DEFAULT 0; | ||
106 | - insert_record RECORD; | ||
107 | - insert_cursor CURSOR FOR SELECT CONCAT(entity_id_uuid_first_part, '-', entity_id_uuid_second_part, '-1', entity_id_uuid_third_part, '-', entity_id_uuid_fourth_part, '-', entity_id_uuid_fifth_part)::uuid AS entity_id, | ||
108 | - new_ts_kv_records.key AS key, | ||
109 | - new_ts_kv_records.ts AS ts, | ||
110 | - new_ts_kv_records.bool_v AS bool_v, | ||
111 | - new_ts_kv_records.str_v AS str_v, | ||
112 | - new_ts_kv_records.long_v AS long_v, | ||
113 | - new_ts_kv_records.dbl_v AS dbl_v | ||
114 | - FROM (SELECT SUBSTRING(entity_id, 8, 8) AS entity_id_uuid_first_part, | ||
115 | - SUBSTRING(entity_id, 4, 4) AS entity_id_uuid_second_part, | ||
116 | - SUBSTRING(entity_id, 1, 3) AS entity_id_uuid_third_part, | ||
117 | - SUBSTRING(entity_id, 16, 4) AS entity_id_uuid_fourth_part, | ||
118 | - SUBSTRING(entity_id, 20) AS entity_id_uuid_fifth_part, | ||
119 | - key_id AS key, | ||
120 | - ts, | ||
121 | - bool_v, | ||
122 | - str_v, | ||
123 | - long_v, | ||
124 | - dbl_v | ||
125 | - FROM tenant_ts_kv_old | ||
126 | - INNER JOIN ts_kv_dictionary ON (tenant_ts_kv_old.key = ts_kv_dictionary.key)) AS new_ts_kv_records; | 109 | +CREATE OR REPLACE PROCEDURE insert_into_ts_kv(IN path_to_file varchar) LANGUAGE plpgsql AS $$ |
127 | BEGIN | 110 | BEGIN |
128 | - OPEN insert_cursor; | ||
129 | - LOOP | ||
130 | - insert_counter := insert_counter + 1; | ||
131 | - FETCH insert_cursor INTO insert_record; | ||
132 | - IF NOT FOUND THEN | ||
133 | - RAISE NOTICE '% records have been inserted into the new ts_kv table!',insert_counter - 1; | ||
134 | - EXIT; | ||
135 | - END IF; | ||
136 | - INSERT INTO ts_kv(entity_id, key, ts, bool_v, str_v, long_v, dbl_v) | ||
137 | - VALUES (insert_record.entity_id, insert_record.key, insert_record.ts, insert_record.bool_v, insert_record.str_v, | ||
138 | - insert_record.long_v, insert_record.dbl_v); | ||
139 | - IF MOD(insert_counter, insert_size) = 0 THEN | ||
140 | - RAISE NOTICE '% records have been inserted into the new ts_kv table!',insert_counter; | ||
141 | - END IF; | ||
142 | - END LOOP; | ||
143 | - CLOSE insert_cursor; | 111 | + |
112 | + EXECUTE format ('COPY (SELECT to_uuid(entity_id) AS entity_id, | ||
113 | + new_ts_kv_records.key AS key, | ||
114 | + new_ts_kv_records.ts AS ts, | ||
115 | + new_ts_kv_records.bool_v AS bool_v, | ||
116 | + new_ts_kv_records.str_v AS str_v, | ||
117 | + new_ts_kv_records.long_v AS long_v, | ||
118 | + new_ts_kv_records.dbl_v AS dbl_v | ||
119 | + FROM (SELECT entity_id AS entity_id, | ||
120 | + key_id AS key, | ||
121 | + ts, | ||
122 | + bool_v, | ||
123 | + str_v, | ||
124 | + long_v, | ||
125 | + dbl_v | ||
126 | + FROM tenant_ts_kv_old | ||
127 | + INNER JOIN ts_kv_dictionary ON (tenant_ts_kv_old.key = ts_kv_dictionary.key)) AS new_ts_kv_records) TO %L;', path_to_file); | ||
128 | + EXECUTE format ('COPY ts_kv FROM %L', path_to_file); | ||
144 | END; | 129 | END; |
145 | $$; | 130 | $$; |
146 | 131 | ||
@@ -177,3 +162,47 @@ BEGIN | @@ -177,3 +162,47 @@ BEGIN | ||
177 | CLOSE insert_cursor; | 162 | CLOSE insert_cursor; |
178 | END; | 163 | END; |
179 | $$; | 164 | $$; |
165 | + | ||
166 | +-- call insert_into_ts_kv_cursor(); | ||
167 | + | ||
168 | +CREATE OR REPLACE PROCEDURE insert_into_ts_kv_cursor() LANGUAGE plpgsql AS $$ | ||
169 | + | ||
170 | +DECLARE | ||
171 | + insert_size CONSTANT integer := 10000; | ||
172 | + insert_counter integer DEFAULT 0; | ||
173 | + insert_record RECORD; | ||
174 | + insert_cursor CURSOR FOR SELECT to_uuid(entity_id) AS entity_id, | ||
175 | + new_ts_kv_records.key AS key, | ||
176 | + new_ts_kv_records.ts AS ts, | ||
177 | + new_ts_kv_records.bool_v AS bool_v, | ||
178 | + new_ts_kv_records.str_v AS str_v, | ||
179 | + new_ts_kv_records.long_v AS long_v, | ||
180 | + new_ts_kv_records.dbl_v AS dbl_v | ||
181 | + FROM (SELECT entity_id AS entity_id, | ||
182 | + key_id AS key, | ||
183 | + ts, | ||
184 | + bool_v, | ||
185 | + str_v, | ||
186 | + long_v, | ||
187 | + dbl_v | ||
188 | + FROM tenant_ts_kv_old | ||
189 | + INNER JOIN ts_kv_dictionary ON (tenant_ts_kv_old.key = ts_kv_dictionary.key)) AS new_ts_kv_records; | ||
190 | +BEGIN | ||
191 | + OPEN insert_cursor; | ||
192 | + LOOP | ||
193 | + insert_counter := insert_counter + 1; | ||
194 | + FETCH insert_cursor INTO insert_record; | ||
195 | + IF NOT FOUND THEN | ||
196 | + RAISE NOTICE '% records have been inserted into the new ts_kv table!',insert_counter - 1; | ||
197 | + EXIT; | ||
198 | + END IF; | ||
199 | + INSERT INTO ts_kv(entity_id, key, ts, bool_v, str_v, long_v, dbl_v) | ||
200 | + VALUES (insert_record.entity_id, insert_record.key, insert_record.ts, insert_record.bool_v, insert_record.str_v, | ||
201 | + insert_record.long_v, insert_record.dbl_v); | ||
202 | + IF MOD(insert_counter, insert_size) = 0 THEN | ||
203 | + RAISE NOTICE '% records have been inserted into the new ts_kv table!',insert_counter; | ||
204 | + END IF; | ||
205 | + END LOOP; | ||
206 | + CLOSE insert_cursor; | ||
207 | +END; | ||
208 | +$$; |
@@ -56,6 +56,7 @@ import org.thingsboard.server.dao.audit.AuditLogService; | @@ -56,6 +56,7 @@ import org.thingsboard.server.dao.audit.AuditLogService; | ||
56 | import org.thingsboard.server.dao.cassandra.CassandraCluster; | 56 | import org.thingsboard.server.dao.cassandra.CassandraCluster; |
57 | import org.thingsboard.server.dao.customer.CustomerService; | 57 | import org.thingsboard.server.dao.customer.CustomerService; |
58 | import org.thingsboard.server.dao.dashboard.DashboardService; | 58 | import org.thingsboard.server.dao.dashboard.DashboardService; |
59 | +import org.thingsboard.server.dao.device.ClaimDevicesService; | ||
59 | import org.thingsboard.server.dao.device.DeviceService; | 60 | import org.thingsboard.server.dao.device.DeviceService; |
60 | import org.thingsboard.server.dao.edge.EdgeService; | 61 | import org.thingsboard.server.dao.edge.EdgeService; |
61 | import org.thingsboard.server.dao.entityview.EntityViewService; | 62 | import org.thingsboard.server.dao.entityview.EntityViewService; |
@@ -219,6 +220,10 @@ public class ActorSystemContext { | @@ -219,6 +220,10 @@ public class ActorSystemContext { | ||
219 | @Getter | 220 | @Getter |
220 | private MailService mailService; | 221 | private MailService mailService; |
221 | 222 | ||
223 | + @Autowired | ||
224 | + @Getter | ||
225 | + private ClaimDevicesService claimDevicesService; | ||
226 | + | ||
222 | //TODO: separate context for TbCore and TbRuleEngine | 227 | //TODO: separate context for TbCore and TbRuleEngine |
223 | @Autowired(required = false) | 228 | @Autowired(required = false) |
224 | @Getter | 229 | @Getter |
@@ -39,6 +39,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; | @@ -39,6 +39,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; | ||
39 | import org.thingsboard.server.common.msg.queue.TbCallback; | 39 | import org.thingsboard.server.common.msg.queue.TbCallback; |
40 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; | 40 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
41 | import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; | 41 | import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; |
42 | +import org.thingsboard.server.gen.transport.TransportProtos; | ||
42 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; | 43 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; |
43 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceSessionsCacheEntry; | 44 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceSessionsCacheEntry; |
44 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; | 45 | import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; |
@@ -232,9 +233,17 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -232,9 +233,17 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
232 | if (msg.hasSubscriptionInfo()) { | 233 | if (msg.hasSubscriptionInfo()) { |
233 | handleSessionActivity(context, msg.getSessionInfo(), msg.getSubscriptionInfo()); | 234 | handleSessionActivity(context, msg.getSessionInfo(), msg.getSubscriptionInfo()); |
234 | } | 235 | } |
236 | + if (msg.hasClaimDevice()) { | ||
237 | + handleClaimDeviceMsg(context, msg.getSessionInfo(), msg.getClaimDevice()); | ||
238 | + } | ||
235 | callback.onSuccess(); | 239 | callback.onSuccess(); |
236 | } | 240 | } |
237 | 241 | ||
242 | + private void handleClaimDeviceMsg(ActorContext context, SessionInfoProto sessionInfo, TransportProtos.ClaimDeviceMsg msg) { | ||
243 | + DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB())); | ||
244 | + systemContext.getClaimDevicesService().registerClaimingInfo(tenantId, deviceId, msg.getSecretKey(), msg.getDurationMs()); | ||
245 | + } | ||
246 | + | ||
238 | private void reportSessionOpen() { | 247 | private void reportSessionOpen() { |
239 | systemContext.getDeviceStateService().onDeviceConnect(deviceId); | 248 | systemContext.getDeviceStateService().onDeviceConnect(deviceId); |
240 | } | 249 | } |
@@ -28,7 +28,6 @@ import org.springframework.web.bind.annotation.ResponseStatus; | @@ -28,7 +28,6 @@ import org.springframework.web.bind.annotation.ResponseStatus; | ||
28 | import org.springframework.web.bind.annotation.RestController; | 28 | import org.springframework.web.bind.annotation.RestController; |
29 | import org.thingsboard.server.common.data.EntityType; | 29 | import org.thingsboard.server.common.data.EntityType; |
30 | import org.thingsboard.server.common.data.alarm.Alarm; | 30 | import org.thingsboard.server.common.data.alarm.Alarm; |
31 | -import org.thingsboard.server.common.data.id.AlarmId; | ||
32 | import org.thingsboard.server.common.data.alarm.AlarmInfo; | 31 | import org.thingsboard.server.common.data.alarm.AlarmInfo; |
33 | import org.thingsboard.server.common.data.alarm.AlarmQuery; | 32 | import org.thingsboard.server.common.data.alarm.AlarmQuery; |
34 | import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; | 33 | import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; |
@@ -37,6 +36,7 @@ import org.thingsboard.server.common.data.alarm.AlarmStatus; | @@ -37,6 +36,7 @@ import org.thingsboard.server.common.data.alarm.AlarmStatus; | ||
37 | import org.thingsboard.server.common.data.audit.ActionType; | 36 | import org.thingsboard.server.common.data.audit.ActionType; |
38 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | 37 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
39 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 38 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
39 | +import org.thingsboard.server.common.data.id.AlarmId; | ||
40 | import org.thingsboard.server.common.data.id.EntityId; | 40 | import org.thingsboard.server.common.data.id.EntityId; |
41 | import org.thingsboard.server.common.data.id.EntityIdFactory; | 41 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
42 | import org.thingsboard.server.common.data.page.TimePageData; | 42 | import org.thingsboard.server.common.data.page.TimePageData; |
@@ -84,8 +84,9 @@ public class AlarmController extends BaseController { | @@ -84,8 +84,9 @@ public class AlarmController extends BaseController { | ||
84 | public Alarm saveAlarm(@RequestBody Alarm alarm) throws ThingsboardException { | 84 | public Alarm saveAlarm(@RequestBody Alarm alarm) throws ThingsboardException { |
85 | try { | 85 | try { |
86 | alarm.setTenantId(getCurrentUser().getTenantId()); | 86 | alarm.setTenantId(getCurrentUser().getTenantId()); |
87 | - Operation operation = alarm.getId() == null ? Operation.CREATE : Operation.WRITE; | ||
88 | - accessControlService.checkPermission(getCurrentUser(), Resource.ALARM, operation, alarm.getId(), alarm); | 87 | + |
88 | + checkEntity(alarm.getId(), alarm, Resource.ALARM); | ||
89 | + | ||
89 | Alarm savedAlarm = checkNotNull(alarmService.createOrUpdateAlarm(alarm)); | 90 | Alarm savedAlarm = checkNotNull(alarmService.createOrUpdateAlarm(alarm)); |
90 | logEntityAction(savedAlarm.getId(), savedAlarm, | 91 | logEntityAction(savedAlarm.getId(), savedAlarm, |
91 | getCurrentUser().getCustomerId(), | 92 | getCurrentUser().getCustomerId(), |
@@ -82,18 +82,15 @@ public class AssetController extends BaseController { | @@ -82,18 +82,15 @@ public class AssetController extends BaseController { | ||
82 | try { | 82 | try { |
83 | asset.setTenantId(getCurrentUser().getTenantId()); | 83 | asset.setTenantId(getCurrentUser().getTenantId()); |
84 | 84 | ||
85 | - Operation operation = asset.getId() == null ? Operation.CREATE : Operation.WRITE; | 85 | + checkEntity(asset.getId(), asset, Resource.ASSET); |
86 | 86 | ||
87 | - accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, operation, | ||
88 | - asset.getId(), asset); | ||
89 | - | ||
90 | - Asset savedAsset = checkNotNull(assetService.saveAsset(asset)); | 87 | + Asset savedAsset = checkNotNull(assetService.saveAsset(asset)); |
91 | 88 | ||
92 | logEntityAction(savedAsset.getId(), savedAsset, | 89 | logEntityAction(savedAsset.getId(), savedAsset, |
93 | savedAsset.getCustomerId(), | 90 | savedAsset.getCustomerId(), |
94 | asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); | 91 | asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); |
95 | 92 | ||
96 | - return savedAsset; | 93 | + return savedAsset; |
97 | } catch (Exception e) { | 94 | } catch (Exception e) { |
98 | logEntityAction(emptyId(EntityType.ASSET), asset, | 95 | logEntityAction(emptyId(EntityType.ASSET), asset, |
99 | null, asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e); | 96 | null, asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e); |
@@ -144,7 +141,7 @@ public class AssetController extends BaseController { | @@ -144,7 +141,7 @@ public class AssetController extends BaseController { | ||
144 | savedAsset.getCustomerId(), | 141 | savedAsset.getCustomerId(), |
145 | ActionType.ASSIGNED_TO_CUSTOMER, null, strAssetId, strCustomerId, customer.getName()); | 142 | ActionType.ASSIGNED_TO_CUSTOMER, null, strAssetId, strCustomerId, customer.getName()); |
146 | 143 | ||
147 | - return savedAsset; | 144 | + return savedAsset; |
148 | } catch (Exception e) { | 145 | } catch (Exception e) { |
149 | 146 | ||
150 | logEntityAction(emptyId(EntityType.ASSET), null, | 147 | logEntityAction(emptyId(EntityType.ASSET), null, |
@@ -224,7 +221,7 @@ public class AssetController extends BaseController { | @@ -224,7 +221,7 @@ public class AssetController extends BaseController { | ||
224 | try { | 221 | try { |
225 | TenantId tenantId = getCurrentUser().getTenantId(); | 222 | TenantId tenantId = getCurrentUser().getTenantId(); |
226 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 223 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); |
227 | - if (type != null && type.trim().length()>0) { | 224 | + if (type != null && type.trim().length() > 0) { |
228 | return checkNotNull(assetService.findAssetsByTenantIdAndType(tenantId, type, pageLink)); | 225 | return checkNotNull(assetService.findAssetsByTenantIdAndType(tenantId, type, pageLink)); |
229 | } else { | 226 | } else { |
230 | return checkNotNull(assetService.findAssetsByTenantId(tenantId, pageLink)); | 227 | return checkNotNull(assetService.findAssetsByTenantId(tenantId, pageLink)); |
@@ -263,7 +260,7 @@ public class AssetController extends BaseController { | @@ -263,7 +260,7 @@ public class AssetController extends BaseController { | ||
263 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | 260 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); |
264 | checkCustomerId(customerId, Operation.READ); | 261 | checkCustomerId(customerId, Operation.READ); |
265 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 262 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); |
266 | - if (type != null && type.trim().length()>0) { | 263 | + if (type != null && type.trim().length() > 0) { |
267 | return checkNotNull(assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); | 264 | return checkNotNull(assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); |
268 | } else { | 265 | } else { |
269 | return checkNotNull(assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink)); | 266 | return checkNotNull(assetService.findAssetsByTenantIdAndCustomerId(tenantId, customerId, pageLink)); |
@@ -26,6 +26,7 @@ import org.springframework.beans.factory.annotation.Value; | @@ -26,6 +26,7 @@ import org.springframework.beans.factory.annotation.Value; | ||
26 | import org.springframework.security.core.Authentication; | 26 | import org.springframework.security.core.Authentication; |
27 | import org.springframework.security.core.context.SecurityContextHolder; | 27 | import org.springframework.security.core.context.SecurityContextHolder; |
28 | import org.springframework.web.bind.annotation.ExceptionHandler; | 28 | import org.springframework.web.bind.annotation.ExceptionHandler; |
29 | +import org.thingsboard.server.common.data.BaseData; | ||
29 | import org.thingsboard.server.common.data.Customer; | 30 | import org.thingsboard.server.common.data.Customer; |
30 | import org.thingsboard.server.common.data.Dashboard; | 31 | import org.thingsboard.server.common.data.Dashboard; |
31 | import org.thingsboard.server.common.data.DashboardInfo; | 32 | import org.thingsboard.server.common.data.DashboardInfo; |
@@ -107,7 +108,6 @@ import org.thingsboard.server.service.state.DeviceStateService; | @@ -107,7 +108,6 @@ import org.thingsboard.server.service.state.DeviceStateService; | ||
107 | import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; | 108 | import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; |
108 | 109 | ||
109 | import javax.mail.MessagingException; | 110 | import javax.mail.MessagingException; |
110 | -import javax.servlet.http.HttpServletRequest; | ||
111 | import javax.servlet.http.HttpServletResponse; | 111 | import javax.servlet.http.HttpServletResponse; |
112 | import java.util.List; | 112 | import java.util.List; |
113 | import java.util.Optional; | 113 | import java.util.Optional; |
@@ -337,11 +337,23 @@ public abstract class BaseController { | @@ -337,11 +337,23 @@ public abstract class BaseController { | ||
337 | } | 337 | } |
338 | } | 338 | } |
339 | 339 | ||
340 | + protected <I extends EntityId, T extends HasTenantId> void checkEntity(I entityId, T entity, Resource resource) throws ThingsboardException { | ||
341 | + if (entityId == null) { | ||
342 | + accessControlService | ||
343 | + .checkPermission(getCurrentUser(), resource, Operation.CREATE, null, entity); | ||
344 | + } else { | ||
345 | + checkEntityId(entityId, Operation.WRITE); | ||
346 | + } | ||
347 | + } | ||
348 | + | ||
340 | protected void checkEntityId(EntityId entityId, Operation operation) throws ThingsboardException { | 349 | protected void checkEntityId(EntityId entityId, Operation operation) throws ThingsboardException { |
341 | try { | 350 | try { |
342 | checkNotNull(entityId); | 351 | checkNotNull(entityId); |
343 | validateId(entityId.getId(), "Incorrect entityId " + entityId); | 352 | validateId(entityId.getId(), "Incorrect entityId " + entityId); |
344 | switch (entityId.getEntityType()) { | 353 | switch (entityId.getEntityType()) { |
354 | + case ALARM: | ||
355 | + checkAlarmId(new AlarmId(entityId.getId()), operation); | ||
356 | + return; | ||
345 | case DEVICE: | 357 | case DEVICE: |
346 | checkDeviceId(new DeviceId(entityId.getId()), operation); | 358 | checkDeviceId(new DeviceId(entityId.getId()), operation); |
347 | return; | 359 | return; |
@@ -372,6 +384,12 @@ public abstract class BaseController { | @@ -372,6 +384,12 @@ public abstract class BaseController { | ||
372 | case EDGE: | 384 | case EDGE: |
373 | checkEdgeId(new EdgeId(entityId.getId()), operation); | 385 | checkEdgeId(new EdgeId(entityId.getId()), operation); |
374 | return; | 386 | return; |
387 | + case WIDGETS_BUNDLE: | ||
388 | + checkWidgetsBundleId(new WidgetsBundleId(entityId.getId()), operation); | ||
389 | + return; | ||
390 | + case WIDGET_TYPE: | ||
391 | + checkWidgetTypeId(new WidgetTypeId(entityId.getId()), operation); | ||
392 | + return; | ||
375 | default: | 393 | default: |
376 | throw new IllegalArgumentException("Unsupported entity type: " + entityId.getEntityType()); | 394 | throw new IllegalArgumentException("Unsupported entity type: " + entityId.getEntityType()); |
377 | } | 395 | } |
@@ -100,8 +100,7 @@ public class CustomerController extends BaseController { | @@ -100,8 +100,7 @@ public class CustomerController extends BaseController { | ||
100 | try { | 100 | try { |
101 | customer.setTenantId(getCurrentUser().getTenantId()); | 101 | customer.setTenantId(getCurrentUser().getTenantId()); |
102 | 102 | ||
103 | - Operation operation = customer.getId() == null ? Operation.CREATE : Operation.WRITE; | ||
104 | - accessControlService.checkPermission(getCurrentUser(), Resource.CUSTOMER, operation, customer.getId(), customer); | 103 | + checkEntity(customer.getId(), customer, Resource.CUSTOMER); |
105 | 104 | ||
106 | Customer savedCustomer = checkNotNull(customerService.saveCustomer(customer)); | 105 | Customer savedCustomer = checkNotNull(customerService.saveCustomer(customer)); |
107 | 106 |
@@ -103,15 +103,12 @@ public class DashboardController extends BaseController { | @@ -103,15 +103,12 @@ public class DashboardController extends BaseController { | ||
103 | 103 | ||
104 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 104 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
105 | @RequestMapping(value = "/dashboard", method = RequestMethod.POST) | 105 | @RequestMapping(value = "/dashboard", method = RequestMethod.POST) |
106 | - @ResponseBody | 106 | + @ResponseBody |
107 | public Dashboard saveDashboard(@RequestBody Dashboard dashboard) throws ThingsboardException { | 107 | public Dashboard saveDashboard(@RequestBody Dashboard dashboard) throws ThingsboardException { |
108 | try { | 108 | try { |
109 | dashboard.setTenantId(getCurrentUser().getTenantId()); | 109 | dashboard.setTenantId(getCurrentUser().getTenantId()); |
110 | 110 | ||
111 | - Operation operation = dashboard.getId() == null ? Operation.CREATE : Operation.WRITE; | ||
112 | - | ||
113 | - accessControlService.checkPermission(getCurrentUser(), Resource.DASHBOARD, operation, | ||
114 | - dashboard.getId(), dashboard); | 111 | + checkEntity(dashboard.getId(), dashboard, Resource.DASHBOARD); |
115 | 112 | ||
116 | Dashboard savedDashboard = checkNotNull(dashboardService.saveDashboard(dashboard)); | 113 | Dashboard savedDashboard = checkNotNull(dashboardService.saveDashboard(dashboard)); |
117 | 114 | ||
@@ -155,9 +152,9 @@ public class DashboardController extends BaseController { | @@ -155,9 +152,9 @@ public class DashboardController extends BaseController { | ||
155 | 152 | ||
156 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 153 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
157 | @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.POST) | 154 | @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.POST) |
158 | - @ResponseBody | 155 | + @ResponseBody |
159 | public Dashboard assignDashboardToCustomer(@PathVariable("customerId") String strCustomerId, | 156 | public Dashboard assignDashboardToCustomer(@PathVariable("customerId") String strCustomerId, |
160 | - @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { | 157 | + @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { |
161 | checkParameter("customerId", strCustomerId); | 158 | checkParameter("customerId", strCustomerId); |
162 | checkParameter(DASHBOARD_ID, strDashboardId); | 159 | checkParameter(DASHBOARD_ID, strDashboardId); |
163 | try { | 160 | try { |
@@ -166,7 +163,7 @@ public class DashboardController extends BaseController { | @@ -166,7 +163,7 @@ public class DashboardController extends BaseController { | ||
166 | 163 | ||
167 | DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); | 164 | DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); |
168 | checkDashboardId(dashboardId, Operation.ASSIGN_TO_CUSTOMER); | 165 | checkDashboardId(dashboardId, Operation.ASSIGN_TO_CUSTOMER); |
169 | - | 166 | + |
170 | Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(getCurrentUser().getTenantId(), dashboardId, customerId)); | 167 | Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(getCurrentUser().getTenantId(), dashboardId, customerId)); |
171 | 168 | ||
172 | logEntityAction(dashboardId, savedDashboard, | 169 | logEntityAction(dashboardId, savedDashboard, |
@@ -187,7 +184,7 @@ public class DashboardController extends BaseController { | @@ -187,7 +184,7 @@ public class DashboardController extends BaseController { | ||
187 | 184 | ||
188 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 185 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
189 | @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.DELETE) | 186 | @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.DELETE) |
190 | - @ResponseBody | 187 | + @ResponseBody |
191 | public Dashboard unassignDashboardFromCustomer(@PathVariable("customerId") String strCustomerId, | 188 | public Dashboard unassignDashboardFromCustomer(@PathVariable("customerId") String strCustomerId, |
192 | @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { | 189 | @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { |
193 | checkParameter("customerId", strCustomerId); | 190 | checkParameter("customerId", strCustomerId); |
@@ -421,7 +418,7 @@ public class DashboardController extends BaseController { | @@ -421,7 +418,7 @@ public class DashboardController extends BaseController { | ||
421 | } | 418 | } |
422 | 419 | ||
423 | @PreAuthorize("hasAuthority('SYS_ADMIN')") | 420 | @PreAuthorize("hasAuthority('SYS_ADMIN')") |
424 | - @RequestMapping(value = "/tenant/{tenantId}/dashboards", params = { "limit" }, method = RequestMethod.GET) | 421 | + @RequestMapping(value = "/tenant/{tenantId}/dashboards", params = {"limit"}, method = RequestMethod.GET) |
425 | @ResponseBody | 422 | @ResponseBody |
426 | public TextPageData<DashboardInfo> getTenantDashboards( | 423 | public TextPageData<DashboardInfo> getTenantDashboards( |
427 | @PathVariable("tenantId") String strTenantId, | 424 | @PathVariable("tenantId") String strTenantId, |
@@ -440,7 +437,7 @@ public class DashboardController extends BaseController { | @@ -440,7 +437,7 @@ public class DashboardController extends BaseController { | ||
440 | } | 437 | } |
441 | 438 | ||
442 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 439 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
443 | - @RequestMapping(value = "/tenant/dashboards", params = { "limit" }, method = RequestMethod.GET) | 440 | + @RequestMapping(value = "/tenant/dashboards", params = {"limit"}, method = RequestMethod.GET) |
444 | @ResponseBody | 441 | @ResponseBody |
445 | public TextPageData<DashboardInfo> getTenantDashboards( | 442 | public TextPageData<DashboardInfo> getTenantDashboards( |
446 | @RequestParam int limit, | 443 | @RequestParam int limit, |
@@ -457,7 +454,7 @@ public class DashboardController extends BaseController { | @@ -457,7 +454,7 @@ public class DashboardController extends BaseController { | ||
457 | } | 454 | } |
458 | 455 | ||
459 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 456 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
460 | - @RequestMapping(value = "/customer/{customerId}/dashboards", params = { "limit" }, method = RequestMethod.GET) | 457 | + @RequestMapping(value = "/customer/{customerId}/dashboards", params = {"limit"}, method = RequestMethod.GET) |
461 | @ResponseBody | 458 | @ResponseBody |
462 | public TimePageData<DashboardInfo> getCustomerDashboards( | 459 | public TimePageData<DashboardInfo> getCustomerDashboards( |
463 | @PathVariable("customerId") String strCustomerId, | 460 | @PathVariable("customerId") String strCustomerId, |
@@ -99,10 +99,7 @@ public class DeviceController extends BaseController { | @@ -99,10 +99,7 @@ public class DeviceController extends BaseController { | ||
99 | try { | 99 | try { |
100 | device.setTenantId(getCurrentUser().getTenantId()); | 100 | device.setTenantId(getCurrentUser().getTenantId()); |
101 | 101 | ||
102 | - Operation operation = device.getId() == null ? Operation.CREATE : Operation.WRITE; | ||
103 | - | ||
104 | - accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, operation, | ||
105 | - device.getId(), device); | 102 | + checkEntity(device.getId(), device, Resource.DEVICE); |
106 | 103 | ||
107 | Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken)); | 104 | Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken)); |
108 | 105 |
@@ -97,10 +97,7 @@ public class EntityViewController extends BaseController { | @@ -97,10 +97,7 @@ public class EntityViewController extends BaseController { | ||
97 | try { | 97 | try { |
98 | entityView.setTenantId(getCurrentUser().getTenantId()); | 98 | entityView.setTenantId(getCurrentUser().getTenantId()); |
99 | 99 | ||
100 | - Operation operation = entityView.getId() == null ? Operation.CREATE : Operation.WRITE; | ||
101 | - | ||
102 | - accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, operation, | ||
103 | - entityView.getId(), entityView); | 100 | + checkEntity(entityView.getId(), entityView, Resource.ENTITY_VIEW); |
104 | 101 | ||
105 | EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView)); | 102 | EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView)); |
106 | List<ListenableFuture<List<Void>>> futures = new ArrayList<>(); | 103 | List<ListenableFuture<List<Void>>> futures = new ArrayList<>(); |
@@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; | @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; | ||
20 | import com.google.common.util.concurrent.FutureCallback; | 20 | import com.google.common.util.concurrent.FutureCallback; |
21 | import lombok.extern.slf4j.Slf4j; | 21 | import lombok.extern.slf4j.Slf4j; |
22 | import org.springframework.beans.factory.annotation.Autowired; | 22 | import org.springframework.beans.factory.annotation.Autowired; |
23 | +import org.springframework.beans.factory.annotation.Value; | ||
23 | import org.springframework.http.HttpStatus; | 24 | import org.springframework.http.HttpStatus; |
24 | import org.springframework.http.ResponseEntity; | 25 | import org.springframework.http.ResponseEntity; |
25 | import org.springframework.security.access.prepost.PreAuthorize; | 26 | import org.springframework.security.access.prepost.PreAuthorize; |
@@ -65,7 +66,6 @@ import java.util.UUID; | @@ -65,7 +66,6 @@ import java.util.UUID; | ||
65 | @Slf4j | 66 | @Slf4j |
66 | public class RpcController extends BaseController { | 67 | public class RpcController extends BaseController { |
67 | 68 | ||
68 | - public static final int DEFAULT_TIMEOUT = 10000; | ||
69 | protected final ObjectMapper jsonMapper = new ObjectMapper(); | 69 | protected final ObjectMapper jsonMapper = new ObjectMapper(); |
70 | 70 | ||
71 | @Autowired | 71 | @Autowired |
@@ -74,6 +74,12 @@ public class RpcController extends BaseController { | @@ -74,6 +74,12 @@ public class RpcController extends BaseController { | ||
74 | @Autowired | 74 | @Autowired |
75 | private AccessValidator accessValidator; | 75 | private AccessValidator accessValidator; |
76 | 76 | ||
77 | + @Value("${server.rest.server_side_rpc.min_timeout:5000}") | ||
78 | + private long minTimeout; | ||
79 | + | ||
80 | + @Value("${server.rest.server_side_rpc.default_timeout:10000}") | ||
81 | + private long defaultTimeout; | ||
82 | + | ||
77 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 83 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
78 | @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST) | 84 | @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST) |
79 | @ResponseBody | 85 | @ResponseBody |
@@ -100,7 +106,8 @@ public class RpcController extends BaseController { | @@ -100,7 +106,8 @@ public class RpcController extends BaseController { | ||
100 | SecurityUser currentUser = getCurrentUser(); | 106 | SecurityUser currentUser = getCurrentUser(); |
101 | TenantId tenantId = currentUser.getTenantId(); | 107 | TenantId tenantId = currentUser.getTenantId(); |
102 | final DeferredResult<ResponseEntity> response = new DeferredResult<>(); | 108 | final DeferredResult<ResponseEntity> response = new DeferredResult<>(); |
103 | - long timeout = System.currentTimeMillis() + (cmd.getTimeout() != null ? cmd.getTimeout() : DEFAULT_TIMEOUT); | 109 | + long timeout = cmd.getTimeout() != null ? cmd.getTimeout() : defaultTimeout; |
110 | + long expTime = System.currentTimeMillis() + Math.max(minTimeout, timeout); | ||
104 | ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(cmd.getMethodName(), cmd.getRequestData()); | 111 | ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(cmd.getMethodName(), cmd.getRequestData()); |
105 | accessValidator.validate(currentUser, Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<DeferredResult<ResponseEntity>>() { | 112 | accessValidator.validate(currentUser, Operation.RPC_CALL, deviceId, new HttpValidationCallback(response, new FutureCallback<DeferredResult<ResponseEntity>>() { |
106 | @Override | 113 | @Override |
@@ -109,7 +116,7 @@ public class RpcController extends BaseController { | @@ -109,7 +116,7 @@ public class RpcController extends BaseController { | ||
109 | tenantId, | 116 | tenantId, |
110 | deviceId, | 117 | deviceId, |
111 | oneWay, | 118 | oneWay, |
112 | - timeout, | 119 | + expTime, |
113 | body | 120 | body |
114 | ); | 121 | ); |
115 | deviceRpcService.processRestApiRpcRequest(rpcRequest, fromDeviceRpcResponse -> reply(new LocalRequestMetaData(rpcRequest, currentUser, result), fromDeviceRpcResponse)); | 122 | deviceRpcService.processRestApiRpcRequest(rpcRequest, fromDeviceRpcResponse -> reply(new LocalRequestMetaData(rpcRequest, currentUser, result), fromDeviceRpcResponse)); |
@@ -130,10 +130,7 @@ public class RuleChainController extends BaseController { | @@ -130,10 +130,7 @@ public class RuleChainController extends BaseController { | ||
130 | boolean created = ruleChain.getId() == null; | 130 | boolean created = ruleChain.getId() == null; |
131 | ruleChain.setTenantId(getCurrentUser().getTenantId()); | 131 | ruleChain.setTenantId(getCurrentUser().getTenantId()); |
132 | 132 | ||
133 | - Operation operation = created ? Operation.CREATE : Operation.WRITE; | ||
134 | - | ||
135 | - accessControlService.checkPermission(getCurrentUser(), Resource.RULE_CHAIN, operation, | ||
136 | - ruleChain.getId(), ruleChain); | 133 | + checkEntity(ruleChain.getId(), ruleChain, Resource.RULE_CHAIN); |
137 | 134 | ||
138 | RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain)); | 135 | RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain)); |
139 | 136 |
@@ -72,10 +72,8 @@ public class TenantController extends BaseController { | @@ -72,10 +72,8 @@ public class TenantController extends BaseController { | ||
72 | try { | 72 | try { |
73 | boolean newTenant = tenant.getId() == null; | 73 | boolean newTenant = tenant.getId() == null; |
74 | 74 | ||
75 | - Operation operation = newTenant ? Operation.CREATE : Operation.WRITE; | 75 | + checkEntity(tenant.getId(), tenant, Resource.TENANT); |
76 | 76 | ||
77 | - accessControlService.checkPermission(getCurrentUser(), Resource.TENANT, operation, | ||
78 | - tenant.getId(), tenant); | ||
79 | tenant = checkNotNull(tenantService.saveTenant(tenant)); | 77 | tenant = checkNotNull(tenantService.saveTenant(tenant)); |
80 | if (newTenant) { | 78 | if (newTenant) { |
81 | installScripts.createDefaultRuleChains(tenant.getId()); | 79 | installScripts.createDefaultRuleChains(tenant.getId()); |
@@ -132,17 +132,13 @@ public class UserController extends BaseController { | @@ -132,17 +132,13 @@ public class UserController extends BaseController { | ||
132 | @ResponseBody | 132 | @ResponseBody |
133 | public User saveUser(@RequestBody User user, | 133 | public User saveUser(@RequestBody User user, |
134 | @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, | 134 | @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, |
135 | - HttpServletRequest request) throws ThingsboardException { | 135 | + HttpServletRequest request) throws ThingsboardException { |
136 | try { | 136 | try { |
137 | - | ||
138 | if (getCurrentUser().getAuthority() == Authority.TENANT_ADMIN) { | 137 | if (getCurrentUser().getAuthority() == Authority.TENANT_ADMIN) { |
139 | user.setTenantId(getCurrentUser().getTenantId()); | 138 | user.setTenantId(getCurrentUser().getTenantId()); |
140 | } | 139 | } |
141 | 140 | ||
142 | - Operation operation = user.getId() == null ? Operation.CREATE : Operation.WRITE; | ||
143 | - | ||
144 | - accessControlService.checkPermission(getCurrentUser(), Resource.USER, operation, | ||
145 | - user.getId(), user); | 141 | + checkEntity(user.getId(), user, Resource.USER); |
146 | 142 | ||
147 | boolean sendEmail = user.getId() == null && sendActivationMail; | 143 | boolean sendEmail = user.getId() == null && sendActivationMail; |
148 | User savedUser = checkNotNull(userService.saveUser(user)); | 144 | User savedUser = checkNotNull(userService.saveUser(user)); |
@@ -250,7 +246,7 @@ public class UserController extends BaseController { | @@ -250,7 +246,7 @@ public class UserController extends BaseController { | ||
250 | } | 246 | } |
251 | 247 | ||
252 | @PreAuthorize("hasAuthority('SYS_ADMIN')") | 248 | @PreAuthorize("hasAuthority('SYS_ADMIN')") |
253 | - @RequestMapping(value = "/tenant/{tenantId}/users", params = { "limit" }, method = RequestMethod.GET) | 249 | + @RequestMapping(value = "/tenant/{tenantId}/users", params = {"limit"}, method = RequestMethod.GET) |
254 | @ResponseBody | 250 | @ResponseBody |
255 | public TextPageData<User> getTenantAdmins( | 251 | public TextPageData<User> getTenantAdmins( |
256 | @PathVariable("tenantId") String strTenantId, | 252 | @PathVariable("tenantId") String strTenantId, |
@@ -269,7 +265,7 @@ public class UserController extends BaseController { | @@ -269,7 +265,7 @@ public class UserController extends BaseController { | ||
269 | } | 265 | } |
270 | 266 | ||
271 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 267 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
272 | - @RequestMapping(value = "/customer/{customerId}/users", params = { "limit" }, method = RequestMethod.GET) | 268 | + @RequestMapping(value = "/customer/{customerId}/users", params = {"limit"}, method = RequestMethod.GET) |
273 | @ResponseBody | 269 | @ResponseBody |
274 | public TextPageData<User> getCustomerUsers( | 270 | public TextPageData<User> getCustomerUsers( |
275 | @PathVariable("customerId") String strCustomerId, | 271 | @PathVariable("customerId") String strCustomerId, |
@@ -66,10 +66,7 @@ public class WidgetTypeController extends BaseController { | @@ -66,10 +66,7 @@ public class WidgetTypeController extends BaseController { | ||
66 | widgetType.setTenantId(getCurrentUser().getTenantId()); | 66 | widgetType.setTenantId(getCurrentUser().getTenantId()); |
67 | } | 67 | } |
68 | 68 | ||
69 | - Operation operation = widgetType.getId() == null ? Operation.CREATE : Operation.WRITE; | ||
70 | - | ||
71 | - accessControlService.checkPermission(getCurrentUser(), Resource.WIDGET_TYPE, operation, | ||
72 | - widgetType.getId(), widgetType); | 69 | + checkEntity(widgetType.getId(), widgetType, Resource.WIDGET_TYPE); |
73 | 70 | ||
74 | return checkNotNull(widgetTypeService.saveWidgetType(widgetType)); | 71 | return checkNotNull(widgetTypeService.saveWidgetType(widgetType)); |
75 | } catch (Exception e) { | 72 | } catch (Exception e) { |
@@ -92,7 +89,7 @@ public class WidgetTypeController extends BaseController { | @@ -92,7 +89,7 @@ public class WidgetTypeController extends BaseController { | ||
92 | } | 89 | } |
93 | 90 | ||
94 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | 91 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
95 | - @RequestMapping(value = "/widgetTypes", params = { "isSystem", "bundleAlias"}, method = RequestMethod.GET) | 92 | + @RequestMapping(value = "/widgetTypes", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) |
96 | @ResponseBody | 93 | @ResponseBody |
97 | public List<WidgetType> getBundleWidgetTypes( | 94 | public List<WidgetType> getBundleWidgetTypes( |
98 | @RequestParam boolean isSystem, | 95 | @RequestParam boolean isSystem, |
@@ -111,7 +108,7 @@ public class WidgetTypeController extends BaseController { | @@ -111,7 +108,7 @@ public class WidgetTypeController extends BaseController { | ||
111 | } | 108 | } |
112 | 109 | ||
113 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 110 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
114 | - @RequestMapping(value = "/widgetType", params = { "isSystem", "bundleAlias", "alias" }, method = RequestMethod.GET) | 111 | + @RequestMapping(value = "/widgetType", params = {"isSystem", "bundleAlias", "alias"}, method = RequestMethod.GET) |
115 | @ResponseBody | 112 | @ResponseBody |
116 | public WidgetType getWidgetType( | 113 | public WidgetType getWidgetType( |
117 | @RequestParam boolean isSystem, | 114 | @RequestParam boolean isSystem, |
@@ -67,11 +67,7 @@ public class WidgetsBundleController extends BaseController { | @@ -67,11 +67,7 @@ public class WidgetsBundleController extends BaseController { | ||
67 | widgetsBundle.setTenantId(getCurrentUser().getTenantId()); | 67 | widgetsBundle.setTenantId(getCurrentUser().getTenantId()); |
68 | } | 68 | } |
69 | 69 | ||
70 | - Operation operation = widgetsBundle.getId() == null ? Operation.CREATE : Operation.WRITE; | ||
71 | - | ||
72 | - accessControlService.checkPermission(getCurrentUser(), Resource.WIDGETS_BUNDLE, operation, | ||
73 | - widgetsBundle.getId(), widgetsBundle); | ||
74 | - | 70 | + checkEntity(widgetsBundle.getId(), widgetsBundle, Resource.WIDGETS_BUNDLE); |
75 | return checkNotNull(widgetsBundleService.saveWidgetsBundle(widgetsBundle)); | 71 | return checkNotNull(widgetsBundleService.saveWidgetsBundle(widgetsBundle)); |
76 | } catch (Exception e) { | 72 | } catch (Exception e) { |
77 | throw handleException(e); | 73 | throw handleException(e); |
@@ -93,7 +89,7 @@ public class WidgetsBundleController extends BaseController { | @@ -93,7 +89,7 @@ public class WidgetsBundleController extends BaseController { | ||
93 | } | 89 | } |
94 | 90 | ||
95 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 91 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
96 | - @RequestMapping(value = "/widgetsBundles", params = { "limit" }, method = RequestMethod.GET) | 92 | + @RequestMapping(value = "/widgetsBundles", params = {"limit"}, method = RequestMethod.GET) |
97 | @ResponseBody | 93 | @ResponseBody |
98 | public TextPageData<WidgetsBundle> getWidgetsBundles( | 94 | public TextPageData<WidgetsBundle> getWidgetsBundles( |
99 | @RequestParam int limit, | 95 | @RequestParam int limit, |
@@ -133,13 +133,20 @@ public class ThingsboardInstallService { | @@ -133,13 +133,20 @@ public class ThingsboardInstallService { | ||
133 | databaseEntitiesUpgradeService.upgradeDatabase("2.4.2"); | 133 | databaseEntitiesUpgradeService.upgradeDatabase("2.4.2"); |
134 | 134 | ||
135 | case "2.4.3": | 135 | case "2.4.3": |
136 | - log.info("Upgrading ThingsBoard from version 2.4.3 to 2.5 ..."); | 136 | + log.info("Upgrading ThingsBoard from version 2.4.3 to 2.5.0 ..."); |
137 | 137 | ||
138 | if (databaseTsUpgradeService != null) { | 138 | if (databaseTsUpgradeService != null) { |
139 | databaseTsUpgradeService.upgradeDatabase("2.4.3"); | 139 | databaseTsUpgradeService.upgradeDatabase("2.4.3"); |
140 | } | 140 | } |
141 | databaseEntitiesUpgradeService.upgradeDatabase("2.4.3"); | 141 | databaseEntitiesUpgradeService.upgradeDatabase("2.4.3"); |
142 | 142 | ||
143 | + case "2.5.0": | ||
144 | + log.info("Upgrading ThingsBoard from version 2.5.0 to 2.5.1 ..."); | ||
145 | + if (databaseTsUpgradeService != null) { | ||
146 | + databaseTsUpgradeService.upgradeDatabase("2.5.0"); | ||
147 | + } | ||
148 | + | ||
149 | + | ||
143 | log.info("Updating system data..."); | 150 | log.info("Updating system data..."); |
144 | 151 | ||
145 | systemDataLoaderService.deleteSystemWidgetBundle("charts"); | 152 | systemDataLoaderService.deleteSystemWidgetBundle("charts"); |
@@ -34,6 +34,9 @@ public abstract class AbstractSqlTsDatabaseUpgradeService { | @@ -34,6 +34,9 @@ public abstract class AbstractSqlTsDatabaseUpgradeService { | ||
34 | protected static final String CALL_REGEX = "call "; | 34 | protected static final String CALL_REGEX = "call "; |
35 | protected static final String DROP_TABLE = "DROP TABLE "; | 35 | protected static final String DROP_TABLE = "DROP TABLE "; |
36 | protected static final String DROP_PROCEDURE_IF_EXISTS = "DROP PROCEDURE IF EXISTS "; | 36 | protected static final String DROP_PROCEDURE_IF_EXISTS = "DROP PROCEDURE IF EXISTS "; |
37 | + protected static final String TS_KV_SQL = "ts_kv.sql"; | ||
38 | + protected static final String PATH_TO_USERS_PUBLIC_FOLDER = "C:\\Users\\Public"; | ||
39 | + protected static final String THINGSBOARD_WINDOWS_UPGRADE_DIR = "THINGSBOARD_WINDOWS_UPGRADE_DIR"; | ||
37 | 40 | ||
38 | @Value("${spring.datasource.url}") | 41 | @Value("${spring.datasource.url}") |
39 | protected String dbUrl; | 42 | protected String dbUrl; |
@@ -48,6 +48,8 @@ public class CassandraTsDatabaseUpgradeService extends AbstractCassandraDatabase | @@ -48,6 +48,8 @@ public class CassandraTsDatabaseUpgradeService extends AbstractCassandraDatabase | ||
48 | } | 48 | } |
49 | log.info("Schema updated."); | 49 | log.info("Schema updated."); |
50 | break; | 50 | break; |
51 | + case "2.5.0": | ||
52 | + break; | ||
51 | default: | 53 | default: |
52 | throw new RuntimeException("Unable to upgrade Cassandra database, unsupported fromVersion: " + fromVersion); | 54 | throw new RuntimeException("Unable to upgrade Cassandra database, unsupported fromVersion: " + fromVersion); |
53 | } | 55 | } |
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
@@ -131,6 +131,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -131,6 +131,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
131 | node.put("username", ""); | 131 | node.put("username", ""); |
132 | node.put("password", ""); | 132 | node.put("password", ""); |
133 | node.put("tlsVersion", "TLSv1.2");//NOSONAR, key used to identify password field (not password value itself) | 133 | node.put("tlsVersion", "TLSv1.2");//NOSONAR, key used to identify password field (not password value itself) |
134 | + node.put("enableProxy", false); | ||
134 | mailSettings.setJsonValue(node); | 135 | mailSettings.setJsonValue(node); |
135 | adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, mailSettings); | 136 | adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, mailSettings); |
136 | } | 137 | } |
@@ -37,8 +37,6 @@ public class PsqlTsDatabaseSchemaService extends SqlAbstractDatabaseSchemaServic | @@ -37,8 +37,6 @@ public class PsqlTsDatabaseSchemaService extends SqlAbstractDatabaseSchemaServic | ||
37 | @Override | 37 | @Override |
38 | public void createDatabaseSchema() throws Exception { | 38 | public void createDatabaseSchema() throws Exception { |
39 | super.createDatabaseSchema(); | 39 | super.createDatabaseSchema(); |
40 | - if (partitionType.equals("INDEFINITE")) { | ||
41 | - executeQuery("CREATE TABLE ts_kv_indefinite PARTITION OF ts_kv DEFAULT;"); | ||
42 | - } | 40 | + executeQuery("CREATE TABLE IF NOT EXISTS ts_kv_indefinite PARTITION OF ts_kv DEFAULT;"); |
43 | } | 41 | } |
44 | } | 42 | } |
@@ -16,12 +16,17 @@ | @@ -16,12 +16,17 @@ | ||
16 | package org.thingsboard.server.service.install; | 16 | package org.thingsboard.server.service.install; |
17 | 17 | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | +import org.apache.commons.lang3.StringUtils; | ||
20 | +import org.apache.commons.lang3.SystemUtils; | ||
19 | import org.springframework.beans.factory.annotation.Value; | 21 | import org.springframework.beans.factory.annotation.Value; |
20 | import org.springframework.context.annotation.Profile; | 22 | import org.springframework.context.annotation.Profile; |
21 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
22 | import org.thingsboard.server.dao.util.PsqlDao; | 24 | import org.thingsboard.server.dao.util.PsqlDao; |
23 | import org.thingsboard.server.dao.util.SqlTsDao; | 25 | import org.thingsboard.server.dao.util.SqlTsDao; |
24 | 26 | ||
27 | +import java.io.File; | ||
28 | +import java.io.IOException; | ||
29 | +import java.nio.file.Files; | ||
25 | import java.nio.file.Path; | 30 | import java.nio.file.Path; |
26 | import java.nio.file.Paths; | 31 | import java.nio.file.Paths; |
27 | import java.sql.Connection; | 32 | import java.sql.Connection; |
@@ -37,6 +42,7 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | @@ -37,6 +42,7 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | ||
37 | @Value("${sql.postgres.ts_key_value_partitioning:MONTHS}") | 42 | @Value("${sql.postgres.ts_key_value_partitioning:MONTHS}") |
38 | private String partitionType; | 43 | private String partitionType; |
39 | 44 | ||
45 | + private static final String TS_KV_LATEST_SQL = "ts_kv_latest.sql"; | ||
40 | private static final String LOAD_FUNCTIONS_SQL = "schema_update_psql_ts.sql"; | 46 | private static final String LOAD_FUNCTIONS_SQL = "schema_update_psql_ts.sql"; |
41 | private static final String LOAD_TTL_FUNCTIONS_SQL = "schema_update_ttl.sql"; | 47 | private static final String LOAD_TTL_FUNCTIONS_SQL = "schema_update_ttl.sql"; |
42 | private static final String LOAD_DROP_PARTITIONS_FUNCTIONS_SQL = "schema_update_psql_drop_partitions.sql"; | 48 | private static final String LOAD_DROP_PARTITIONS_FUNCTIONS_SQL = "schema_update_psql_drop_partitions.sql"; |
@@ -49,15 +55,17 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | @@ -49,15 +55,17 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | ||
49 | private static final String CREATE_PARTITIONS = "create_partitions(IN partition_type varchar)"; | 55 | private static final String CREATE_PARTITIONS = "create_partitions(IN partition_type varchar)"; |
50 | private static final String CREATE_TS_KV_DICTIONARY_TABLE = "create_ts_kv_dictionary_table()"; | 56 | private static final String CREATE_TS_KV_DICTIONARY_TABLE = "create_ts_kv_dictionary_table()"; |
51 | private static final String INSERT_INTO_DICTIONARY = "insert_into_dictionary()"; | 57 | private static final String INSERT_INTO_DICTIONARY = "insert_into_dictionary()"; |
52 | - private static final String INSERT_INTO_TS_KV = "insert_into_ts_kv()"; | ||
53 | - private static final String INSERT_INTO_TS_KV_LATEST = "insert_into_ts_kv_latest()"; | 58 | + private static final String INSERT_INTO_TS_KV = "insert_into_ts_kv(IN path_to_file varchar)"; |
59 | + private static final String INSERT_INTO_TS_KV_LATEST = "insert_into_ts_kv_latest(IN path_to_file varchar)"; | ||
60 | + private static final String INSERT_INTO_TS_KV_CURSOR = "insert_into_ts_kv_cursor()"; | ||
61 | + private static final String INSERT_INTO_TS_KV_LATEST_CURSOR = "insert_into_ts_kv_latest_cursor()"; | ||
54 | 62 | ||
55 | private static final String CALL_CREATE_PARTITION_TS_KV_TABLE = CALL_REGEX + CREATE_PARTITION_TS_KV_TABLE; | 63 | private static final String CALL_CREATE_PARTITION_TS_KV_TABLE = CALL_REGEX + CREATE_PARTITION_TS_KV_TABLE; |
56 | private static final String CALL_CREATE_NEW_TS_KV_LATEST_TABLE = CALL_REGEX + CREATE_NEW_TS_KV_LATEST_TABLE; | 64 | private static final String CALL_CREATE_NEW_TS_KV_LATEST_TABLE = CALL_REGEX + CREATE_NEW_TS_KV_LATEST_TABLE; |
57 | private static final String CALL_CREATE_TS_KV_DICTIONARY_TABLE = CALL_REGEX + CREATE_TS_KV_DICTIONARY_TABLE; | 65 | private static final String CALL_CREATE_TS_KV_DICTIONARY_TABLE = CALL_REGEX + CREATE_TS_KV_DICTIONARY_TABLE; |
58 | private static final String CALL_INSERT_INTO_DICTIONARY = CALL_REGEX + INSERT_INTO_DICTIONARY; | 66 | private static final String CALL_INSERT_INTO_DICTIONARY = CALL_REGEX + INSERT_INTO_DICTIONARY; |
59 | - private static final String CALL_INSERT_INTO_TS_KV = CALL_REGEX + INSERT_INTO_TS_KV; | ||
60 | - private static final String CALL_INSERT_INTO_TS_KV_LATEST = CALL_REGEX + INSERT_INTO_TS_KV_LATEST; | 67 | + private static final String CALL_INSERT_INTO_TS_KV_CURSOR = CALL_REGEX + INSERT_INTO_TS_KV_CURSOR; |
68 | + private static final String CALL_INSERT_INTO_TS_KV_LATEST_CURSOR = CALL_REGEX + INSERT_INTO_TS_KV_LATEST_CURSOR; | ||
61 | 69 | ||
62 | private static final String DROP_TABLE_TS_KV_OLD = DROP_TABLE + TS_KV_OLD; | 70 | private static final String DROP_TABLE_TS_KV_OLD = DROP_TABLE + TS_KV_OLD; |
63 | private static final String DROP_TABLE_TS_KV_LATEST_OLD = DROP_TABLE + TS_KV_LATEST_OLD; | 71 | private static final String DROP_TABLE_TS_KV_LATEST_OLD = DROP_TABLE + TS_KV_LATEST_OLD; |
@@ -69,6 +77,8 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | @@ -69,6 +77,8 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | ||
69 | private static final String DROP_PROCEDURE_INSERT_INTO_DICTIONARY = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_DICTIONARY; | 77 | private static final String DROP_PROCEDURE_INSERT_INTO_DICTIONARY = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_DICTIONARY; |
70 | private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV; | 78 | private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV; |
71 | private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV_LATEST; | 79 | private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV_LATEST; |
80 | + private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV_CURSOR = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV_CURSOR; | ||
81 | + private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST_CURSOR = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV_LATEST_CURSOR; | ||
72 | private static final String DROP_FUNCTION_GET_PARTITION_DATA = "DROP FUNCTION IF EXISTS get_partitions_data;"; | 82 | private static final String DROP_FUNCTION_GET_PARTITION_DATA = "DROP FUNCTION IF EXISTS get_partitions_data;"; |
73 | 83 | ||
74 | @Override | 84 | @Override |
@@ -89,14 +99,63 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | @@ -89,14 +99,63 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | ||
89 | executeQuery(conn, CALL_CREATE_PARTITION_TS_KV_TABLE); | 99 | executeQuery(conn, CALL_CREATE_PARTITION_TS_KV_TABLE); |
90 | if (!partitionType.equals("INDEFINITE")) { | 100 | if (!partitionType.equals("INDEFINITE")) { |
91 | executeQuery(conn, "call create_partitions('" + partitionType + "')"); | 101 | executeQuery(conn, "call create_partitions('" + partitionType + "')"); |
92 | - } else { | ||
93 | - executeQuery(conn, "CREATE TABLE IF NOT EXISTS ts_kv_indefinite PARTITION OF ts_kv DEFAULT;"); | ||
94 | } | 102 | } |
95 | executeQuery(conn, CALL_CREATE_TS_KV_DICTIONARY_TABLE); | 103 | executeQuery(conn, CALL_CREATE_TS_KV_DICTIONARY_TABLE); |
96 | executeQuery(conn, CALL_INSERT_INTO_DICTIONARY); | 104 | executeQuery(conn, CALL_INSERT_INTO_DICTIONARY); |
97 | - executeQuery(conn, CALL_INSERT_INTO_TS_KV); | ||
98 | - executeQuery(conn, CALL_CREATE_NEW_TS_KV_LATEST_TABLE); | ||
99 | - executeQuery(conn, CALL_INSERT_INTO_TS_KV_LATEST); | 105 | + |
106 | + Path pathToTempTsKvFile = null; | ||
107 | + Path pathToTempTsKvLatestFile = null; | ||
108 | + if (SystemUtils.IS_OS_WINDOWS) { | ||
109 | + log.info("Lookup for environment variable: {} ...", THINGSBOARD_WINDOWS_UPGRADE_DIR); | ||
110 | + Path pathToDir; | ||
111 | + String thingsboardWindowsUpgradeDir = System.getenv("THINGSBOARD_WINDOWS_UPGRADE_DIR"); | ||
112 | + if (StringUtils.isNotEmpty(thingsboardWindowsUpgradeDir)) { | ||
113 | + log.info("Environment variable: {} was found!", THINGSBOARD_WINDOWS_UPGRADE_DIR); | ||
114 | + pathToDir = Paths.get(thingsboardWindowsUpgradeDir); | ||
115 | + } else { | ||
116 | + log.info("Failed to lookup environment variable: {}", THINGSBOARD_WINDOWS_UPGRADE_DIR); | ||
117 | + pathToDir = Paths.get(PATH_TO_USERS_PUBLIC_FOLDER); | ||
118 | + } | ||
119 | + log.info("Directory: {} will be used for creation temporary upgrade files!", pathToDir); | ||
120 | + try { | ||
121 | + Path tsKvFile = Files.createTempFile(pathToDir, "ts_kv", ".sql"); | ||
122 | + Path tsKvLatestFile = Files.createTempFile(pathToDir, "ts_kv_latest", ".sql"); | ||
123 | + pathToTempTsKvFile = tsKvFile.toAbsolutePath(); | ||
124 | + pathToTempTsKvLatestFile = tsKvLatestFile.toAbsolutePath(); | ||
125 | + try { | ||
126 | + copyTimeseries(conn, pathToTempTsKvFile, pathToTempTsKvLatestFile); | ||
127 | + } catch (Exception e) { | ||
128 | + insertTimeseries(conn); | ||
129 | + } | ||
130 | + } catch (IOException | SecurityException e) { | ||
131 | + log.warn("Failed to create time-series upgrade files due to: {}", e.getMessage()); | ||
132 | + insertTimeseries(conn); | ||
133 | + } | ||
134 | + } else { | ||
135 | + try { | ||
136 | + Path tempDirPath = Files.createTempDirectory("ts_kv"); | ||
137 | + File tempDirAsFile = tempDirPath.toFile(); | ||
138 | + boolean writable = tempDirAsFile.setWritable(true, false); | ||
139 | + boolean readable = tempDirAsFile.setReadable(true, false); | ||
140 | + boolean executable = tempDirAsFile.setExecutable(true, false); | ||
141 | + pathToTempTsKvFile = tempDirPath.resolve(TS_KV_SQL).toAbsolutePath(); | ||
142 | + pathToTempTsKvLatestFile = tempDirPath.resolve(TS_KV_LATEST_SQL).toAbsolutePath(); | ||
143 | + try { | ||
144 | + if (writable && readable && executable) { | ||
145 | + copyTimeseries(conn, pathToTempTsKvFile, pathToTempTsKvLatestFile); | ||
146 | + } else { | ||
147 | + throw new RuntimeException("Failed to grant write permissions for the: " + tempDirPath + "folder!"); | ||
148 | + } | ||
149 | + } catch (Exception e) { | ||
150 | + insertTimeseries(conn); | ||
151 | + } | ||
152 | + } catch (IOException | SecurityException e) { | ||
153 | + log.warn("Failed to create time-series upgrade files due to: {}", e.getMessage()); | ||
154 | + insertTimeseries(conn); | ||
155 | + } | ||
156 | + } | ||
157 | + | ||
158 | + removeUpgradeFiles(pathToTempTsKvFile, pathToTempTsKvLatestFile); | ||
100 | 159 | ||
101 | executeQuery(conn, DROP_TABLE_TS_KV_OLD); | 160 | executeQuery(conn, DROP_TABLE_TS_KV_OLD); |
102 | executeQuery(conn, DROP_TABLE_TS_KV_LATEST_OLD); | 161 | executeQuery(conn, DROP_TABLE_TS_KV_LATEST_OLD); |
@@ -108,6 +167,8 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | @@ -108,6 +167,8 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | ||
108 | executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV); | 167 | executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV); |
109 | executeQuery(conn, DROP_PROCEDURE_CREATE_NEW_TS_KV_LATEST_TABLE); | 168 | executeQuery(conn, DROP_PROCEDURE_CREATE_NEW_TS_KV_LATEST_TABLE); |
110 | executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST); | 169 | executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST); |
170 | + executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV_CURSOR); | ||
171 | + executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST_CURSOR); | ||
111 | executeQuery(conn, DROP_FUNCTION_GET_PARTITION_DATA); | 172 | executeQuery(conn, DROP_FUNCTION_GET_PARTITION_DATA); |
112 | 173 | ||
113 | executeQuery(conn, "ALTER TABLE ts_kv ADD COLUMN IF NOT EXISTS json_v json;"); | 174 | executeQuery(conn, "ALTER TABLE ts_kv ADD COLUMN IF NOT EXISTS json_v json;"); |
@@ -128,11 +189,46 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | @@ -128,11 +189,46 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe | ||
128 | } | 189 | } |
129 | } | 190 | } |
130 | break; | 191 | break; |
192 | + case "2.5.0": | ||
193 | + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { | ||
194 | + executeQuery(conn, "CREATE TABLE IF NOT EXISTS ts_kv_indefinite PARTITION OF ts_kv DEFAULT;"); | ||
195 | + executeQuery(conn, "UPDATE tb_schema_settings SET schema_version = 2005001"); | ||
196 | + } | ||
197 | + break; | ||
131 | default: | 198 | default: |
132 | throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); | 199 | throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); |
133 | } | 200 | } |
134 | } | 201 | } |
135 | 202 | ||
203 | + private void removeUpgradeFiles(Path pathToTempTsKvFile, Path pathToTempTsKvLatestFile) { | ||
204 | + if (pathToTempTsKvFile != null && pathToTempTsKvFile.toFile().exists()) { | ||
205 | + boolean deleteTsKvFile = pathToTempTsKvFile.toFile().delete(); | ||
206 | + if (deleteTsKvFile) { | ||
207 | + log.info("Successfully deleted the temp file for ts_kv table upgrade!"); | ||
208 | + } | ||
209 | + } | ||
210 | + if (pathToTempTsKvLatestFile != null && pathToTempTsKvLatestFile.toFile().exists()) { | ||
211 | + boolean deleteTsKvLatestFile = pathToTempTsKvLatestFile.toFile().delete(); | ||
212 | + if (deleteTsKvLatestFile) { | ||
213 | + log.info("Successfully deleted the temp file for ts_kv_latest table upgrade!"); | ||
214 | + } | ||
215 | + } | ||
216 | + } | ||
217 | + | ||
218 | + private void copyTimeseries(Connection conn, Path pathToTempTsKvFile, Path pathToTempTsKvLatestFile) { | ||
219 | + executeQuery(conn, "call insert_into_ts_kv('" + pathToTempTsKvFile + "')"); | ||
220 | + executeQuery(conn, CALL_CREATE_NEW_TS_KV_LATEST_TABLE); | ||
221 | + executeQuery(conn, "call insert_into_ts_kv_latest('" + pathToTempTsKvLatestFile + "')"); | ||
222 | + } | ||
223 | + | ||
224 | + private void insertTimeseries(Connection conn) { | ||
225 | + log.warn("Upgrade script failed using the copy to/from files strategy!" + | ||
226 | + " Trying to perfrom the upgrade using Inserts strategy ..."); | ||
227 | + executeQuery(conn, CALL_INSERT_INTO_TS_KV_CURSOR); | ||
228 | + executeQuery(conn, CALL_CREATE_NEW_TS_KV_LATEST_TABLE); | ||
229 | + executeQuery(conn, CALL_INSERT_INTO_TS_KV_LATEST_CURSOR); | ||
230 | + } | ||
231 | + | ||
136 | @Override | 232 | @Override |
137 | protected void loadSql(Connection conn, String fileName) { | 233 | protected void loadSql(Connection conn, String fileName) { |
138 | Path schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.4.3", fileName); | 234 | Path schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.4.3", fileName); |
@@ -16,6 +16,8 @@ | @@ -16,6 +16,8 @@ | ||
16 | package org.thingsboard.server.service.install; | 16 | package org.thingsboard.server.service.install; |
17 | 17 | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | +import org.apache.commons.lang3.StringUtils; | ||
20 | +import org.apache.commons.lang3.SystemUtils; | ||
19 | import org.springframework.beans.factory.annotation.Autowired; | 21 | import org.springframework.beans.factory.annotation.Autowired; |
20 | import org.springframework.beans.factory.annotation.Value; | 22 | import org.springframework.beans.factory.annotation.Value; |
21 | import org.springframework.context.annotation.Profile; | 23 | import org.springframework.context.annotation.Profile; |
@@ -23,6 +25,9 @@ import org.springframework.stereotype.Service; | @@ -23,6 +25,9 @@ import org.springframework.stereotype.Service; | ||
23 | import org.thingsboard.server.dao.util.PsqlDao; | 25 | import org.thingsboard.server.dao.util.PsqlDao; |
24 | import org.thingsboard.server.dao.util.TimescaleDBTsDao; | 26 | import org.thingsboard.server.dao.util.TimescaleDBTsDao; |
25 | 27 | ||
28 | +import java.io.File; | ||
29 | +import java.io.IOException; | ||
30 | +import java.nio.file.Files; | ||
26 | import java.nio.file.Path; | 31 | import java.nio.file.Path; |
27 | import java.nio.file.Paths; | 32 | import java.nio.file.Paths; |
28 | import java.sql.Connection; | 33 | import java.sql.Connection; |
@@ -47,15 +52,16 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr | @@ -47,15 +52,16 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr | ||
47 | private static final String CREATE_NEW_TS_KV_TABLE = "create_new_ts_kv_table()"; | 52 | private static final String CREATE_NEW_TS_KV_TABLE = "create_new_ts_kv_table()"; |
48 | private static final String CREATE_TS_KV_DICTIONARY_TABLE = "create_ts_kv_dictionary_table()"; | 53 | private static final String CREATE_TS_KV_DICTIONARY_TABLE = "create_ts_kv_dictionary_table()"; |
49 | private static final String INSERT_INTO_DICTIONARY = "insert_into_dictionary()"; | 54 | private static final String INSERT_INTO_DICTIONARY = "insert_into_dictionary()"; |
50 | - private static final String INSERT_INTO_TS_KV = "insert_into_ts_kv()"; | 55 | + private static final String INSERT_INTO_TS_KV = "insert_into_ts_kv(IN path_to_file varchar)"; |
56 | + private static final String INSERT_INTO_TS_KV_CURSOR = "insert_into_ts_kv_cursor()"; | ||
51 | private static final String INSERT_INTO_TS_KV_LATEST = "insert_into_ts_kv_latest()"; | 57 | private static final String INSERT_INTO_TS_KV_LATEST = "insert_into_ts_kv_latest()"; |
52 | 58 | ||
53 | private static final String CALL_CREATE_TS_KV_LATEST_TABLE = CALL_REGEX + CREATE_TS_KV_LATEST_TABLE; | 59 | private static final String CALL_CREATE_TS_KV_LATEST_TABLE = CALL_REGEX + CREATE_TS_KV_LATEST_TABLE; |
54 | private static final String CALL_CREATE_NEW_TENANT_TS_KV_TABLE = CALL_REGEX + CREATE_NEW_TS_KV_TABLE; | 60 | private static final String CALL_CREATE_NEW_TENANT_TS_KV_TABLE = CALL_REGEX + CREATE_NEW_TS_KV_TABLE; |
55 | private static final String CALL_CREATE_TS_KV_DICTIONARY_TABLE = CALL_REGEX + CREATE_TS_KV_DICTIONARY_TABLE; | 61 | private static final String CALL_CREATE_TS_KV_DICTIONARY_TABLE = CALL_REGEX + CREATE_TS_KV_DICTIONARY_TABLE; |
56 | private static final String CALL_INSERT_INTO_DICTIONARY = CALL_REGEX + INSERT_INTO_DICTIONARY; | 62 | private static final String CALL_INSERT_INTO_DICTIONARY = CALL_REGEX + INSERT_INTO_DICTIONARY; |
57 | - private static final String CALL_INSERT_INTO_TS_KV = CALL_REGEX + INSERT_INTO_TS_KV; | ||
58 | private static final String CALL_INSERT_INTO_TS_KV_LATEST = CALL_REGEX + INSERT_INTO_TS_KV_LATEST; | 63 | private static final String CALL_INSERT_INTO_TS_KV_LATEST = CALL_REGEX + INSERT_INTO_TS_KV_LATEST; |
64 | + private static final String CALL_INSERT_INTO_TS_KV_CURSOR = CALL_REGEX + INSERT_INTO_TS_KV_CURSOR; | ||
59 | 65 | ||
60 | private static final String DROP_OLD_TENANT_TS_KV_TABLE = DROP_TABLE + TENANT_TS_KV_OLD_TABLE; | 66 | private static final String DROP_OLD_TENANT_TS_KV_TABLE = DROP_TABLE + TENANT_TS_KV_OLD_TABLE; |
61 | 67 | ||
@@ -63,7 +69,8 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr | @@ -63,7 +69,8 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr | ||
63 | private static final String DROP_PROCEDURE_CREATE_TENANT_TS_KV_TABLE_COPY = DROP_PROCEDURE_IF_EXISTS + CREATE_NEW_TS_KV_TABLE; | 69 | private static final String DROP_PROCEDURE_CREATE_TENANT_TS_KV_TABLE_COPY = DROP_PROCEDURE_IF_EXISTS + CREATE_NEW_TS_KV_TABLE; |
64 | private static final String DROP_PROCEDURE_CREATE_TS_KV_DICTIONARY_TABLE = DROP_PROCEDURE_IF_EXISTS + CREATE_TS_KV_DICTIONARY_TABLE; | 70 | private static final String DROP_PROCEDURE_CREATE_TS_KV_DICTIONARY_TABLE = DROP_PROCEDURE_IF_EXISTS + CREATE_TS_KV_DICTIONARY_TABLE; |
65 | private static final String DROP_PROCEDURE_INSERT_INTO_DICTIONARY = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_DICTIONARY; | 71 | private static final String DROP_PROCEDURE_INSERT_INTO_DICTIONARY = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_DICTIONARY; |
66 | - private static final String DROP_PROCEDURE_INSERT_INTO_TENANT_TS_KV = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV; | 72 | + private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV; |
73 | + private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV_CURSOR = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV_CURSOR; | ||
67 | private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV_LATEST; | 74 | private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV_LATEST; |
68 | 75 | ||
69 | @Autowired | 76 | @Autowired |
@@ -91,7 +98,56 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr | @@ -91,7 +98,56 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr | ||
91 | 98 | ||
92 | executeQuery(conn, CALL_CREATE_TS_KV_DICTIONARY_TABLE); | 99 | executeQuery(conn, CALL_CREATE_TS_KV_DICTIONARY_TABLE); |
93 | executeQuery(conn, CALL_INSERT_INTO_DICTIONARY); | 100 | executeQuery(conn, CALL_INSERT_INTO_DICTIONARY); |
94 | - executeQuery(conn, CALL_INSERT_INTO_TS_KV); | 101 | + |
102 | + Path pathToTempTsKvFile = null; | ||
103 | + if (SystemUtils.IS_OS_WINDOWS) { | ||
104 | + Path pathToDir; | ||
105 | + log.info("Lookup for environment variable: {} ...", THINGSBOARD_WINDOWS_UPGRADE_DIR); | ||
106 | + String thingsboardWindowsUpgradeDir = System.getenv(THINGSBOARD_WINDOWS_UPGRADE_DIR); | ||
107 | + if (StringUtils.isNotEmpty(thingsboardWindowsUpgradeDir)) { | ||
108 | + log.info("Environment variable: {} was found!", THINGSBOARD_WINDOWS_UPGRADE_DIR); | ||
109 | + pathToDir = Paths.get(thingsboardWindowsUpgradeDir); | ||
110 | + } else { | ||
111 | + log.info("Failed to lookup environment variable: {}", THINGSBOARD_WINDOWS_UPGRADE_DIR); | ||
112 | + pathToDir = Paths.get(PATH_TO_USERS_PUBLIC_FOLDER); | ||
113 | + } | ||
114 | + log.info("Directory: {} will be used for creation temporary upgrade file!", pathToDir); | ||
115 | + try { | ||
116 | + Path tsKvFile = Files.createTempFile(pathToDir, "ts_kv", ".sql"); | ||
117 | + pathToTempTsKvFile = tsKvFile.toAbsolutePath(); | ||
118 | + try { | ||
119 | + executeQuery(conn, "call insert_into_ts_kv('" + pathToTempTsKvFile + "')"); | ||
120 | + } catch (Exception e) { | ||
121 | + insertTimeseries(conn); | ||
122 | + } | ||
123 | + } catch (IOException | SecurityException e) { | ||
124 | + log.warn("Failed to create time-series upgrade files due to: {}", e.getMessage()); | ||
125 | + insertTimeseries(conn); | ||
126 | + } | ||
127 | + } else { | ||
128 | + try { | ||
129 | + Path tempDirPath = Files.createTempDirectory("ts_kv"); | ||
130 | + File tempDirAsFile = tempDirPath.toFile(); | ||
131 | + boolean writable = tempDirAsFile.setWritable(true, false); | ||
132 | + boolean readable = tempDirAsFile.setReadable(true, false); | ||
133 | + boolean executable = tempDirAsFile.setExecutable(true, false); | ||
134 | + pathToTempTsKvFile = tempDirPath.resolve(TS_KV_SQL).toAbsolutePath(); | ||
135 | + try { | ||
136 | + if (writable && readable && executable) { | ||
137 | + executeQuery(conn, "call insert_into_ts_kv('" + pathToTempTsKvFile + "')"); | ||
138 | + } else { | ||
139 | + throw new RuntimeException("Failed to grant write permissions for the: " + tempDirPath + "folder!"); | ||
140 | + } | ||
141 | + } catch (Exception e) { | ||
142 | + insertTimeseries(conn); | ||
143 | + } | ||
144 | + } catch (IOException | SecurityException e) { | ||
145 | + log.warn("Failed to create time-series upgrade files due to: {}", e.getMessage()); | ||
146 | + insertTimeseries(conn); | ||
147 | + } | ||
148 | + } | ||
149 | + removeUpgradeFile(pathToTempTsKvFile); | ||
150 | + | ||
95 | executeQuery(conn, CALL_INSERT_INTO_TS_KV_LATEST); | 151 | executeQuery(conn, CALL_INSERT_INTO_TS_KV_LATEST); |
96 | 152 | ||
97 | executeQuery(conn, DROP_OLD_TENANT_TS_KV_TABLE); | 153 | executeQuery(conn, DROP_OLD_TENANT_TS_KV_TABLE); |
@@ -100,7 +156,8 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr | @@ -100,7 +156,8 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr | ||
100 | executeQuery(conn, DROP_PROCEDURE_CREATE_TENANT_TS_KV_TABLE_COPY); | 156 | executeQuery(conn, DROP_PROCEDURE_CREATE_TENANT_TS_KV_TABLE_COPY); |
101 | executeQuery(conn, DROP_PROCEDURE_CREATE_TS_KV_DICTIONARY_TABLE); | 157 | executeQuery(conn, DROP_PROCEDURE_CREATE_TS_KV_DICTIONARY_TABLE); |
102 | executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_DICTIONARY); | 158 | executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_DICTIONARY); |
103 | - executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TENANT_TS_KV); | 159 | + executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV); |
160 | + executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV_CURSOR); | ||
104 | executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST); | 161 | executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST); |
105 | 162 | ||
106 | executeQuery(conn, "ALTER TABLE ts_kv ADD COLUMN IF NOT EXISTS json_v json;"); | 163 | executeQuery(conn, "ALTER TABLE ts_kv ADD COLUMN IF NOT EXISTS json_v json;"); |
@@ -115,11 +172,31 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr | @@ -115,11 +172,31 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr | ||
115 | } | 172 | } |
116 | } | 173 | } |
117 | break; | 174 | break; |
175 | + case "2.5.0": | ||
176 | + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { | ||
177 | + executeQuery(conn, "UPDATE tb_schema_settings SET schema_version = 2005001"); | ||
178 | + } | ||
179 | + break; | ||
118 | default: | 180 | default: |
119 | throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); | 181 | throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); |
120 | } | 182 | } |
121 | } | 183 | } |
122 | 184 | ||
185 | + private void insertTimeseries(Connection conn) { | ||
186 | + log.warn("Upgrade script failed using the copy to/from files strategy!" + | ||
187 | + " Trying to perfrom the upgrade using Inserts strategy ..."); | ||
188 | + executeQuery(conn, CALL_INSERT_INTO_TS_KV_CURSOR); | ||
189 | + } | ||
190 | + | ||
191 | + private void removeUpgradeFile(Path pathToTempTsKvFile) { | ||
192 | + if (pathToTempTsKvFile != null && pathToTempTsKvFile.toFile().exists()) { | ||
193 | + boolean deleteTsKvFile = pathToTempTsKvFile.toFile().delete(); | ||
194 | + if (deleteTsKvFile) { | ||
195 | + log.info("Successfully deleted the temp file for ts_kv table upgrade!"); | ||
196 | + } | ||
197 | + } | ||
198 | + } | ||
199 | + | ||
123 | @Override | 200 | @Override |
124 | protected void loadSql(Connection conn, String fileName) { | 201 | protected void loadSql(Connection conn, String fileName) { |
125 | Path schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.4.3", fileName); | 202 | Path schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "2.4.3", fileName); |
@@ -115,6 +115,21 @@ public class DefaultMailService implements MailService { | @@ -115,6 +115,21 @@ public class DefaultMailService implements MailService { | ||
115 | if (enableTls && jsonConfig.has("tlsVersion") && StringUtils.isNoneEmpty(jsonConfig.get("tlsVersion").asText())) { | 115 | if (enableTls && jsonConfig.has("tlsVersion") && StringUtils.isNoneEmpty(jsonConfig.get("tlsVersion").asText())) { |
116 | javaMailProperties.put(MAIL_PROP + protocol + ".ssl.protocols", jsonConfig.get("tlsVersion").asText()); | 116 | javaMailProperties.put(MAIL_PROP + protocol + ".ssl.protocols", jsonConfig.get("tlsVersion").asText()); |
117 | } | 117 | } |
118 | + | ||
119 | + boolean enableProxy = jsonConfig.has("enableProxy") && jsonConfig.get("enableProxy").asBoolean(); | ||
120 | + | ||
121 | + if (enableProxy) { | ||
122 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.host", jsonConfig.get("proxyHost").asText()); | ||
123 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.port", jsonConfig.get("proxyPort").asText()); | ||
124 | + String proxyUser = jsonConfig.get("proxyUser").asText(); | ||
125 | + if (StringUtils.isNoneEmpty(proxyUser)) { | ||
126 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.user", proxyUser); | ||
127 | + } | ||
128 | + String proxyPassword = jsonConfig.get("proxyPassword").asText(); | ||
129 | + if (StringUtils.isNoneEmpty(proxyPassword)) { | ||
130 | + javaMailProperties.put(MAIL_PROP + protocol + ".proxy.password", proxyPassword); | ||
131 | + } | ||
132 | + } | ||
118 | return javaMailProperties; | 133 | return javaMailProperties; |
119 | } | 134 | } |
120 | 135 |
@@ -46,6 +46,9 @@ import java.util.concurrent.atomic.AtomicInteger; | @@ -46,6 +46,9 @@ import java.util.concurrent.atomic.AtomicInteger; | ||
46 | @Service | 46 | @Service |
47 | public class RemoteJsInvokeService extends AbstractJsInvokeService { | 47 | public class RemoteJsInvokeService extends AbstractJsInvokeService { |
48 | 48 | ||
49 | + @Value("${queue.js.max_eval_requests_timeout}") | ||
50 | + private long maxEvalRequestsTimeout; | ||
51 | + | ||
49 | @Value("${queue.js.max_requests_timeout}") | 52 | @Value("${queue.js.max_requests_timeout}") |
50 | private long maxRequestsTimeout; | 53 | private long maxRequestsTimeout; |
51 | 54 | ||
@@ -59,22 +62,22 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | @@ -59,22 +62,22 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | ||
59 | @Value("${js.remote.stats.enabled:false}") | 62 | @Value("${js.remote.stats.enabled:false}") |
60 | private boolean statsEnabled; | 63 | private boolean statsEnabled; |
61 | 64 | ||
62 | - private final AtomicInteger kafkaPushedMsgs = new AtomicInteger(0); | ||
63 | - private final AtomicInteger kafkaInvokeMsgs = new AtomicInteger(0); | ||
64 | - private final AtomicInteger kafkaEvalMsgs = new AtomicInteger(0); | ||
65 | - private final AtomicInteger kafkaFailedMsgs = new AtomicInteger(0); | ||
66 | - private final AtomicInteger kafkaTimeoutMsgs = new AtomicInteger(0); | 65 | + private final AtomicInteger queuePushedMsgs = new AtomicInteger(0); |
66 | + private final AtomicInteger queueInvokeMsgs = new AtomicInteger(0); | ||
67 | + private final AtomicInteger queueEvalMsgs = new AtomicInteger(0); | ||
68 | + private final AtomicInteger queueFailedMsgs = new AtomicInteger(0); | ||
69 | + private final AtomicInteger queueTimeoutMsgs = new AtomicInteger(0); | ||
67 | 70 | ||
68 | @Scheduled(fixedDelayString = "${js.remote.stats.print_interval_ms}") | 71 | @Scheduled(fixedDelayString = "${js.remote.stats.print_interval_ms}") |
69 | public void printStats() { | 72 | public void printStats() { |
70 | if (statsEnabled) { | 73 | if (statsEnabled) { |
71 | - int pushedMsgs = kafkaPushedMsgs.getAndSet(0); | ||
72 | - int invokeMsgs = kafkaInvokeMsgs.getAndSet(0); | ||
73 | - int evalMsgs = kafkaEvalMsgs.getAndSet(0); | ||
74 | - int failed = kafkaFailedMsgs.getAndSet(0); | ||
75 | - int timedOut = kafkaTimeoutMsgs.getAndSet(0); | 74 | + int pushedMsgs = queuePushedMsgs.getAndSet(0); |
75 | + int invokeMsgs = queueInvokeMsgs.getAndSet(0); | ||
76 | + int evalMsgs = queueEvalMsgs.getAndSet(0); | ||
77 | + int failed = queueFailedMsgs.getAndSet(0); | ||
78 | + int timedOut = queueTimeoutMsgs.getAndSet(0); | ||
76 | if (pushedMsgs > 0 || invokeMsgs > 0 || evalMsgs > 0 || failed > 0 || timedOut > 0) { | 79 | if (pushedMsgs > 0 || invokeMsgs > 0 || evalMsgs > 0 || failed > 0 || timedOut > 0) { |
77 | - log.info("Kafka JS Invoke Stats: pushed [{}] received [{}] invoke [{}] eval [{}] failed [{}] timedOut [{}]", | 80 | + log.info("Queue JS Invoke Stats: pushed [{}] received [{}] invoke [{}] eval [{}] failed [{}] timedOut [{}]", |
78 | pushedMsgs, invokeMsgs + evalMsgs, invokeMsgs, evalMsgs, failed, timedOut); | 81 | pushedMsgs, invokeMsgs + evalMsgs, invokeMsgs, evalMsgs, failed, timedOut); |
79 | } | 82 | } |
80 | } | 83 | } |
@@ -113,22 +116,22 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | @@ -113,22 +116,22 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | ||
113 | 116 | ||
114 | log.trace("Post compile request for scriptId [{}]", scriptId); | 117 | log.trace("Post compile request for scriptId [{}]", scriptId); |
115 | ListenableFuture<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> future = requestTemplate.send(new TbProtoJsQueueMsg<>(UUID.randomUUID(), jsRequestWrapper)); | 118 | ListenableFuture<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>> future = requestTemplate.send(new TbProtoJsQueueMsg<>(UUID.randomUUID(), jsRequestWrapper)); |
116 | - if (maxRequestsTimeout > 0) { | ||
117 | - future = Futures.withTimeout(future, maxRequestsTimeout, TimeUnit.MILLISECONDS, timeoutExecutorService); | 119 | + if (maxEvalRequestsTimeout > 0) { |
120 | + future = Futures.withTimeout(future, maxEvalRequestsTimeout, TimeUnit.MILLISECONDS, timeoutExecutorService); | ||
118 | } | 121 | } |
119 | - kafkaPushedMsgs.incrementAndGet(); | 122 | + queuePushedMsgs.incrementAndGet(); |
120 | Futures.addCallback(future, new FutureCallback<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>>() { | 123 | Futures.addCallback(future, new FutureCallback<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>>() { |
121 | @Override | 124 | @Override |
122 | public void onSuccess(@Nullable TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse> result) { | 125 | public void onSuccess(@Nullable TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse> result) { |
123 | - kafkaEvalMsgs.incrementAndGet(); | 126 | + queueEvalMsgs.incrementAndGet(); |
124 | } | 127 | } |
125 | 128 | ||
126 | @Override | 129 | @Override |
127 | public void onFailure(Throwable t) { | 130 | public void onFailure(Throwable t) { |
128 | if (t instanceof TimeoutException || (t.getCause() != null && t.getCause() instanceof TimeoutException)) { | 131 | if (t instanceof TimeoutException || (t.getCause() != null && t.getCause() instanceof TimeoutException)) { |
129 | - kafkaTimeoutMsgs.incrementAndGet(); | 132 | + queueTimeoutMsgs.incrementAndGet(); |
130 | } | 133 | } |
131 | - kafkaFailedMsgs.incrementAndGet(); | 134 | + queueFailedMsgs.incrementAndGet(); |
132 | } | 135 | } |
133 | }, MoreExecutors.directExecutor()); | 136 | }, MoreExecutors.directExecutor()); |
134 | return Futures.transform(future, response -> { | 137 | return Futures.transform(future, response -> { |
@@ -170,20 +173,20 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | @@ -170,20 +173,20 @@ public class RemoteJsInvokeService extends AbstractJsInvokeService { | ||
170 | if (maxRequestsTimeout > 0) { | 173 | if (maxRequestsTimeout > 0) { |
171 | future = Futures.withTimeout(future, maxRequestsTimeout, TimeUnit.MILLISECONDS, timeoutExecutorService); | 174 | future = Futures.withTimeout(future, maxRequestsTimeout, TimeUnit.MILLISECONDS, timeoutExecutorService); |
172 | } | 175 | } |
173 | - kafkaPushedMsgs.incrementAndGet(); | 176 | + queuePushedMsgs.incrementAndGet(); |
174 | Futures.addCallback(future, new FutureCallback<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>>() { | 177 | Futures.addCallback(future, new FutureCallback<TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse>>() { |
175 | @Override | 178 | @Override |
176 | public void onSuccess(@Nullable TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse> result) { | 179 | public void onSuccess(@Nullable TbProtoQueueMsg<JsInvokeProtos.RemoteJsResponse> result) { |
177 | - kafkaInvokeMsgs.incrementAndGet(); | 180 | + queueInvokeMsgs.incrementAndGet(); |
178 | } | 181 | } |
179 | 182 | ||
180 | @Override | 183 | @Override |
181 | public void onFailure(Throwable t) { | 184 | public void onFailure(Throwable t) { |
182 | onScriptExecutionError(scriptId); | 185 | onScriptExecutionError(scriptId); |
183 | if (t instanceof TimeoutException || (t.getCause() != null && t.getCause() instanceof TimeoutException)) { | 186 | if (t instanceof TimeoutException || (t.getCause() != null && t.getCause() instanceof TimeoutException)) { |
184 | - kafkaTimeoutMsgs.incrementAndGet(); | 187 | + queueTimeoutMsgs.incrementAndGet(); |
185 | } | 188 | } |
186 | - kafkaFailedMsgs.incrementAndGet(); | 189 | + queueFailedMsgs.incrementAndGet(); |
187 | } | 190 | } |
188 | }, MoreExecutors.directExecutor()); | 191 | }, MoreExecutors.directExecutor()); |
189 | return Futures.transform(future, response -> { | 192 | return Futures.transform(future, response -> { |
@@ -15,6 +15,9 @@ | @@ -15,6 +15,9 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.service.security.auth.oauth2; | 16 | package org.thingsboard.server.service.security.auth.oauth2; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
20 | +import com.google.common.base.Strings; | ||
18 | import lombok.extern.slf4j.Slf4j; | 21 | import lombok.extern.slf4j.Slf4j; |
19 | import org.springframework.beans.factory.annotation.Autowired; | 22 | import org.springframework.beans.factory.annotation.Autowired; |
20 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | 23 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
@@ -22,14 +25,21 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; | @@ -22,14 +25,21 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||
22 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | 25 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
23 | import org.springframework.util.StringUtils; | 26 | import org.springframework.util.StringUtils; |
24 | import org.thingsboard.server.common.data.Customer; | 27 | import org.thingsboard.server.common.data.Customer; |
28 | +import org.thingsboard.server.common.data.DashboardInfo; | ||
25 | import org.thingsboard.server.common.data.Tenant; | 29 | import org.thingsboard.server.common.data.Tenant; |
26 | import org.thingsboard.server.common.data.User; | 30 | import org.thingsboard.server.common.data.User; |
27 | import org.thingsboard.server.common.data.id.CustomerId; | 31 | import org.thingsboard.server.common.data.id.CustomerId; |
32 | +import org.thingsboard.server.common.data.id.DashboardId; | ||
33 | +import org.thingsboard.server.common.data.id.IdBased; | ||
28 | import org.thingsboard.server.common.data.id.TenantId; | 34 | import org.thingsboard.server.common.data.id.TenantId; |
35 | +import org.thingsboard.server.common.data.page.TextPageData; | ||
29 | import org.thingsboard.server.common.data.page.TextPageLink; | 36 | import org.thingsboard.server.common.data.page.TextPageLink; |
37 | +import org.thingsboard.server.common.data.page.TimePageData; | ||
38 | +import org.thingsboard.server.common.data.page.TimePageLink; | ||
30 | import org.thingsboard.server.common.data.security.Authority; | 39 | import org.thingsboard.server.common.data.security.Authority; |
31 | import org.thingsboard.server.common.data.security.UserCredentials; | 40 | import org.thingsboard.server.common.data.security.UserCredentials; |
32 | import org.thingsboard.server.dao.customer.CustomerService; | 41 | import org.thingsboard.server.dao.customer.CustomerService; |
42 | +import org.thingsboard.server.dao.dashboard.DashboardService; | ||
33 | import org.thingsboard.server.dao.oauth2.OAuth2User; | 43 | import org.thingsboard.server.dao.oauth2.OAuth2User; |
34 | import org.thingsboard.server.dao.tenant.TenantService; | 44 | import org.thingsboard.server.dao.tenant.TenantService; |
35 | import org.thingsboard.server.dao.user.UserService; | 45 | import org.thingsboard.server.dao.user.UserService; |
@@ -40,11 +50,15 @@ import org.thingsboard.server.service.security.model.UserPrincipal; | @@ -40,11 +50,15 @@ import org.thingsboard.server.service.security.model.UserPrincipal; | ||
40 | import java.io.IOException; | 50 | import java.io.IOException; |
41 | import java.util.List; | 51 | import java.util.List; |
42 | import java.util.Optional; | 52 | import java.util.Optional; |
53 | +import java.util.concurrent.ExecutionException; | ||
43 | import java.util.concurrent.locks.Lock; | 54 | import java.util.concurrent.locks.Lock; |
44 | import java.util.concurrent.locks.ReentrantLock; | 55 | import java.util.concurrent.locks.ReentrantLock; |
45 | 56 | ||
46 | @Slf4j | 57 | @Slf4j |
47 | public abstract class AbstractOAuth2ClientMapper { | 58 | public abstract class AbstractOAuth2ClientMapper { |
59 | + private static final int DASHBOARDS_REQUEST_LIMIT = 10; | ||
60 | + | ||
61 | + private static final ObjectMapper objectMapper = new ObjectMapper(); | ||
48 | 62 | ||
49 | @Autowired | 63 | @Autowired |
50 | private UserService userService; | 64 | private UserService userService; |
@@ -59,6 +73,9 @@ public abstract class AbstractOAuth2ClientMapper { | @@ -59,6 +73,9 @@ public abstract class AbstractOAuth2ClientMapper { | ||
59 | private CustomerService customerService; | 73 | private CustomerService customerService; |
60 | 74 | ||
61 | @Autowired | 75 | @Autowired |
76 | + private DashboardService dashboardService; | ||
77 | + | ||
78 | + @Autowired | ||
62 | private InstallScripts installScripts; | 79 | private InstallScripts installScripts; |
63 | 80 | ||
64 | private final Lock userCreationLock = new ReentrantLock(); | 81 | private final Lock userCreationLock = new ReentrantLock(); |
@@ -92,6 +109,20 @@ public abstract class AbstractOAuth2ClientMapper { | @@ -92,6 +109,20 @@ public abstract class AbstractOAuth2ClientMapper { | ||
92 | user.setEmail(oauth2User.getEmail()); | 109 | user.setEmail(oauth2User.getEmail()); |
93 | user.setFirstName(oauth2User.getFirstName()); | 110 | user.setFirstName(oauth2User.getFirstName()); |
94 | user.setLastName(oauth2User.getLastName()); | 111 | user.setLastName(oauth2User.getLastName()); |
112 | + | ||
113 | + if (!StringUtils.isEmpty(oauth2User.getDefaultDashboardName())) { | ||
114 | + Optional<DashboardId> dashboardIdOpt = | ||
115 | + user.getAuthority() == Authority.TENANT_ADMIN ? | ||
116 | + getDashboardId(tenantId, oauth2User.getDefaultDashboardName()) | ||
117 | + : getDashboardId(tenantId, customerId, oauth2User.getDefaultDashboardName()); | ||
118 | + if (dashboardIdOpt.isPresent()) { | ||
119 | + ObjectNode additionalInfo = objectMapper.createObjectNode(); | ||
120 | + additionalInfo.put("defaultDashboardFullscreen", oauth2User.isAlwaysFullScreen()); | ||
121 | + additionalInfo.put("defaultDashboardId", dashboardIdOpt.get().getId().toString()); | ||
122 | + user.setAdditionalInfo(additionalInfo); | ||
123 | + } | ||
124 | + } | ||
125 | + | ||
95 | user = userService.saveUser(user); | 126 | user = userService.saveUser(user); |
96 | if (activateUser) { | 127 | if (activateUser) { |
97 | UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId()); | 128 | UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId()); |
@@ -143,4 +174,32 @@ public abstract class AbstractOAuth2ClientMapper { | @@ -143,4 +174,32 @@ public abstract class AbstractOAuth2ClientMapper { | ||
143 | return customerService.saveCustomer(customer).getId(); | 174 | return customerService.saveCustomer(customer).getId(); |
144 | } | 175 | } |
145 | } | 176 | } |
177 | + | ||
178 | + private Optional<DashboardId> getDashboardId(TenantId tenantId, String dashboardName) { | ||
179 | + TextPageLink searchTextLink = new TextPageLink(1, dashboardName); | ||
180 | + TextPageData<DashboardInfo> dashboardsPage = dashboardService.findDashboardsByTenantId(tenantId, searchTextLink); | ||
181 | + return dashboardsPage.getData().stream() | ||
182 | + .findAny() | ||
183 | + .map(IdBased::getId); | ||
184 | + } | ||
185 | + | ||
186 | + private Optional<DashboardId> getDashboardId(TenantId tenantId, CustomerId customerId, String dashboardName) { | ||
187 | + TimePageData<DashboardInfo> dashboardsPage = null; | ||
188 | + do { | ||
189 | + TimePageLink timePageLink = dashboardsPage != null ? | ||
190 | + dashboardsPage.getNextPageLink() : new TimePageLink(DASHBOARDS_REQUEST_LIMIT); | ||
191 | + try { | ||
192 | + dashboardsPage = dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, timePageLink).get(); | ||
193 | + } catch (InterruptedException | ExecutionException e) { | ||
194 | + throw new RuntimeException("Failed to get customer's dashboards.", e); | ||
195 | + } | ||
196 | + Optional<DashboardInfo> dashboardInfoOpt = dashboardsPage.getData().stream() | ||
197 | + .filter(dashboardInfo -> dashboardName.equals(dashboardInfo.getName())) | ||
198 | + .findAny(); | ||
199 | + if (dashboardInfoOpt.isPresent()) { | ||
200 | + return dashboardInfoOpt.map(DashboardInfo::getId); | ||
201 | + } | ||
202 | + } while (dashboardsPage.hasNext()); | ||
203 | + return Optional.empty(); | ||
204 | + } | ||
146 | } | 205 | } |
@@ -56,6 +56,10 @@ public class BasicOAuth2ClientMapper extends AbstractOAuth2ClientMapper implemen | @@ -56,6 +56,10 @@ public class BasicOAuth2ClientMapper extends AbstractOAuth2ClientMapper implemen | ||
56 | String customerName = sub.replace(config.getBasic().getCustomerNamePattern()); | 56 | String customerName = sub.replace(config.getBasic().getCustomerNamePattern()); |
57 | oauth2User.setCustomerName(customerName); | 57 | oauth2User.setCustomerName(customerName); |
58 | } | 58 | } |
59 | + oauth2User.setAlwaysFullScreen(config.getBasic().isAlwaysFullScreen()); | ||
60 | + if (!StringUtils.isEmpty(config.getBasic().getDefaultDashboardName())) { | ||
61 | + oauth2User.setDefaultDashboardName(config.getBasic().getDefaultDashboardName()); | ||
62 | + } | ||
59 | 63 | ||
60 | return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.isAllowUserCreation(), config.isActivateUser()); | 64 | return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.isAllowUserCreation(), config.isActivateUser()); |
61 | } | 65 | } |
@@ -56,8 +56,8 @@ public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme | @@ -56,8 +56,8 @@ public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme | ||
56 | try { | 56 | try { |
57 | return restTemplate.postForEntity(custom.getUrl(), request, OAuth2User.class).getBody(); | 57 | return restTemplate.postForEntity(custom.getUrl(), request, OAuth2User.class).getBody(); |
58 | } catch (Exception e) { | 58 | } catch (Exception e) { |
59 | - log.error("Can't connect to custom mapper endpoint", e); | ||
60 | - throw new RuntimeException("Can't connect to custom mapper endpoint", e); | 59 | + log.error("There was an error during connection to custom mapper endpoint", e); |
60 | + throw new RuntimeException("Unable to login. Please contact your Administrator!"); | ||
61 | } | 61 | } |
62 | } | 62 | } |
63 | } | 63 | } |
@@ -32,6 +32,8 @@ import org.thingsboard.server.utils.MiscUtils; | @@ -32,6 +32,8 @@ import org.thingsboard.server.utils.MiscUtils; | ||
32 | import javax.servlet.http.HttpServletRequest; | 32 | import javax.servlet.http.HttpServletRequest; |
33 | import javax.servlet.http.HttpServletResponse; | 33 | import javax.servlet.http.HttpServletResponse; |
34 | import java.io.IOException; | 34 | import java.io.IOException; |
35 | +import java.net.URLEncoder; | ||
36 | +import java.nio.charset.StandardCharsets; | ||
35 | 37 | ||
36 | @Component(value = "oauth2AuthenticationSuccessHandler") | 38 | @Component(value = "oauth2AuthenticationSuccessHandler") |
37 | @ConditionalOnProperty(prefix = "security.oauth2", value = "enabled", havingValue = "true") | 39 | @ConditionalOnProperty(prefix = "security.oauth2", value = "enabled", havingValue = "true") |
@@ -57,16 +59,22 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS | @@ -57,16 +59,22 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS | ||
57 | public void onAuthenticationSuccess(HttpServletRequest request, | 59 | public void onAuthenticationSuccess(HttpServletRequest request, |
58 | HttpServletResponse response, | 60 | HttpServletResponse response, |
59 | Authentication authentication) throws IOException { | 61 | Authentication authentication) throws IOException { |
60 | - OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication; | ||
61 | 62 | ||
62 | - OAuth2Client oauth2Client = oauth2Configuration.getClientByRegistrationId(token.getAuthorizedClientRegistrationId()); | ||
63 | - OAuth2ClientMapper mapper = oauth2ClientMapperProvider.getOAuth2ClientMapperByType(oauth2Client.getMapperConfig().getType()); | ||
64 | - SecurityUser securityUser = mapper.getOrCreateUserByClientPrincipal(token, oauth2Client.getMapperConfig()); | 63 | + String baseUrl = MiscUtils.constructBaseUrl(request); |
64 | + try { | ||
65 | + OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication; | ||
65 | 66 | ||
66 | - JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser); | ||
67 | - JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser); | 67 | + OAuth2Client oauth2Client = oauth2Configuration.getClientByRegistrationId(token.getAuthorizedClientRegistrationId()); |
68 | + OAuth2ClientMapper mapper = oauth2ClientMapperProvider.getOAuth2ClientMapperByType(oauth2Client.getMapperConfig().getType()); | ||
69 | + SecurityUser securityUser = mapper.getOrCreateUserByClientPrincipal(token, oauth2Client.getMapperConfig()); | ||
68 | 70 | ||
69 | - String baseUrl = MiscUtils.constructBaseUrl(request); | ||
70 | - getRedirectStrategy().sendRedirect(request, response, baseUrl + "/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken()); | 71 | + JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser); |
72 | + JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser); | ||
73 | + | ||
74 | + getRedirectStrategy().sendRedirect(request, response, baseUrl + "/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken()); | ||
75 | + } catch (Exception e) { | ||
76 | + getRedirectStrategy().sendRedirect(request, response, baseUrl + "/login?loginError=" + | ||
77 | + URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8.toString())); | ||
78 | + } | ||
71 | } | 79 | } |
72 | } | 80 | } |
@@ -47,4 +47,13 @@ public enum Resource { | @@ -47,4 +47,13 @@ public enum Resource { | ||
47 | public Optional<EntityType> getEntityType() { | 47 | public Optional<EntityType> getEntityType() { |
48 | return Optional.ofNullable(entityType); | 48 | return Optional.ofNullable(entityType); |
49 | } | 49 | } |
50 | + | ||
51 | + public static Resource of(EntityType entityType) { | ||
52 | + for (Resource resource : Resource.values()) { | ||
53 | + if (resource.getEntityType().get() == entityType) { | ||
54 | + return resource; | ||
55 | + } | ||
56 | + } | ||
57 | + throw new IllegalArgumentException("Unknown EntityType: " + entityType.name()); | ||
58 | + } | ||
50 | } | 59 | } |
@@ -292,28 +292,38 @@ public class DefaultDeviceStateService implements DeviceStateService { | @@ -292,28 +292,38 @@ public class DefaultDeviceStateService implements DeviceStateService { | ||
292 | } | 292 | } |
293 | } | 293 | } |
294 | 294 | ||
295 | + volatile Set<TopicPartitionInfo> pendingPartitions; | ||
296 | + | ||
295 | @Override | 297 | @Override |
296 | public void onApplicationEvent(PartitionChangeEvent partitionChangeEvent) { | 298 | public void onApplicationEvent(PartitionChangeEvent partitionChangeEvent) { |
297 | if (ServiceType.TB_CORE.equals(partitionChangeEvent.getServiceType())) { | 299 | if (ServiceType.TB_CORE.equals(partitionChangeEvent.getServiceType())) { |
298 | synchronized (this) { | 300 | synchronized (this) { |
301 | + pendingPartitions = partitionChangeEvent.getPartitions(); | ||
299 | if (!clusterUpdatePending) { | 302 | if (!clusterUpdatePending) { |
300 | clusterUpdatePending = true; | 303 | clusterUpdatePending = true; |
301 | queueExecutor.submit(() -> { | 304 | queueExecutor.submit(() -> { |
302 | clusterUpdatePending = false; | 305 | clusterUpdatePending = false; |
303 | - initStateFromDB(partitionChangeEvent.getPartitions()); | 306 | + initStateFromDB(); |
304 | }); | 307 | }); |
305 | } | 308 | } |
306 | } | 309 | } |
307 | } | 310 | } |
308 | } | 311 | } |
309 | 312 | ||
310 | - private void initStateFromDB(Set<TopicPartitionInfo> partitions) { | 313 | + private void initStateFromDB() { |
311 | try { | 314 | try { |
312 | - Set<TopicPartitionInfo> addedPartitions = new HashSet<>(partitions); | 315 | + log.info("CURRENT PARTITIONS: {}", partitionedDevices.keySet()); |
316 | + log.info("NEW PARTITIONS: {}", pendingPartitions); | ||
317 | + | ||
318 | + Set<TopicPartitionInfo> addedPartitions = new HashSet<>(pendingPartitions); | ||
313 | addedPartitions.removeAll(partitionedDevices.keySet()); | 319 | addedPartitions.removeAll(partitionedDevices.keySet()); |
314 | 320 | ||
321 | + log.info("ADDED PARTITIONS: {}", addedPartitions); | ||
322 | + | ||
315 | Set<TopicPartitionInfo> removedPartitions = new HashSet<>(partitionedDevices.keySet()); | 323 | Set<TopicPartitionInfo> removedPartitions = new HashSet<>(partitionedDevices.keySet()); |
316 | - removedPartitions.removeAll(partitions); | 324 | + removedPartitions.removeAll(pendingPartitions); |
325 | + | ||
326 | + log.info("REMOVED PARTITIONS: {}", removedPartitions); | ||
317 | 327 | ||
318 | // We no longer manage current partition of devices; | 328 | // We no longer manage current partition of devices; |
319 | removedPartitions.forEach(partition -> { | 329 | removedPartitions.forEach(partition -> { |
@@ -224,7 +224,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer | @@ -224,7 +224,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer | ||
224 | return null; | 224 | return null; |
225 | } | 225 | } |
226 | }, | 226 | }, |
227 | - s -> (StringUtils.isEmpty(s.getScope()) || scope.equals(s.getScope().name())), | 227 | + s -> (TbAttributeSubscriptionScope.ANY_SCOPE.equals(s.getScope()) || scope.equals(s.getScope().name())), |
228 | s -> { | 228 | s -> { |
229 | List<TsKvEntry> subscriptionUpdate = null; | 229 | List<TsKvEntry> subscriptionUpdate = null; |
230 | for (AttributeKvEntry kv : attributes) { | 230 | for (AttributeKvEntry kv : attributes) { |
@@ -17,6 +17,6 @@ package org.thingsboard.server.service.subscription; | @@ -17,6 +17,6 @@ package org.thingsboard.server.service.subscription; | ||
17 | 17 | ||
18 | public enum TbAttributeSubscriptionScope { | 18 | public enum TbAttributeSubscriptionScope { |
19 | 19 | ||
20 | - CLIENT_SCOPE, SHARED_SCOPE, SERVER_SCOPE | 20 | + ANY_SCOPE, CLIENT_SCOPE, SHARED_SCOPE, SERVER_SCOPE |
21 | 21 | ||
22 | } | 22 | } |
@@ -345,7 +345,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | @@ -345,7 +345,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | ||
345 | keys.forEach(key -> subState.put(key, 0L)); | 345 | keys.forEach(key -> subState.put(key, 0L)); |
346 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); | 346 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); |
347 | 347 | ||
348 | - TbAttributeSubscriptionScope scope = StringUtils.isEmpty(cmd.getScope()) ? TbAttributeSubscriptionScope.SERVER_SCOPE : TbAttributeSubscriptionScope.valueOf(cmd.getScope()); | 348 | + TbAttributeSubscriptionScope scope = StringUtils.isEmpty(cmd.getScope()) ? TbAttributeSubscriptionScope.ANY_SCOPE : TbAttributeSubscriptionScope.valueOf(cmd.getScope()); |
349 | 349 | ||
350 | TbAttributeSubscription sub = TbAttributeSubscription.builder() | 350 | TbAttributeSubscription sub = TbAttributeSubscription.builder() |
351 | .serviceId(serviceId) | 351 | .serviceId(serviceId) |
@@ -442,7 +442,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | @@ -442,7 +442,7 @@ public class DefaultTelemetryWebSocketService implements TelemetryWebSocketServi | ||
442 | Map<String, Long> subState = new HashMap<>(attributesData.size()); | 442 | Map<String, Long> subState = new HashMap<>(attributesData.size()); |
443 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); | 443 | attributesData.forEach(v -> subState.put(v.getKey(), v.getTs())); |
444 | 444 | ||
445 | - TbAttributeSubscriptionScope scope = StringUtils.isEmpty(cmd.getScope()) ? TbAttributeSubscriptionScope.SERVER_SCOPE : TbAttributeSubscriptionScope.valueOf(cmd.getScope()); | 445 | + TbAttributeSubscriptionScope scope = StringUtils.isEmpty(cmd.getScope()) ? TbAttributeSubscriptionScope.ANY_SCOPE : TbAttributeSubscriptionScope.valueOf(cmd.getScope()); |
446 | 446 | ||
447 | TbAttributeSubscription sub = TbAttributeSubscription.builder() | 447 | TbAttributeSubscription sub = TbAttributeSubscription.builder() |
448 | .serviceId(serviceId) | 448 | .serviceId(serviceId) |
@@ -17,6 +17,7 @@ package org.thingsboard.server.service.transport; | @@ -17,6 +17,7 @@ package org.thingsboard.server.service.transport; | ||
17 | 17 | ||
18 | import com.fasterxml.jackson.core.JsonProcessingException; | 18 | import com.fasterxml.jackson.core.JsonProcessingException; |
19 | import com.fasterxml.jackson.databind.ObjectMapper; | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
20 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
20 | import com.google.common.util.concurrent.Futures; | 21 | import com.google.common.util.concurrent.Futures; |
21 | import com.google.common.util.concurrent.ListenableFuture; | 22 | import com.google.common.util.concurrent.ListenableFuture; |
22 | import com.google.common.util.concurrent.MoreExecutors; | 23 | import com.google.common.util.concurrent.MoreExecutors; |
@@ -24,13 +25,18 @@ import lombok.extern.slf4j.Slf4j; | @@ -24,13 +25,18 @@ import lombok.extern.slf4j.Slf4j; | ||
24 | import org.springframework.beans.factory.annotation.Autowired; | 25 | import org.springframework.beans.factory.annotation.Autowired; |
25 | import org.springframework.stereotype.Service; | 26 | import org.springframework.stereotype.Service; |
26 | import org.springframework.util.StringUtils; | 27 | import org.springframework.util.StringUtils; |
28 | +import org.thingsboard.server.common.data.DataConstants; | ||
27 | import org.thingsboard.server.common.data.Device; | 29 | import org.thingsboard.server.common.data.Device; |
28 | import org.thingsboard.server.common.data.Tenant; | 30 | import org.thingsboard.server.common.data.Tenant; |
31 | +import org.thingsboard.server.common.data.id.CustomerId; | ||
29 | import org.thingsboard.server.common.data.id.DeviceId; | 32 | import org.thingsboard.server.common.data.id.DeviceId; |
30 | import org.thingsboard.server.common.data.id.TenantId; | 33 | import org.thingsboard.server.common.data.id.TenantId; |
31 | import org.thingsboard.server.common.data.relation.EntityRelation; | 34 | import org.thingsboard.server.common.data.relation.EntityRelation; |
32 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 35 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
33 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; | 36 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
37 | +import org.thingsboard.server.common.msg.TbMsg; | ||
38 | +import org.thingsboard.server.common.msg.TbMsgDataType; | ||
39 | +import org.thingsboard.server.common.msg.TbMsgMetaData; | ||
34 | import org.thingsboard.server.dao.device.DeviceCredentialsService; | 40 | import org.thingsboard.server.dao.device.DeviceCredentialsService; |
35 | import org.thingsboard.server.dao.device.DeviceService; | 41 | import org.thingsboard.server.dao.device.DeviceService; |
36 | import org.thingsboard.server.dao.relation.RelationService; | 42 | import org.thingsboard.server.dao.relation.RelationService; |
@@ -48,6 +54,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509Ce | @@ -48,6 +54,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509Ce | ||
48 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; | 54 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
49 | import org.thingsboard.server.queue.util.TbCoreComponent; | 55 | import org.thingsboard.server.queue.util.TbCoreComponent; |
50 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; | 56 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
57 | +import org.thingsboard.server.service.queue.TbClusterService; | ||
51 | import org.thingsboard.server.service.state.DeviceStateService; | 58 | import org.thingsboard.server.service.state.DeviceStateService; |
52 | 59 | ||
53 | import java.util.UUID; | 60 | import java.util.UUID; |
@@ -82,6 +89,9 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -82,6 +89,9 @@ public class DefaultTransportApiService implements TransportApiService { | ||
82 | @Autowired | 89 | @Autowired |
83 | private DbCallbackExecutorService dbCallbackExecutorService; | 90 | private DbCallbackExecutorService dbCallbackExecutorService; |
84 | 91 | ||
92 | + @Autowired | ||
93 | + protected TbClusterService tbClusterService; | ||
94 | + | ||
85 | private ReentrantLock deviceCreationLock = new ReentrantLock(); | 95 | private ReentrantLock deviceCreationLock = new ReentrantLock(); |
86 | 96 | ||
87 | @Override | 97 | @Override |
@@ -119,14 +129,27 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -119,14 +129,27 @@ public class DefaultTransportApiService implements TransportApiService { | ||
119 | try { | 129 | try { |
120 | Device device = deviceService.findDeviceByTenantIdAndName(gateway.getTenantId(), requestMsg.getDeviceName()); | 130 | Device device = deviceService.findDeviceByTenantIdAndName(gateway.getTenantId(), requestMsg.getDeviceName()); |
121 | if (device == null) { | 131 | if (device == null) { |
132 | + TenantId tenantId = gateway.getTenantId(); | ||
122 | device = new Device(); | 133 | device = new Device(); |
123 | - device.setTenantId(gateway.getTenantId()); | 134 | + device.setTenantId(tenantId); |
124 | device.setName(requestMsg.getDeviceName()); | 135 | device.setName(requestMsg.getDeviceName()); |
125 | device.setType(requestMsg.getDeviceType()); | 136 | device.setType(requestMsg.getDeviceType()); |
126 | device.setCustomerId(gateway.getCustomerId()); | 137 | device.setCustomerId(gateway.getCustomerId()); |
127 | device = deviceService.saveDevice(device); | 138 | device = deviceService.saveDevice(device); |
128 | relationService.saveRelationAsync(TenantId.SYS_TENANT_ID, new EntityRelation(gateway.getId(), device.getId(), "Created")); | 139 | relationService.saveRelationAsync(TenantId.SYS_TENANT_ID, new EntityRelation(gateway.getId(), device.getId(), "Created")); |
129 | deviceStateService.onDeviceAdded(device); | 140 | deviceStateService.onDeviceAdded(device); |
141 | + | ||
142 | + TbMsgMetaData metaData = new TbMsgMetaData(); | ||
143 | + CustomerId customerId = gateway.getCustomerId(); | ||
144 | + if (customerId != null && !customerId.isNullUid()) { | ||
145 | + metaData.putValue("customerId", customerId.toString()); | ||
146 | + } | ||
147 | + metaData.putValue("gatewayId", gatewayId.toString()); | ||
148 | + | ||
149 | + DeviceId deviceId = device.getId(); | ||
150 | + ObjectNode entityNode = mapper.valueToTree(device); | ||
151 | + TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, deviceId, metaData, TbMsgDataType.JSON, mapper.writeValueAsString(entityNode)); | ||
152 | + tbClusterService.pushMsgToRuleEngine(tenantId, deviceId, tbMsg, null); | ||
130 | } | 153 | } |
131 | return TransportApiResponseMsg.newBuilder() | 154 | return TransportApiResponseMsg.newBuilder() |
132 | .setGetOrCreateDeviceResponseMsg(GetOrCreateDeviceFromGatewayResponseMsg.newBuilder().setDeviceInfo(getDeviceInfoProto(device)).build()).build(); | 155 | .setGetOrCreateDeviceResponseMsg(GetOrCreateDeviceFromGatewayResponseMsg.newBuilder().setDeviceInfo(getDeviceInfoProto(device)).build()).build(); |
@@ -54,6 +54,13 @@ server: | @@ -54,6 +54,13 @@ server: | ||
54 | customer: | 54 | customer: |
55 | enabled: "${TB_SERVER_REST_LIMITS_CUSTOMER_ENABLED:false}" | 55 | enabled: "${TB_SERVER_REST_LIMITS_CUSTOMER_ENABLED:false}" |
56 | configuration: "${TB_SERVER_REST_LIMITS_CUSTOMER_CONFIGURATION:50:1,1000:60}" | 56 | configuration: "${TB_SERVER_REST_LIMITS_CUSTOMER_CONFIGURATION:50:1,1000:60}" |
57 | + server_side_rpc: | ||
58 | + # Minimum value of the server side RPC timeout. May override value provided in the REST API call. | ||
59 | + # Since 2.5 migration to queues, the RPC delay depends on the size of the pending messages in the queue, | ||
60 | + # so default UI parameter of 500ms may not be sufficient for loaded environments. | ||
61 | + min_timeout: "${MIN_SERVER_SIDE_RPC_TIMEOUT:5000}" | ||
62 | + # Default value of the server side RPC timeout. | ||
63 | + default_timeout: "${DEFAULT_SERVER_SIDE_RPC_TIMEOUT:10000}" | ||
57 | 64 | ||
58 | # Zookeeper connection parameters. Used for service discovery. | 65 | # Zookeeper connection parameters. Used for service discovery. |
59 | zk: | 66 | zk: |
@@ -148,6 +155,10 @@ security: | @@ -148,6 +155,10 @@ security: | ||
148 | # If this field is not empty, user will be created as a user under defined Customer | 155 | # If this field is not empty, user will be created as a user under defined Customer |
149 | # %{attribute_key} as placeholder for attribute value of attributes of external user object | 156 | # %{attribute_key} as placeholder for attribute value of attributes of external user object |
150 | customerNamePattern: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_CUSTOMER_NAME_PATTERN:}" | 157 | customerNamePattern: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_CUSTOMER_NAME_PATTERN:}" |
158 | + # If this field is not empty, user will be created with default defined Dashboard | ||
159 | + defaultDashboardName: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_DEFAULT_DASHBOARD_NAME:}" | ||
160 | + # If this field is set 'true' along with non-empty 'defaultDashboardName', user will start from the defined Dashboard in fullscreen mode | ||
161 | + alwaysFullScreen: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_ALWAYS_FULL_SCREEN:false}" | ||
151 | custom: | 162 | custom: |
152 | url: "${SECURITY_OAUTH2_DEFAULT_MAPPER_CUSTOM_URL:}" | 163 | url: "${SECURITY_OAUTH2_DEFAULT_MAPPER_CUSTOM_URL:}" |
153 | username: "${SECURITY_OAUTH2_DEFAULT_MAPPER_CUSTOM_USERNAME:}" | 164 | username: "${SECURITY_OAUTH2_DEFAULT_MAPPER_CUSTOM_USERNAME:}" |
@@ -676,7 +687,7 @@ queue: | @@ -676,7 +687,7 @@ queue: | ||
676 | topic: "${TB_QUEUE_CORE_TOPIC:tb_core}" | 687 | topic: "${TB_QUEUE_CORE_TOPIC:tb_core}" |
677 | poll-interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}" | 688 | poll-interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}" |
678 | partitions: "${TB_QUEUE_CORE_PARTITIONS:10}" | 689 | partitions: "${TB_QUEUE_CORE_PARTITIONS:10}" |
679 | - pack-processing-timeout: "${TB_QUEUE_CORE_PACK_PROCESSING_TIMEOUT_MS:60000}" | 690 | + pack-processing-timeout: "${TB_QUEUE_CORE_PACK_PROCESSING_TIMEOUT_MS:2000}" |
680 | stats: | 691 | stats: |
681 | enabled: "${TB_QUEUE_CORE_STATS_ENABLED:true}" | 692 | enabled: "${TB_QUEUE_CORE_STATS_ENABLED:true}" |
682 | print-interval-ms: "${TB_QUEUE_CORE_STATS_PRINT_INTERVAL_MS:60000}" | 693 | print-interval-ms: "${TB_QUEUE_CORE_STATS_PRINT_INTERVAL_MS:60000}" |
@@ -688,6 +699,8 @@ queue: | @@ -688,6 +699,8 @@ queue: | ||
688 | # JS Eval max pending requests | 699 | # JS Eval max pending requests |
689 | max_pending_requests: "${REMOTE_JS_MAX_PENDING_REQUESTS:10000}" | 700 | max_pending_requests: "${REMOTE_JS_MAX_PENDING_REQUESTS:10000}" |
690 | # JS Eval max request timeout | 701 | # JS Eval max request timeout |
702 | + max_eval_requests_timeout: "${REMOTE_JS_MAX_EVAL_REQUEST_TIMEOUT:60000}" | ||
703 | + # JS max request timeout | ||
691 | max_requests_timeout: "${REMOTE_JS_MAX_REQUEST_TIMEOUT:10000}" | 704 | max_requests_timeout: "${REMOTE_JS_MAX_REQUEST_TIMEOUT:10000}" |
692 | # JS response poll interval | 705 | # JS response poll interval |
693 | response_poll_interval: "${REMOTE_JS_RESPONSE_POLL_INTERVAL_MS:25}" | 706 | response_poll_interval: "${REMOTE_JS_RESPONSE_POLL_INTERVAL_MS:25}" |
@@ -696,7 +709,7 @@ queue: | @@ -696,7 +709,7 @@ queue: | ||
696 | rule-engine: | 709 | rule-engine: |
697 | topic: "${TB_QUEUE_RULE_ENGINE_TOPIC:tb_rule_engine}" | 710 | topic: "${TB_QUEUE_RULE_ENGINE_TOPIC:tb_rule_engine}" |
698 | poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}" | 711 | poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}" |
699 | - pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}" | 712 | + pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:2000}" |
700 | stats: | 713 | stats: |
701 | enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}" | 714 | enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}" |
702 | print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:60000}" | 715 | print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:60000}" |
@@ -705,7 +718,7 @@ queue: | @@ -705,7 +718,7 @@ queue: | ||
705 | topic: "${TB_QUEUE_RE_MAIN_TOPIC:tb_rule_engine.main}" | 718 | topic: "${TB_QUEUE_RE_MAIN_TOPIC:tb_rule_engine.main}" |
706 | poll-interval: "${TB_QUEUE_RE_MAIN_POLL_INTERVAL_MS:25}" | 719 | poll-interval: "${TB_QUEUE_RE_MAIN_POLL_INTERVAL_MS:25}" |
707 | partitions: "${TB_QUEUE_RE_MAIN_PARTITIONS:10}" | 720 | partitions: "${TB_QUEUE_RE_MAIN_PARTITIONS:10}" |
708 | - pack-processing-timeout: "${TB_QUEUE_RE_MAIN_PACK_PROCESSING_TIMEOUT_MS:60000}" | 721 | + pack-processing-timeout: "${TB_QUEUE_RE_MAIN_PACK_PROCESSING_TIMEOUT_MS:2000}" |
709 | submit-strategy: | 722 | submit-strategy: |
710 | type: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL | 723 | type: "${TB_QUEUE_RE_MAIN_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL |
711 | # For BATCH only | 724 | # For BATCH only |
@@ -720,7 +733,7 @@ queue: | @@ -720,7 +733,7 @@ queue: | ||
720 | topic: "${TB_QUEUE_RE_HP_TOPIC:tb_rule_engine.hp}" | 733 | topic: "${TB_QUEUE_RE_HP_TOPIC:tb_rule_engine.hp}" |
721 | poll-interval: "${TB_QUEUE_RE_HP_POLL_INTERVAL_MS:25}" | 734 | poll-interval: "${TB_QUEUE_RE_HP_POLL_INTERVAL_MS:25}" |
722 | partitions: "${TB_QUEUE_RE_HP_PARTITIONS:10}" | 735 | partitions: "${TB_QUEUE_RE_HP_PARTITIONS:10}" |
723 | - pack-processing-timeout: "${TB_QUEUE_RE_HP_PACK_PROCESSING_TIMEOUT_MS:60000}" | 736 | + pack-processing-timeout: "${TB_QUEUE_RE_HP_PACK_PROCESSING_TIMEOUT_MS:2000}" |
724 | submit-strategy: | 737 | submit-strategy: |
725 | type: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL | 738 | type: "${TB_QUEUE_RE_HP_SUBMIT_STRATEGY_TYPE:BURST}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL |
726 | # For BATCH only | 739 | # For BATCH only |
@@ -735,7 +748,7 @@ queue: | @@ -735,7 +748,7 @@ queue: | ||
735 | topic: "${TB_QUEUE_RE_SQ_TOPIC:tb_rule_engine.sq}" | 748 | topic: "${TB_QUEUE_RE_SQ_TOPIC:tb_rule_engine.sq}" |
736 | poll-interval: "${TB_QUEUE_RE_SQ_POLL_INTERVAL_MS:25}" | 749 | poll-interval: "${TB_QUEUE_RE_SQ_POLL_INTERVAL_MS:25}" |
737 | partitions: "${TB_QUEUE_RE_SQ_PARTITIONS:10}" | 750 | partitions: "${TB_QUEUE_RE_SQ_PARTITIONS:10}" |
738 | - pack-processing-timeout: "${TB_QUEUE_RE_SQ_PACK_PROCESSING_TIMEOUT_MS:60000}" | 751 | + pack-processing-timeout: "${TB_QUEUE_RE_SQ_PACK_PROCESSING_TIMEOUT_MS:2000}" |
739 | submit-strategy: | 752 | submit-strategy: |
740 | type: "${TB_QUEUE_RE_SQ_SUBMIT_STRATEGY_TYPE:SEQUENTIAL_BY_ORIGINATOR}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL | 753 | type: "${TB_QUEUE_RE_SQ_SUBMIT_STRATEGY_TYPE:SEQUENTIAL_BY_ORIGINATOR}" # BURST, BATCH, SEQUENTIAL_BY_ORIGINATOR, SEQUENTIAL_BY_TENANT, SEQUENTIAL |
741 | # For BATCH only | 754 | # For BATCH only |
@@ -33,7 +33,6 @@ import org.junit.rules.TestRule; | @@ -33,7 +33,6 @@ import org.junit.rules.TestRule; | ||
33 | import org.junit.rules.TestWatcher; | 33 | import org.junit.rules.TestWatcher; |
34 | import org.junit.runner.Description; | 34 | import org.junit.runner.Description; |
35 | import org.junit.runner.RunWith; | 35 | import org.junit.runner.RunWith; |
36 | -import org.mockito.Mockito; | ||
37 | import org.springframework.beans.factory.annotation.Autowired; | 36 | import org.springframework.beans.factory.annotation.Autowired; |
38 | import org.springframework.boot.test.context.SpringBootContextLoader; | 37 | import org.springframework.boot.test.context.SpringBootContextLoader; |
39 | import org.springframework.boot.test.context.SpringBootTest; | 38 | import org.springframework.boot.test.context.SpringBootTest; |
@@ -49,7 +48,6 @@ import org.springframework.mock.http.MockHttpOutputMessage; | @@ -49,7 +48,6 @@ import org.springframework.mock.http.MockHttpOutputMessage; | ||
49 | import org.springframework.test.annotation.DirtiesContext; | 48 | import org.springframework.test.annotation.DirtiesContext; |
50 | import org.springframework.test.context.ActiveProfiles; | 49 | import org.springframework.test.context.ActiveProfiles; |
51 | import org.springframework.test.context.ContextConfiguration; | 50 | import org.springframework.test.context.ContextConfiguration; |
52 | -import org.springframework.test.context.TestPropertySource; | ||
53 | import org.springframework.test.context.junit4.SpringRunner; | 51 | import org.springframework.test.context.junit4.SpringRunner; |
54 | import org.springframework.test.context.web.WebAppConfiguration; | 52 | import org.springframework.test.context.web.WebAppConfiguration; |
55 | import org.springframework.test.web.servlet.MockMvc; | 53 | import org.springframework.test.web.servlet.MockMvc; |
@@ -75,7 +73,6 @@ import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRequest; | @@ -75,7 +73,6 @@ import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRequest; | ||
75 | import org.thingsboard.server.service.security.auth.rest.LoginRequest; | 73 | import org.thingsboard.server.service.security.auth.rest.LoginRequest; |
76 | 74 | ||
77 | import java.io.IOException; | 75 | import java.io.IOException; |
78 | -import java.nio.charset.Charset; | ||
79 | import java.util.ArrayList; | 76 | import java.util.ArrayList; |
80 | import java.util.Arrays; | 77 | import java.util.Arrays; |
81 | import java.util.Comparator; | 78 | import java.util.Comparator; |
@@ -223,6 +220,27 @@ public abstract class AbstractControllerTest { | @@ -223,6 +220,27 @@ public abstract class AbstractControllerTest { | ||
223 | login(CUSTOMER_USER_EMAIL, CUSTOMER_USER_PASSWORD); | 220 | login(CUSTOMER_USER_EMAIL, CUSTOMER_USER_PASSWORD); |
224 | } | 221 | } |
225 | 222 | ||
223 | + private Tenant savedDifferentTenant; | ||
224 | + protected void loginDifferentTenant() throws Exception { | ||
225 | + loginSysAdmin(); | ||
226 | + Tenant tenant = new Tenant(); | ||
227 | + tenant.setTitle("Different tenant"); | ||
228 | + savedDifferentTenant = doPost("/api/tenant", tenant, Tenant.class); | ||
229 | + Assert.assertNotNull(savedDifferentTenant); | ||
230 | + User differentTenantAdmin = new User(); | ||
231 | + differentTenantAdmin.setAuthority(Authority.TENANT_ADMIN); | ||
232 | + differentTenantAdmin.setTenantId(savedDifferentTenant.getId()); | ||
233 | + differentTenantAdmin.setEmail("different_tenant@thingsboard.org"); | ||
234 | + | ||
235 | + createUserAndLogin(differentTenantAdmin, "testPassword"); | ||
236 | + } | ||
237 | + | ||
238 | + protected void deleteDifferentTenant() throws Exception { | ||
239 | + loginSysAdmin(); | ||
240 | + doDelete("/api/tenant/" + savedDifferentTenant.getId().getId().toString()) | ||
241 | + .andExpect(status().isOk()); | ||
242 | + } | ||
243 | + | ||
226 | protected User createUserAndLogin(User user, String password) throws Exception { | 244 | protected User createUserAndLogin(User user, String password) throws Exception { |
227 | User savedUser = doPost("/api/user", user, User.class); | 245 | User savedUser = doPost("/api/user", user, User.class); |
228 | logout(); | 246 | logout(); |
@@ -99,6 +99,18 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -99,6 +99,18 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
99 | } | 99 | } |
100 | 100 | ||
101 | @Test | 101 | @Test |
102 | + public void testUpdateAssetFromDifferentTenant() throws Exception { | ||
103 | + Asset asset = new Asset(); | ||
104 | + asset.setName("My asset"); | ||
105 | + asset.setType("default"); | ||
106 | + Asset savedAsset = doPost("/api/asset", asset, Asset.class); | ||
107 | + | ||
108 | + loginDifferentTenant(); | ||
109 | + doPost("/api/asset", savedAsset, Asset.class, status().isForbidden()); | ||
110 | + deleteDifferentTenant(); | ||
111 | + } | ||
112 | + | ||
113 | + @Test | ||
102 | public void testFindAssetById() throws Exception { | 114 | public void testFindAssetById() throws Exception { |
103 | Asset asset = new Asset(); | 115 | Asset asset = new Asset(); |
104 | asset.setName("My asset"); | 116 | asset.setName("My asset"); |
@@ -23,6 +23,8 @@ import java.util.Collections; | @@ -23,6 +23,8 @@ import java.util.Collections; | ||
23 | import java.util.List; | 23 | import java.util.List; |
24 | 24 | ||
25 | import org.apache.commons.lang3.RandomStringUtils; | 25 | import org.apache.commons.lang3.RandomStringUtils; |
26 | +import org.junit.After; | ||
27 | +import org.junit.Before; | ||
26 | import org.thingsboard.server.common.data.Customer; | 28 | import org.thingsboard.server.common.data.Customer; |
27 | import org.thingsboard.server.common.data.Tenant; | 29 | import org.thingsboard.server.common.data.Tenant; |
28 | import org.thingsboard.server.common.data.User; | 30 | import org.thingsboard.server.common.data.User; |
@@ -38,25 +40,39 @@ import com.fasterxml.jackson.core.type.TypeReference; | @@ -38,25 +40,39 @@ import com.fasterxml.jackson.core.type.TypeReference; | ||
38 | public abstract class BaseCustomerControllerTest extends AbstractControllerTest { | 40 | public abstract class BaseCustomerControllerTest extends AbstractControllerTest { |
39 | 41 | ||
40 | private IdComparator<Customer> idComparator = new IdComparator<>(); | 42 | private IdComparator<Customer> idComparator = new IdComparator<>(); |
41 | - | ||
42 | - @Test | ||
43 | - public void testSaveCustomer() throws Exception { | 43 | + |
44 | + private Tenant savedTenant; | ||
45 | + private User tenantAdmin; | ||
46 | + | ||
47 | + @Before | ||
48 | + public void beforeTest() throws Exception { | ||
44 | loginSysAdmin(); | 49 | loginSysAdmin(); |
45 | 50 | ||
46 | Tenant tenant = new Tenant(); | 51 | Tenant tenant = new Tenant(); |
47 | tenant.setTitle("My tenant"); | 52 | tenant.setTitle("My tenant"); |
48 | - Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 53 | + savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
49 | Assert.assertNotNull(savedTenant); | 54 | Assert.assertNotNull(savedTenant); |
50 | - | ||
51 | - User tenantAdmin = new User(); | 55 | + |
56 | + tenantAdmin = new User(); | ||
52 | tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | 57 | tenantAdmin.setAuthority(Authority.TENANT_ADMIN); |
53 | tenantAdmin.setTenantId(savedTenant.getId()); | 58 | tenantAdmin.setTenantId(savedTenant.getId()); |
54 | tenantAdmin.setEmail("tenant2@thingsboard.org"); | 59 | tenantAdmin.setEmail("tenant2@thingsboard.org"); |
55 | tenantAdmin.setFirstName("Joe"); | 60 | tenantAdmin.setFirstName("Joe"); |
56 | tenantAdmin.setLastName("Downs"); | 61 | tenantAdmin.setLastName("Downs"); |
57 | - | 62 | + |
58 | tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | 63 | tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); |
59 | - | 64 | + } |
65 | + | ||
66 | + @After | ||
67 | + public void afterTest() throws Exception { | ||
68 | + loginSysAdmin(); | ||
69 | + | ||
70 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
71 | + .andExpect(status().isOk()); | ||
72 | + } | ||
73 | + | ||
74 | + @Test | ||
75 | + public void testSaveCustomer() throws Exception { | ||
60 | Customer customer = new Customer(); | 76 | Customer customer = new Customer(); |
61 | customer.setTitle("My customer"); | 77 | customer.setTitle("My customer"); |
62 | Customer savedCustomer = doPost("/api/customer", customer, Customer.class); | 78 | Customer savedCustomer = doPost("/api/customer", customer, Customer.class); |
@@ -66,266 +82,159 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | @@ -66,266 +82,159 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | ||
66 | Assert.assertEquals(customer.getTitle(), savedCustomer.getTitle()); | 82 | Assert.assertEquals(customer.getTitle(), savedCustomer.getTitle()); |
67 | savedCustomer.setTitle("My new customer"); | 83 | savedCustomer.setTitle("My new customer"); |
68 | doPost("/api/customer", savedCustomer, Customer.class); | 84 | doPost("/api/customer", savedCustomer, Customer.class); |
69 | - | ||
70 | - Customer foundCustomer = doGet("/api/customer/"+savedCustomer.getId().getId().toString(), Customer.class); | 85 | + |
86 | + Customer foundCustomer = doGet("/api/customer/"+savedCustomer.getId().getId().toString(), Customer.class); | ||
71 | Assert.assertEquals(foundCustomer.getTitle(), savedCustomer.getTitle()); | 87 | Assert.assertEquals(foundCustomer.getTitle(), savedCustomer.getTitle()); |
72 | - | 88 | + |
73 | doDelete("/api/customer/"+savedCustomer.getId().getId().toString()) | 89 | doDelete("/api/customer/"+savedCustomer.getId().getId().toString()) |
74 | .andExpect(status().isOk()); | 90 | .andExpect(status().isOk()); |
75 | - | ||
76 | - loginSysAdmin(); | ||
77 | - | ||
78 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
79 | - .andExpect(status().isOk()); | ||
80 | } | 91 | } |
81 | - | 92 | + |
82 | @Test | 93 | @Test |
83 | - public void testFindCustomerById() throws Exception { | ||
84 | - | ||
85 | - loginSysAdmin(); | 94 | + public void testUpdateCustomerFromDifferentTenant() throws Exception { |
95 | + Customer customer = new Customer(); | ||
96 | + customer.setTitle("My customer"); | ||
97 | + Customer savedCustomer = doPost("/api/customer", customer, Customer.class); | ||
98 | + doPost("/api/customer", savedCustomer, Customer.class); | ||
86 | 99 | ||
87 | - Tenant tenant = new Tenant(); | ||
88 | - tenant.setTitle("My tenant"); | ||
89 | - Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | ||
90 | - Assert.assertNotNull(savedTenant); | ||
91 | - | ||
92 | - User tenantAdmin = new User(); | ||
93 | - tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | ||
94 | - tenantAdmin.setTenantId(savedTenant.getId()); | ||
95 | - tenantAdmin.setEmail("tenant2@thingsboard.org"); | ||
96 | - tenantAdmin.setFirstName("Joe"); | ||
97 | - tenantAdmin.setLastName("Downs"); | ||
98 | - | ||
99 | - tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | ||
100 | - | 100 | + loginDifferentTenant(); |
101 | + doPost("/api/customer", savedCustomer, Customer.class, status().isForbidden()); | ||
102 | + deleteDifferentTenant(); | ||
103 | + | ||
104 | + login(tenantAdmin.getName(), "testPassword1"); | ||
105 | + doDelete("/api/customer/" + savedCustomer.getId().getId().toString()) | ||
106 | + .andExpect(status().isOk()); | ||
107 | + } | ||
108 | + | ||
109 | + @Test | ||
110 | + public void testFindCustomerById() throws Exception { | ||
101 | Customer customer = new Customer(); | 111 | Customer customer = new Customer(); |
102 | customer.setTitle("My customer"); | 112 | customer.setTitle("My customer"); |
103 | Customer savedCustomer = doPost("/api/customer", customer, Customer.class); | 113 | Customer savedCustomer = doPost("/api/customer", customer, Customer.class); |
104 | - | ||
105 | - Customer foundCustomer = doGet("/api/customer/"+savedCustomer.getId().getId().toString(), Customer.class); | 114 | + |
115 | + Customer foundCustomer = doGet("/api/customer/" + savedCustomer.getId().getId().toString(), Customer.class); | ||
106 | Assert.assertNotNull(foundCustomer); | 116 | Assert.assertNotNull(foundCustomer); |
107 | Assert.assertEquals(savedCustomer, foundCustomer); | 117 | Assert.assertEquals(savedCustomer, foundCustomer); |
108 | - | ||
109 | - doDelete("/api/customer/"+savedCustomer.getId().getId().toString()) | ||
110 | - .andExpect(status().isOk()); | ||
111 | - | ||
112 | - loginSysAdmin(); | ||
113 | - | ||
114 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
115 | - .andExpect(status().isOk()); | 118 | + |
119 | + doDelete("/api/customer/" + savedCustomer.getId().getId().toString()) | ||
120 | + .andExpect(status().isOk()); | ||
116 | } | 121 | } |
117 | - | 122 | + |
118 | @Test | 123 | @Test |
119 | public void testDeleteCustomer() throws Exception { | 124 | public void testDeleteCustomer() throws Exception { |
120 | - | ||
121 | - loginSysAdmin(); | ||
122 | - | ||
123 | - Tenant tenant = new Tenant(); | ||
124 | - tenant.setTitle("My tenant"); | ||
125 | - Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | ||
126 | - Assert.assertNotNull(savedTenant); | ||
127 | - | ||
128 | - User tenantAdmin = new User(); | ||
129 | - tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | ||
130 | - tenantAdmin.setTenantId(savedTenant.getId()); | ||
131 | - tenantAdmin.setEmail("tenant2@thingsboard.org"); | ||
132 | - tenantAdmin.setFirstName("Joe"); | ||
133 | - tenantAdmin.setLastName("Downs"); | ||
134 | - | ||
135 | - tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | ||
136 | - | ||
137 | Customer customer = new Customer(); | 125 | Customer customer = new Customer(); |
138 | customer.setTitle("My customer"); | 126 | customer.setTitle("My customer"); |
139 | Customer savedCustomer = doPost("/api/customer", customer, Customer.class); | 127 | Customer savedCustomer = doPost("/api/customer", customer, Customer.class); |
140 | - | ||
141 | - doDelete("/api/customer/"+savedCustomer.getId().getId().toString()) | ||
142 | - .andExpect(status().isOk()); | ||
143 | 128 | ||
144 | - doGet("/api/customer/"+savedCustomer.getId().getId().toString()) | ||
145 | - .andExpect(status().isNotFound()); | ||
146 | - | ||
147 | - loginSysAdmin(); | ||
148 | - | ||
149 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
150 | - .andExpect(status().isOk()); | 129 | + doDelete("/api/customer/" + savedCustomer.getId().getId().toString()) |
130 | + .andExpect(status().isOk()); | ||
131 | + | ||
132 | + doGet("/api/customer/" + savedCustomer.getId().getId().toString()) | ||
133 | + .andExpect(status().isNotFound()); | ||
151 | } | 134 | } |
152 | - | 135 | + |
153 | @Test | 136 | @Test |
154 | public void testSaveCustomerWithEmptyTitle() throws Exception { | 137 | public void testSaveCustomerWithEmptyTitle() throws Exception { |
155 | - | ||
156 | - loginSysAdmin(); | ||
157 | - | ||
158 | - Tenant tenant = new Tenant(); | ||
159 | - tenant.setTitle("My tenant"); | ||
160 | - Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | ||
161 | - Assert.assertNotNull(savedTenant); | ||
162 | - | ||
163 | - User tenantAdmin = new User(); | ||
164 | - tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | ||
165 | - tenantAdmin.setTenantId(savedTenant.getId()); | ||
166 | - tenantAdmin.setEmail("tenant2@thingsboard.org"); | ||
167 | - tenantAdmin.setFirstName("Joe"); | ||
168 | - tenantAdmin.setLastName("Downs"); | ||
169 | - | ||
170 | - tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | ||
171 | - | ||
172 | Customer customer = new Customer(); | 138 | Customer customer = new Customer(); |
173 | doPost("/api/customer", customer) | 139 | doPost("/api/customer", customer) |
174 | - .andExpect(status().isBadRequest()) | ||
175 | - .andExpect(statusReason(containsString("Customer title should be specified"))); | ||
176 | - | ||
177 | - loginSysAdmin(); | ||
178 | - | ||
179 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
180 | - .andExpect(status().isOk()); | 140 | + .andExpect(status().isBadRequest()) |
141 | + .andExpect(statusReason(containsString("Customer title should be specified"))); | ||
181 | } | 142 | } |
182 | - | 143 | + |
183 | @Test | 144 | @Test |
184 | public void testSaveCustomerWithInvalidEmail() throws Exception { | 145 | public void testSaveCustomerWithInvalidEmail() throws Exception { |
185 | - | ||
186 | - loginSysAdmin(); | ||
187 | - | ||
188 | - Tenant tenant = new Tenant(); | ||
189 | - tenant.setTitle("My tenant"); | ||
190 | - Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | ||
191 | - Assert.assertNotNull(savedTenant); | ||
192 | - | ||
193 | - User tenantAdmin = new User(); | ||
194 | - tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | ||
195 | - tenantAdmin.setTenantId(savedTenant.getId()); | ||
196 | - tenantAdmin.setEmail("tenant2@thingsboard.org"); | ||
197 | - tenantAdmin.setFirstName("Joe"); | ||
198 | - tenantAdmin.setLastName("Downs"); | ||
199 | - | ||
200 | - tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | ||
201 | - | ||
202 | Customer customer = new Customer(); | 146 | Customer customer = new Customer(); |
203 | customer.setTitle("My customer"); | 147 | customer.setTitle("My customer"); |
204 | customer.setEmail("invalid@mail"); | 148 | customer.setEmail("invalid@mail"); |
205 | doPost("/api/customer", customer) | 149 | doPost("/api/customer", customer) |
206 | - .andExpect(status().isBadRequest()) | ||
207 | - .andExpect(statusReason(containsString("Invalid email address format 'invalid@mail'"))); | ||
208 | - | ||
209 | - loginSysAdmin(); | ||
210 | - | ||
211 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
212 | - .andExpect(status().isOk()); | 150 | + .andExpect(status().isBadRequest()) |
151 | + .andExpect(statusReason(containsString("Invalid email address format 'invalid@mail'"))); | ||
152 | + | ||
153 | +// loginSysAdmin(); | ||
154 | +// | ||
155 | +// doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
156 | +// .andExpect(status().isOk()); | ||
213 | } | 157 | } |
214 | - | 158 | + |
215 | @Test | 159 | @Test |
216 | public void testFindCustomers() throws Exception { | 160 | public void testFindCustomers() throws Exception { |
217 | - loginSysAdmin(); | ||
218 | - | ||
219 | - Tenant tenant = new Tenant(); | ||
220 | - tenant.setTitle("My tenant"); | ||
221 | - Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | ||
222 | - Assert.assertNotNull(savedTenant); | ||
223 | - | ||
224 | TenantId tenantId = savedTenant.getId(); | 161 | TenantId tenantId = savedTenant.getId(); |
225 | - | ||
226 | - User tenantAdmin = new User(); | ||
227 | - tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | ||
228 | - tenantAdmin.setTenantId(tenantId); | ||
229 | - tenantAdmin.setEmail("tenant2@thingsboard.org"); | ||
230 | - tenantAdmin.setFirstName("Joe"); | ||
231 | - tenantAdmin.setLastName("Downs"); | ||
232 | - | ||
233 | - tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | ||
234 | - | 162 | + |
235 | List<Customer> customers = new ArrayList<>(); | 163 | List<Customer> customers = new ArrayList<>(); |
236 | - for (int i=0;i<135;i++) { | 164 | + for (int i = 0; i < 135; i++) { |
237 | Customer customer = new Customer(); | 165 | Customer customer = new Customer(); |
238 | customer.setTenantId(tenantId); | 166 | customer.setTenantId(tenantId); |
239 | - customer.setTitle("Customer"+i); | 167 | + customer.setTitle("Customer" + i); |
240 | customers.add(doPost("/api/customer", customer, Customer.class)); | 168 | customers.add(doPost("/api/customer", customer, Customer.class)); |
241 | } | 169 | } |
242 | - | 170 | + |
243 | List<Customer> loadedCustomers = new ArrayList<>(); | 171 | List<Customer> loadedCustomers = new ArrayList<>(); |
244 | TextPageLink pageLink = new TextPageLink(23); | 172 | TextPageLink pageLink = new TextPageLink(23); |
245 | TextPageData<Customer> pageData = null; | 173 | TextPageData<Customer> pageData = null; |
246 | do { | 174 | do { |
247 | - pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>(){}, pageLink); | 175 | + pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>() { |
176 | + }, pageLink); | ||
248 | loadedCustomers.addAll(pageData.getData()); | 177 | loadedCustomers.addAll(pageData.getData()); |
249 | if (pageData.hasNext()) { | 178 | if (pageData.hasNext()) { |
250 | pageLink = pageData.getNextPageLink(); | 179 | pageLink = pageData.getNextPageLink(); |
251 | } | 180 | } |
252 | } while (pageData.hasNext()); | 181 | } while (pageData.hasNext()); |
253 | - | 182 | + |
254 | Collections.sort(customers, idComparator); | 183 | Collections.sort(customers, idComparator); |
255 | Collections.sort(loadedCustomers, idComparator); | 184 | Collections.sort(loadedCustomers, idComparator); |
256 | - | 185 | + |
257 | Assert.assertEquals(customers, loadedCustomers); | 186 | Assert.assertEquals(customers, loadedCustomers); |
258 | - | ||
259 | - loginSysAdmin(); | ||
260 | - | ||
261 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
262 | - .andExpect(status().isOk()); | ||
263 | } | 187 | } |
264 | - | 188 | + |
265 | @Test | 189 | @Test |
266 | public void testFindCustomersByTitle() throws Exception { | 190 | public void testFindCustomersByTitle() throws Exception { |
267 | - | ||
268 | - loginSysAdmin(); | ||
269 | - | ||
270 | - Tenant tenant = new Tenant(); | ||
271 | - tenant.setTitle("My tenant"); | ||
272 | - Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | ||
273 | - Assert.assertNotNull(savedTenant); | ||
274 | - | ||
275 | TenantId tenantId = savedTenant.getId(); | 191 | TenantId tenantId = savedTenant.getId(); |
276 | - | ||
277 | - User tenantAdmin = new User(); | ||
278 | - tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | ||
279 | - tenantAdmin.setTenantId(tenantId); | ||
280 | - tenantAdmin.setEmail("tenant2@thingsboard.org"); | ||
281 | - tenantAdmin.setFirstName("Joe"); | ||
282 | - tenantAdmin.setLastName("Downs"); | ||
283 | - | ||
284 | - tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | ||
285 | - | 192 | + |
286 | String title1 = "Customer title 1"; | 193 | String title1 = "Customer title 1"; |
287 | List<Customer> customersTitle1 = new ArrayList<>(); | 194 | List<Customer> customersTitle1 = new ArrayList<>(); |
288 | - for (int i=0;i<143;i++) { | 195 | + for (int i = 0; i < 143; i++) { |
289 | Customer customer = new Customer(); | 196 | Customer customer = new Customer(); |
290 | customer.setTenantId(tenantId); | 197 | customer.setTenantId(tenantId); |
291 | - String suffix = RandomStringUtils.randomAlphanumeric((int)(5 + Math.random()*10)); | ||
292 | - String title = title1+suffix; | 198 | + String suffix = RandomStringUtils.randomAlphanumeric((int) (5 + Math.random() * 10)); |
199 | + String title = title1 + suffix; | ||
293 | title = i % 2 == 0 ? title.toLowerCase() : title.toUpperCase(); | 200 | title = i % 2 == 0 ? title.toLowerCase() : title.toUpperCase(); |
294 | customer.setTitle(title); | 201 | customer.setTitle(title); |
295 | customersTitle1.add(doPost("/api/customer", customer, Customer.class)); | 202 | customersTitle1.add(doPost("/api/customer", customer, Customer.class)); |
296 | } | 203 | } |
297 | String title2 = "Customer title 2"; | 204 | String title2 = "Customer title 2"; |
298 | List<Customer> customersTitle2 = new ArrayList<>(); | 205 | List<Customer> customersTitle2 = new ArrayList<>(); |
299 | - for (int i=0;i<175;i++) { | 206 | + for (int i = 0; i < 175; i++) { |
300 | Customer customer = new Customer(); | 207 | Customer customer = new Customer(); |
301 | customer.setTenantId(tenantId); | 208 | customer.setTenantId(tenantId); |
302 | - String suffix = RandomStringUtils.randomAlphanumeric((int)(5 + Math.random()*10)); | ||
303 | - String title = title2+suffix; | 209 | + String suffix = RandomStringUtils.randomAlphanumeric((int) (5 + Math.random() * 10)); |
210 | + String title = title2 + suffix; | ||
304 | title = i % 2 == 0 ? title.toLowerCase() : title.toUpperCase(); | 211 | title = i % 2 == 0 ? title.toLowerCase() : title.toUpperCase(); |
305 | customer.setTitle(title); | 212 | customer.setTitle(title); |
306 | customersTitle2.add(doPost("/api/customer", customer, Customer.class)); | 213 | customersTitle2.add(doPost("/api/customer", customer, Customer.class)); |
307 | } | 214 | } |
308 | - | 215 | + |
309 | List<Customer> loadedCustomersTitle1 = new ArrayList<>(); | 216 | List<Customer> loadedCustomersTitle1 = new ArrayList<>(); |
310 | TextPageLink pageLink = new TextPageLink(15, title1); | 217 | TextPageLink pageLink = new TextPageLink(15, title1); |
311 | TextPageData<Customer> pageData = null; | 218 | TextPageData<Customer> pageData = null; |
312 | do { | 219 | do { |
313 | - pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>(){}, pageLink); | 220 | + pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>() { |
221 | + }, pageLink); | ||
314 | loadedCustomersTitle1.addAll(pageData.getData()); | 222 | loadedCustomersTitle1.addAll(pageData.getData()); |
315 | if (pageData.hasNext()) { | 223 | if (pageData.hasNext()) { |
316 | pageLink = pageData.getNextPageLink(); | 224 | pageLink = pageData.getNextPageLink(); |
317 | } | 225 | } |
318 | } while (pageData.hasNext()); | 226 | } while (pageData.hasNext()); |
319 | - | 227 | + |
320 | Collections.sort(customersTitle1, idComparator); | 228 | Collections.sort(customersTitle1, idComparator); |
321 | Collections.sort(loadedCustomersTitle1, idComparator); | 229 | Collections.sort(loadedCustomersTitle1, idComparator); |
322 | - | 230 | + |
323 | Assert.assertEquals(customersTitle1, loadedCustomersTitle1); | 231 | Assert.assertEquals(customersTitle1, loadedCustomersTitle1); |
324 | - | 232 | + |
325 | List<Customer> loadedCustomersTitle2 = new ArrayList<>(); | 233 | List<Customer> loadedCustomersTitle2 = new ArrayList<>(); |
326 | pageLink = new TextPageLink(4, title2); | 234 | pageLink = new TextPageLink(4, title2); |
327 | do { | 235 | do { |
328 | - pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>(){}, pageLink); | 236 | + pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>() { |
237 | + }, pageLink); | ||
329 | loadedCustomersTitle2.addAll(pageData.getData()); | 238 | loadedCustomersTitle2.addAll(pageData.getData()); |
330 | if (pageData.hasNext()) { | 239 | if (pageData.hasNext()) { |
331 | pageLink = pageData.getNextPageLink(); | 240 | pageLink = pageData.getNextPageLink(); |
@@ -334,33 +243,30 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | @@ -334,33 +243,30 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | ||
334 | 243 | ||
335 | Collections.sort(customersTitle2, idComparator); | 244 | Collections.sort(customersTitle2, idComparator); |
336 | Collections.sort(loadedCustomersTitle2, idComparator); | 245 | Collections.sort(loadedCustomersTitle2, idComparator); |
337 | - | 246 | + |
338 | Assert.assertEquals(customersTitle2, loadedCustomersTitle2); | 247 | Assert.assertEquals(customersTitle2, loadedCustomersTitle2); |
339 | - | 248 | + |
340 | for (Customer customer : loadedCustomersTitle1) { | 249 | for (Customer customer : loadedCustomersTitle1) { |
341 | - doDelete("/api/customer/"+customer.getId().getId().toString()) | ||
342 | - .andExpect(status().isOk()); | 250 | + doDelete("/api/customer/" + customer.getId().getId().toString()) |
251 | + .andExpect(status().isOk()); | ||
343 | } | 252 | } |
344 | - | 253 | + |
345 | pageLink = new TextPageLink(4, title1); | 254 | pageLink = new TextPageLink(4, title1); |
346 | - pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>(){}, pageLink); | 255 | + pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>() { |
256 | + }, pageLink); | ||
347 | Assert.assertFalse(pageData.hasNext()); | 257 | Assert.assertFalse(pageData.hasNext()); |
348 | Assert.assertEquals(0, pageData.getData().size()); | 258 | Assert.assertEquals(0, pageData.getData().size()); |
349 | - | 259 | + |
350 | for (Customer customer : loadedCustomersTitle2) { | 260 | for (Customer customer : loadedCustomersTitle2) { |
351 | - doDelete("/api/customer/"+customer.getId().getId().toString()) | ||
352 | - .andExpect(status().isOk()); | 261 | + doDelete("/api/customer/" + customer.getId().getId().toString()) |
262 | + .andExpect(status().isOk()); | ||
353 | } | 263 | } |
354 | - | 264 | + |
355 | pageLink = new TextPageLink(4, title2); | 265 | pageLink = new TextPageLink(4, title2); |
356 | - pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>(){}, pageLink); | 266 | + pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>() { |
267 | + }, pageLink); | ||
357 | Assert.assertFalse(pageData.hasNext()); | 268 | Assert.assertFalse(pageData.hasNext()); |
358 | Assert.assertEquals(0, pageData.getData().size()); | 269 | Assert.assertEquals(0, pageData.getData().size()); |
359 | - | ||
360 | - loginSysAdmin(); | ||
361 | - | ||
362 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
363 | - .andExpect(status().isOk()); | ||
364 | } | 270 | } |
365 | - | 271 | + |
366 | } | 272 | } |
@@ -16,10 +16,8 @@ | @@ -16,10 +16,8 @@ | ||
16 | package org.thingsboard.server.controller; | 16 | package org.thingsboard.server.controller; |
17 | 17 | ||
18 | import static org.hamcrest.Matchers.containsString; | 18 | import static org.hamcrest.Matchers.containsString; |
19 | -import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; | ||
20 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | 19 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
21 | 20 | ||
22 | -import java.sql.Time; | ||
23 | import java.util.ArrayList; | 21 | import java.util.ArrayList; |
24 | import java.util.Collections; | 22 | import java.util.Collections; |
25 | import java.util.List; | 23 | import java.util.List; |
@@ -33,7 +31,6 @@ import org.thingsboard.server.common.data.page.TextPageLink; | @@ -33,7 +31,6 @@ import org.thingsboard.server.common.data.page.TextPageLink; | ||
33 | import org.thingsboard.server.common.data.page.TimePageData; | 31 | import org.thingsboard.server.common.data.page.TimePageData; |
34 | import org.thingsboard.server.common.data.page.TimePageLink; | 32 | import org.thingsboard.server.common.data.page.TimePageLink; |
35 | import org.thingsboard.server.common.data.security.Authority; | 33 | import org.thingsboard.server.common.data.security.Authority; |
36 | -import org.thingsboard.server.dao.model.ModelConstants; | ||
37 | import org.junit.After; | 34 | import org.junit.After; |
38 | import org.junit.Assert; | 35 | import org.junit.Assert; |
39 | import org.junit.Before; | 36 | import org.junit.Before; |
@@ -93,6 +90,17 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | @@ -93,6 +90,17 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | ||
93 | Dashboard foundDashboard = doGet("/api/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); | 90 | Dashboard foundDashboard = doGet("/api/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class); |
94 | Assert.assertEquals(foundDashboard.getTitle(), savedDashboard.getTitle()); | 91 | Assert.assertEquals(foundDashboard.getTitle(), savedDashboard.getTitle()); |
95 | } | 92 | } |
93 | + | ||
94 | + @Test | ||
95 | + public void testUpdateDashboardFromDifferentTenant() throws Exception { | ||
96 | + Dashboard dashboard = new Dashboard(); | ||
97 | + dashboard.setTitle("My dashboard"); | ||
98 | + Dashboard savedDashboard = doPost("/api/dashboard", dashboard, Dashboard.class); | ||
99 | + | ||
100 | + loginDifferentTenant(); | ||
101 | + doPost("/api/dashboard", savedDashboard, Dashboard.class, status().isForbidden()); | ||
102 | + deleteDifferentTenant(); | ||
103 | + } | ||
96 | 104 | ||
97 | @Test | 105 | @Test |
98 | public void testFindDashboardById() throws Exception { | 106 | public void testFindDashboardById() throws Exception { |
@@ -107,6 +107,17 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -107,6 +107,17 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
107 | Device foundDevice = doGet("/api/device/" + savedDevice.getId().getId().toString(), Device.class); | 107 | Device foundDevice = doGet("/api/device/" + savedDevice.getId().getId().toString(), Device.class); |
108 | Assert.assertEquals(foundDevice.getName(), savedDevice.getName()); | 108 | Assert.assertEquals(foundDevice.getName(), savedDevice.getName()); |
109 | } | 109 | } |
110 | + | ||
111 | + @Test | ||
112 | + public void testUpdateDeviceFromDifferentTenant() throws Exception { | ||
113 | + Device device = new Device(); | ||
114 | + device.setName("My device"); | ||
115 | + device.setType("default"); | ||
116 | + Device savedDevice = doPost("/api/device", device, Device.class); | ||
117 | + loginDifferentTenant(); | ||
118 | + doPost("/api/device", savedDevice, Device.class, status().isForbidden()); | ||
119 | + deleteDifferentTenant(); | ||
120 | + } | ||
110 | 121 | ||
111 | @Test | 122 | @Test |
112 | public void testFindDeviceById() throws Exception { | 123 | public void testFindDeviceById() throws Exception { |
@@ -25,7 +25,6 @@ import org.eclipse.paho.client.mqttv3.MqttMessage; | @@ -25,7 +25,6 @@ import org.eclipse.paho.client.mqttv3.MqttMessage; | ||
25 | import org.junit.After; | 25 | import org.junit.After; |
26 | import org.junit.Assert; | 26 | import org.junit.Assert; |
27 | import org.junit.Before; | 27 | import org.junit.Before; |
28 | -import org.junit.Ignore; | ||
29 | import org.junit.Test; | 28 | import org.junit.Test; |
30 | import org.thingsboard.server.common.data.Customer; | 29 | import org.thingsboard.server.common.data.Customer; |
31 | import org.thingsboard.server.common.data.Device; | 30 | import org.thingsboard.server.common.data.Device; |
@@ -132,6 +131,15 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | @@ -132,6 +131,15 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | ||
132 | assertEquals(foundEntityView.getKeys(), telemetry); | 131 | assertEquals(foundEntityView.getKeys(), telemetry); |
133 | } | 132 | } |
134 | 133 | ||
134 | + | ||
135 | + @Test | ||
136 | + public void testUpdateEntityViewFromDifferentTenant() throws Exception { | ||
137 | + EntityView savedView = getNewSavedEntityView("Test entity view"); | ||
138 | + loginDifferentTenant(); | ||
139 | + doPost("/api/entityView", savedView, EntityView.class, status().isForbidden()); | ||
140 | + deleteDifferentTenant(); | ||
141 | + } | ||
142 | + | ||
135 | @Test | 143 | @Test |
136 | public void testDeleteEntityView() throws Exception { | 144 | public void testDeleteEntityView() throws Exception { |
137 | EntityView view = getNewSavedEntityView("Test entity view"); | 145 | EntityView view = getNewSavedEntityView("Test entity view"); |
@@ -38,21 +38,23 @@ import java.util.List; | @@ -38,21 +38,23 @@ import java.util.List; | ||
38 | 38 | ||
39 | import static org.hamcrest.Matchers.containsString; | 39 | import static org.hamcrest.Matchers.containsString; |
40 | import static org.hamcrest.Matchers.is; | 40 | import static org.hamcrest.Matchers.is; |
41 | -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | 41 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; |
42 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; | ||
43 | +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
42 | 44 | ||
43 | public abstract class BaseUserControllerTest extends AbstractControllerTest { | 45 | public abstract class BaseUserControllerTest extends AbstractControllerTest { |
44 | - | 46 | + |
45 | private IdComparator<User> idComparator = new IdComparator<>(); | 47 | private IdComparator<User> idComparator = new IdComparator<>(); |
46 | 48 | ||
47 | @Test | 49 | @Test |
48 | public void testSaveUser() throws Exception { | 50 | public void testSaveUser() throws Exception { |
49 | loginSysAdmin(); | 51 | loginSysAdmin(); |
50 | - | 52 | + |
51 | Tenant tenant = new Tenant(); | 53 | Tenant tenant = new Tenant(); |
52 | tenant.setTitle("My tenant"); | 54 | tenant.setTitle("My tenant"); |
53 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 55 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
54 | Assert.assertNotNull(savedTenant); | 56 | Assert.assertNotNull(savedTenant); |
55 | - | 57 | + |
56 | String email = "tenant2@thingsboard.org"; | 58 | String email = "tenant2@thingsboard.org"; |
57 | User user = new User(); | 59 | User user = new User(); |
58 | user.setAuthority(Authority.TENANT_ADMIN); | 60 | user.setAuthority(Authority.TENANT_ADMIN); |
@@ -66,13 +68,13 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -66,13 +68,13 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
66 | Assert.assertTrue(savedUser.getCreatedTime() > 0); | 68 | Assert.assertTrue(savedUser.getCreatedTime() > 0); |
67 | Assert.assertEquals(user.getEmail(), savedUser.getEmail()); | 69 | Assert.assertEquals(user.getEmail(), savedUser.getEmail()); |
68 | 70 | ||
69 | - User foundUser = doGet("/api/user/"+savedUser.getId().getId().toString(), User.class); | 71 | + User foundUser = doGet("/api/user/" + savedUser.getId().getId().toString(), User.class); |
70 | Assert.assertEquals(foundUser, savedUser); | 72 | Assert.assertEquals(foundUser, savedUser); |
71 | - | 73 | + |
72 | logout(); | 74 | logout(); |
73 | doGet("/api/noauth/activate?activateToken={activateToken}", TestMailService.currentActivateToken) | 75 | doGet("/api/noauth/activate?activateToken={activateToken}", TestMailService.currentActivateToken) |
74 | - .andExpect(status().isSeeOther()) | ||
75 | - .andExpect(header().string(HttpHeaders.LOCATION, "/login/createPassword?activateToken=" + TestMailService.currentActivateToken)); | 76 | + .andExpect(status().isSeeOther()) |
77 | + .andExpect(header().string(HttpHeaders.LOCATION, "/login/createPassword?activateToken=" + TestMailService.currentActivateToken)); | ||
76 | 78 | ||
77 | JsonNode activateRequest = new ObjectMapper().createObjectNode() | 79 | JsonNode activateRequest = new ObjectMapper().createObjectNode() |
78 | .put("activateToken", TestMailService.currentActivateToken) | 80 | .put("activateToken", TestMailService.currentActivateToken) |
@@ -82,36 +84,61 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -82,36 +84,61 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
82 | validateAndSetJwtToken(tokenInfo, email); | 84 | validateAndSetJwtToken(tokenInfo, email); |
83 | 85 | ||
84 | doGet("/api/auth/user") | 86 | doGet("/api/auth/user") |
85 | - .andExpect(status().isOk()) | ||
86 | - .andExpect(jsonPath("$.authority",is(Authority.TENANT_ADMIN.name()))) | ||
87 | - .andExpect(jsonPath("$.email",is(email))); | ||
88 | - | 87 | + .andExpect(status().isOk()) |
88 | + .andExpect(jsonPath("$.authority", is(Authority.TENANT_ADMIN.name()))) | ||
89 | + .andExpect(jsonPath("$.email", is(email))); | ||
90 | + | ||
89 | logout(); | 91 | logout(); |
90 | - | 92 | + |
91 | login(email, "testPassword"); | 93 | login(email, "testPassword"); |
92 | - | 94 | + |
93 | doGet("/api/auth/user") | 95 | doGet("/api/auth/user") |
94 | - .andExpect(status().isOk()) | ||
95 | - .andExpect(jsonPath("$.authority",is(Authority.TENANT_ADMIN.name()))) | ||
96 | - .andExpect(jsonPath("$.email",is(email))); | ||
97 | - | 96 | + .andExpect(status().isOk()) |
97 | + .andExpect(jsonPath("$.authority", is(Authority.TENANT_ADMIN.name()))) | ||
98 | + .andExpect(jsonPath("$.email", is(email))); | ||
99 | + | ||
98 | loginSysAdmin(); | 100 | loginSysAdmin(); |
99 | - doDelete("/api/user/"+savedUser.getId().getId().toString()) | ||
100 | - .andExpect(status().isOk()); | ||
101 | - | ||
102 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
103 | - .andExpect(status().isOk()); | 101 | + doDelete("/api/user/" + savedUser.getId().getId().toString()) |
102 | + .andExpect(status().isOk()); | ||
103 | + | ||
104 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
105 | + .andExpect(status().isOk()); | ||
104 | } | 106 | } |
105 | - | 107 | + |
108 | + @Test | ||
109 | + public void testUpdateUserFromDifferentTenant() throws Exception { | ||
110 | + loginSysAdmin(); | ||
111 | + Tenant tenant = new Tenant(); | ||
112 | + tenant.setTitle("My tenant"); | ||
113 | + Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | ||
114 | + Assert.assertNotNull(savedTenant); | ||
115 | + | ||
116 | + User tenantAdmin = new User(); | ||
117 | + tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | ||
118 | + tenantAdmin.setTenantId(savedTenant.getId()); | ||
119 | + tenantAdmin.setEmail("tenant2@thingsboard.org"); | ||
120 | + tenantAdmin.setFirstName("Joe"); | ||
121 | + tenantAdmin.setLastName("Downs"); | ||
122 | + tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | ||
123 | + | ||
124 | + loginDifferentTenant(); | ||
125 | + doPost("/api/user", tenantAdmin, User.class, status().isForbidden()); | ||
126 | + deleteDifferentTenant(); | ||
127 | + | ||
128 | + loginSysAdmin(); | ||
129 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
130 | + .andExpect(status().isOk()); | ||
131 | + } | ||
132 | + | ||
106 | @Test | 133 | @Test |
107 | public void testResetPassword() throws Exception { | 134 | public void testResetPassword() throws Exception { |
108 | loginSysAdmin(); | 135 | loginSysAdmin(); |
109 | - | 136 | + |
110 | Tenant tenant = new Tenant(); | 137 | Tenant tenant = new Tenant(); |
111 | tenant.setTitle("My tenant"); | 138 | tenant.setTitle("My tenant"); |
112 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 139 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
113 | Assert.assertNotNull(savedTenant); | 140 | Assert.assertNotNull(savedTenant); |
114 | - | 141 | + |
115 | String email = "tenant2@thingsboard.org"; | 142 | String email = "tenant2@thingsboard.org"; |
116 | User user = new User(); | 143 | User user = new User(); |
117 | user.setAuthority(Authority.TENANT_ADMIN); | 144 | user.setAuthority(Authority.TENANT_ADMIN); |
@@ -119,7 +146,7 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -119,7 +146,7 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
119 | user.setEmail(email); | 146 | user.setEmail(email); |
120 | user.setFirstName("Joe"); | 147 | user.setFirstName("Joe"); |
121 | user.setLastName("Downs"); | 148 | user.setLastName("Downs"); |
122 | - | 149 | + |
123 | User savedUser = createUserAndLogin(user, "testPassword1"); | 150 | User savedUser = createUserAndLogin(user, "testPassword1"); |
124 | logout(); | 151 | logout(); |
125 | 152 | ||
@@ -127,10 +154,10 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -127,10 +154,10 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
127 | .put("email", email); | 154 | .put("email", email); |
128 | 155 | ||
129 | doPost("/api/noauth/resetPasswordByEmail", resetPasswordByEmailRequest) | 156 | doPost("/api/noauth/resetPasswordByEmail", resetPasswordByEmailRequest) |
130 | - .andExpect(status().isOk()); | 157 | + .andExpect(status().isOk()); |
131 | doGet("/api/noauth/resetPassword?resetToken={resetToken}", TestMailService.currentResetPasswordToken) | 158 | doGet("/api/noauth/resetPassword?resetToken={resetToken}", TestMailService.currentResetPasswordToken) |
132 | - .andExpect(status().isSeeOther()) | ||
133 | - .andExpect(header().string(HttpHeaders.LOCATION, "/login/resetPassword?resetToken=" + TestMailService.currentResetPasswordToken)); | 159 | + .andExpect(status().isSeeOther()) |
160 | + .andExpect(header().string(HttpHeaders.LOCATION, "/login/resetPassword?resetToken=" + TestMailService.currentResetPasswordToken)); | ||
134 | 161 | ||
135 | JsonNode resetPasswordRequest = new ObjectMapper().createObjectNode() | 162 | JsonNode resetPasswordRequest = new ObjectMapper().createObjectNode() |
136 | .put("resetToken", TestMailService.currentResetPasswordToken) | 163 | .put("resetToken", TestMailService.currentResetPasswordToken) |
@@ -140,35 +167,35 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -140,35 +167,35 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
140 | validateAndSetJwtToken(tokenInfo, email); | 167 | validateAndSetJwtToken(tokenInfo, email); |
141 | 168 | ||
142 | doGet("/api/auth/user") | 169 | doGet("/api/auth/user") |
143 | - .andExpect(status().isOk()) | ||
144 | - .andExpect(jsonPath("$.authority",is(Authority.TENANT_ADMIN.name()))) | ||
145 | - .andExpect(jsonPath("$.email",is(email))); | ||
146 | - | 170 | + .andExpect(status().isOk()) |
171 | + .andExpect(jsonPath("$.authority", is(Authority.TENANT_ADMIN.name()))) | ||
172 | + .andExpect(jsonPath("$.email", is(email))); | ||
173 | + | ||
147 | logout(); | 174 | logout(); |
148 | - | 175 | + |
149 | login(email, "testPassword2"); | 176 | login(email, "testPassword2"); |
150 | doGet("/api/auth/user") | 177 | doGet("/api/auth/user") |
151 | - .andExpect(status().isOk()) | ||
152 | - .andExpect(jsonPath("$.authority",is(Authority.TENANT_ADMIN.name()))) | ||
153 | - .andExpect(jsonPath("$.email",is(email))); | ||
154 | - | 178 | + .andExpect(status().isOk()) |
179 | + .andExpect(jsonPath("$.authority", is(Authority.TENANT_ADMIN.name()))) | ||
180 | + .andExpect(jsonPath("$.email", is(email))); | ||
181 | + | ||
155 | loginSysAdmin(); | 182 | loginSysAdmin(); |
156 | - doDelete("/api/user/"+savedUser.getId().getId().toString()) | ||
157 | - .andExpect(status().isOk()); | ||
158 | - | ||
159 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
160 | - .andExpect(status().isOk()); | 183 | + doDelete("/api/user/" + savedUser.getId().getId().toString()) |
184 | + .andExpect(status().isOk()); | ||
185 | + | ||
186 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
187 | + .andExpect(status().isOk()); | ||
161 | } | 188 | } |
162 | - | 189 | + |
163 | @Test | 190 | @Test |
164 | public void testFindUserById() throws Exception { | 191 | public void testFindUserById() throws Exception { |
165 | loginSysAdmin(); | 192 | loginSysAdmin(); |
166 | - | 193 | + |
167 | Tenant tenant = new Tenant(); | 194 | Tenant tenant = new Tenant(); |
168 | tenant.setTitle("My tenant"); | 195 | tenant.setTitle("My tenant"); |
169 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 196 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
170 | Assert.assertNotNull(savedTenant); | 197 | Assert.assertNotNull(savedTenant); |
171 | - | 198 | + |
172 | String email = "tenant2@thingsboard.org"; | 199 | String email = "tenant2@thingsboard.org"; |
173 | User user = new User(); | 200 | User user = new User(); |
174 | user.setAuthority(Authority.TENANT_ADMIN); | 201 | user.setAuthority(Authority.TENANT_ADMIN); |
@@ -176,25 +203,25 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -176,25 +203,25 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
176 | user.setEmail(email); | 203 | user.setEmail(email); |
177 | user.setFirstName("Joe"); | 204 | user.setFirstName("Joe"); |
178 | user.setLastName("Downs"); | 205 | user.setLastName("Downs"); |
179 | - | 206 | + |
180 | User savedUser = doPost("/api/user", user, User.class); | 207 | User savedUser = doPost("/api/user", user, User.class); |
181 | - User foundUser = doGet("/api/user/"+savedUser.getId().getId().toString(), User.class); | 208 | + User foundUser = doGet("/api/user/" + savedUser.getId().getId().toString(), User.class); |
182 | Assert.assertNotNull(foundUser); | 209 | Assert.assertNotNull(foundUser); |
183 | Assert.assertEquals(savedUser, foundUser); | 210 | Assert.assertEquals(savedUser, foundUser); |
184 | - | ||
185 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
186 | - .andExpect(status().isOk()); | 211 | + |
212 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
213 | + .andExpect(status().isOk()); | ||
187 | } | 214 | } |
188 | - | 215 | + |
189 | @Test | 216 | @Test |
190 | public void testSaveUserWithSameEmail() throws Exception { | 217 | public void testSaveUserWithSameEmail() throws Exception { |
191 | loginSysAdmin(); | 218 | loginSysAdmin(); |
192 | - | 219 | + |
193 | Tenant tenant = new Tenant(); | 220 | Tenant tenant = new Tenant(); |
194 | tenant.setTitle("My tenant"); | 221 | tenant.setTitle("My tenant"); |
195 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 222 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
196 | Assert.assertNotNull(savedTenant); | 223 | Assert.assertNotNull(savedTenant); |
197 | - | 224 | + |
198 | String email = TENANT_ADMIN_EMAIL; | 225 | String email = TENANT_ADMIN_EMAIL; |
199 | User user = new User(); | 226 | User user = new User(); |
200 | user.setAuthority(Authority.TENANT_ADMIN); | 227 | user.setAuthority(Authority.TENANT_ADMIN); |
@@ -202,24 +229,24 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -202,24 +229,24 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
202 | user.setEmail(email); | 229 | user.setEmail(email); |
203 | user.setFirstName("Joe"); | 230 | user.setFirstName("Joe"); |
204 | user.setLastName("Downs"); | 231 | user.setLastName("Downs"); |
205 | - | 232 | + |
206 | doPost("/api/user", user) | 233 | doPost("/api/user", user) |
207 | - .andExpect(status().isBadRequest()) | ||
208 | - .andExpect(statusReason(containsString("User with email '" + email + "' already present in database"))); | ||
209 | - | ||
210 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
211 | - .andExpect(status().isOk()); | 234 | + .andExpect(status().isBadRequest()) |
235 | + .andExpect(statusReason(containsString("User with email '" + email + "' already present in database"))); | ||
236 | + | ||
237 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
238 | + .andExpect(status().isOk()); | ||
212 | } | 239 | } |
213 | - | 240 | + |
214 | @Test | 241 | @Test |
215 | public void testSaveUserWithInvalidEmail() throws Exception { | 242 | public void testSaveUserWithInvalidEmail() throws Exception { |
216 | loginSysAdmin(); | 243 | loginSysAdmin(); |
217 | - | 244 | + |
218 | Tenant tenant = new Tenant(); | 245 | Tenant tenant = new Tenant(); |
219 | tenant.setTitle("My tenant"); | 246 | tenant.setTitle("My tenant"); |
220 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 247 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
221 | Assert.assertNotNull(savedTenant); | 248 | Assert.assertNotNull(savedTenant); |
222 | - | 249 | + |
223 | String email = "tenant_thingsboard.org"; | 250 | String email = "tenant_thingsboard.org"; |
224 | User user = new User(); | 251 | User user = new User(); |
225 | user.setAuthority(Authority.TENANT_ADMIN); | 252 | user.setAuthority(Authority.TENANT_ADMIN); |
@@ -227,62 +254,62 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -227,62 +254,62 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
227 | user.setEmail(email); | 254 | user.setEmail(email); |
228 | user.setFirstName("Joe"); | 255 | user.setFirstName("Joe"); |
229 | user.setLastName("Downs"); | 256 | user.setLastName("Downs"); |
230 | - | 257 | + |
231 | doPost("/api/user", user) | 258 | doPost("/api/user", user) |
232 | - .andExpect(status().isBadRequest()) | ||
233 | - .andExpect(statusReason(containsString("Invalid email address format '" + email + "'"))); | ||
234 | - | ||
235 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
236 | - .andExpect(status().isOk()); | 259 | + .andExpect(status().isBadRequest()) |
260 | + .andExpect(statusReason(containsString("Invalid email address format '" + email + "'"))); | ||
261 | + | ||
262 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
263 | + .andExpect(status().isOk()); | ||
237 | } | 264 | } |
238 | - | 265 | + |
239 | @Test | 266 | @Test |
240 | public void testSaveUserWithEmptyEmail() throws Exception { | 267 | public void testSaveUserWithEmptyEmail() throws Exception { |
241 | loginSysAdmin(); | 268 | loginSysAdmin(); |
242 | - | 269 | + |
243 | Tenant tenant = new Tenant(); | 270 | Tenant tenant = new Tenant(); |
244 | tenant.setTitle("My tenant"); | 271 | tenant.setTitle("My tenant"); |
245 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 272 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
246 | Assert.assertNotNull(savedTenant); | 273 | Assert.assertNotNull(savedTenant); |
247 | - | 274 | + |
248 | User user = new User(); | 275 | User user = new User(); |
249 | user.setAuthority(Authority.TENANT_ADMIN); | 276 | user.setAuthority(Authority.TENANT_ADMIN); |
250 | user.setTenantId(savedTenant.getId()); | 277 | user.setTenantId(savedTenant.getId()); |
251 | user.setFirstName("Joe"); | 278 | user.setFirstName("Joe"); |
252 | user.setLastName("Downs"); | 279 | user.setLastName("Downs"); |
253 | - | 280 | + |
254 | doPost("/api/user", user) | 281 | doPost("/api/user", user) |
255 | - .andExpect(status().isBadRequest()) | ||
256 | - .andExpect(statusReason(containsString("User email should be specified"))); | ||
257 | - | ||
258 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
259 | - .andExpect(status().isOk()); | 282 | + .andExpect(status().isBadRequest()) |
283 | + .andExpect(statusReason(containsString("User email should be specified"))); | ||
284 | + | ||
285 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
286 | + .andExpect(status().isOk()); | ||
260 | } | 287 | } |
261 | - | 288 | + |
262 | @Test | 289 | @Test |
263 | public void testSaveUserWithoutTenant() throws Exception { | 290 | public void testSaveUserWithoutTenant() throws Exception { |
264 | loginSysAdmin(); | 291 | loginSysAdmin(); |
265 | - | 292 | + |
266 | User user = new User(); | 293 | User user = new User(); |
267 | user.setAuthority(Authority.TENANT_ADMIN); | 294 | user.setAuthority(Authority.TENANT_ADMIN); |
268 | user.setEmail("tenant2@thingsboard.org"); | 295 | user.setEmail("tenant2@thingsboard.org"); |
269 | user.setFirstName("Joe"); | 296 | user.setFirstName("Joe"); |
270 | user.setLastName("Downs"); | 297 | user.setLastName("Downs"); |
271 | - | 298 | + |
272 | doPost("/api/user", user) | 299 | doPost("/api/user", user) |
273 | - .andExpect(status().isBadRequest()) | ||
274 | - .andExpect(statusReason(containsString("Tenant administrator should be assigned to tenant"))); | 300 | + .andExpect(status().isBadRequest()) |
301 | + .andExpect(statusReason(containsString("Tenant administrator should be assigned to tenant"))); | ||
275 | } | 302 | } |
276 | - | 303 | + |
277 | @Test | 304 | @Test |
278 | public void testDeleteUser() throws Exception { | 305 | public void testDeleteUser() throws Exception { |
279 | loginSysAdmin(); | 306 | loginSysAdmin(); |
280 | - | 307 | + |
281 | Tenant tenant = new Tenant(); | 308 | Tenant tenant = new Tenant(); |
282 | tenant.setTitle("My tenant"); | 309 | tenant.setTitle("My tenant"); |
283 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 310 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
284 | Assert.assertNotNull(savedTenant); | 311 | Assert.assertNotNull(savedTenant); |
285 | - | 312 | + |
286 | String email = "tenant2@thingsboard.org"; | 313 | String email = "tenant2@thingsboard.org"; |
287 | User user = new User(); | 314 | User user = new User(); |
288 | user.setAuthority(Authority.TENANT_ADMIN); | 315 | user.setAuthority(Authority.TENANT_ADMIN); |
@@ -290,176 +317,182 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -290,176 +317,182 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
290 | user.setEmail(email); | 317 | user.setEmail(email); |
291 | user.setFirstName("Joe"); | 318 | user.setFirstName("Joe"); |
292 | user.setLastName("Downs"); | 319 | user.setLastName("Downs"); |
293 | - | 320 | + |
294 | User savedUser = doPost("/api/user", user, User.class); | 321 | User savedUser = doPost("/api/user", user, User.class); |
295 | - User foundUser = doGet("/api/user/"+savedUser.getId().getId().toString(), User.class); | 322 | + User foundUser = doGet("/api/user/" + savedUser.getId().getId().toString(), User.class); |
296 | Assert.assertNotNull(foundUser); | 323 | Assert.assertNotNull(foundUser); |
297 | - | ||
298 | - doDelete("/api/user/"+savedUser.getId().getId().toString()) | ||
299 | - .andExpect(status().isOk()); | ||
300 | - | ||
301 | - doGet("/api/user/"+savedUser.getId().getId().toString()) | ||
302 | - .andExpect(status().isNotFound()); | ||
303 | - | ||
304 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
305 | - .andExpect(status().isOk()); | 324 | + |
325 | + doDelete("/api/user/" + savedUser.getId().getId().toString()) | ||
326 | + .andExpect(status().isOk()); | ||
327 | + | ||
328 | + doGet("/api/user/" + savedUser.getId().getId().toString()) | ||
329 | + .andExpect(status().isNotFound()); | ||
330 | + | ||
331 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
332 | + .andExpect(status().isOk()); | ||
306 | } | 333 | } |
307 | - | 334 | + |
308 | @Test | 335 | @Test |
309 | public void testFindTenantAdmins() throws Exception { | 336 | public void testFindTenantAdmins() throws Exception { |
310 | loginSysAdmin(); | 337 | loginSysAdmin(); |
311 | - | 338 | + |
312 | Tenant tenant = new Tenant(); | 339 | Tenant tenant = new Tenant(); |
313 | tenant.setTitle("My tenant"); | 340 | tenant.setTitle("My tenant"); |
314 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 341 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
315 | Assert.assertNotNull(savedTenant); | 342 | Assert.assertNotNull(savedTenant); |
316 | - | 343 | + |
317 | TenantId tenantId = savedTenant.getId(); | 344 | TenantId tenantId = savedTenant.getId(); |
318 | - | 345 | + |
319 | List<User> tenantAdmins = new ArrayList<>(); | 346 | List<User> tenantAdmins = new ArrayList<>(); |
320 | - for (int i=0;i<64;i++) { | 347 | + for (int i = 0; i < 64; i++) { |
321 | User user = new User(); | 348 | User user = new User(); |
322 | user.setAuthority(Authority.TENANT_ADMIN); | 349 | user.setAuthority(Authority.TENANT_ADMIN); |
323 | user.setTenantId(tenantId); | 350 | user.setTenantId(tenantId); |
324 | user.setEmail("testTenant" + i + "@thingsboard.org"); | 351 | user.setEmail("testTenant" + i + "@thingsboard.org"); |
325 | tenantAdmins.add(doPost("/api/user", user, User.class)); | 352 | tenantAdmins.add(doPost("/api/user", user, User.class)); |
326 | } | 353 | } |
327 | - | 354 | + |
328 | List<User> loadedTenantAdmins = new ArrayList<>(); | 355 | List<User> loadedTenantAdmins = new ArrayList<>(); |
329 | TextPageLink pageLink = new TextPageLink(33); | 356 | TextPageLink pageLink = new TextPageLink(33); |
330 | TextPageData<User> pageData = null; | 357 | TextPageData<User> pageData = null; |
331 | do { | 358 | do { |
332 | - pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | ||
333 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 359 | + pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
360 | + new TypeReference<TextPageData<User>>() { | ||
361 | + }, pageLink); | ||
334 | loadedTenantAdmins.addAll(pageData.getData()); | 362 | loadedTenantAdmins.addAll(pageData.getData()); |
335 | if (pageData.hasNext()) { | 363 | if (pageData.hasNext()) { |
336 | pageLink = pageData.getNextPageLink(); | 364 | pageLink = pageData.getNextPageLink(); |
337 | } | 365 | } |
338 | } while (pageData.hasNext()); | 366 | } while (pageData.hasNext()); |
339 | - | 367 | + |
340 | Collections.sort(tenantAdmins, idComparator); | 368 | Collections.sort(tenantAdmins, idComparator); |
341 | Collections.sort(loadedTenantAdmins, idComparator); | 369 | Collections.sort(loadedTenantAdmins, idComparator); |
342 | - | 370 | + |
343 | Assert.assertEquals(tenantAdmins, loadedTenantAdmins); | 371 | Assert.assertEquals(tenantAdmins, loadedTenantAdmins); |
344 | - | ||
345 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
346 | - .andExpect(status().isOk()); | ||
347 | - | 372 | + |
373 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
374 | + .andExpect(status().isOk()); | ||
375 | + | ||
348 | pageLink = new TextPageLink(33); | 376 | pageLink = new TextPageLink(33); |
349 | - pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | ||
350 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 377 | + pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
378 | + new TypeReference<TextPageData<User>>() { | ||
379 | + }, pageLink); | ||
351 | Assert.assertFalse(pageData.hasNext()); | 380 | Assert.assertFalse(pageData.hasNext()); |
352 | Assert.assertTrue(pageData.getData().isEmpty()); | 381 | Assert.assertTrue(pageData.getData().isEmpty()); |
353 | } | 382 | } |
354 | - | 383 | + |
355 | @Test | 384 | @Test |
356 | public void testFindTenantAdminsByEmail() throws Exception { | 385 | public void testFindTenantAdminsByEmail() throws Exception { |
357 | - | 386 | + |
358 | loginSysAdmin(); | 387 | loginSysAdmin(); |
359 | - | 388 | + |
360 | Tenant tenant = new Tenant(); | 389 | Tenant tenant = new Tenant(); |
361 | tenant.setTitle("My tenant"); | 390 | tenant.setTitle("My tenant"); |
362 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 391 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
363 | Assert.assertNotNull(savedTenant); | 392 | Assert.assertNotNull(savedTenant); |
364 | - | 393 | + |
365 | TenantId tenantId = savedTenant.getId(); | 394 | TenantId tenantId = savedTenant.getId(); |
366 | - | ||
367 | - String email1 = "testEmail1"; | 395 | + |
396 | + String email1 = "testEmail1"; | ||
368 | List<User> tenantAdminsEmail1 = new ArrayList<>(); | 397 | List<User> tenantAdminsEmail1 = new ArrayList<>(); |
369 | - | ||
370 | - for (int i=0;i<124;i++) { | 398 | + |
399 | + for (int i = 0; i < 124; i++) { | ||
371 | User user = new User(); | 400 | User user = new User(); |
372 | user.setAuthority(Authority.TENANT_ADMIN); | 401 | user.setAuthority(Authority.TENANT_ADMIN); |
373 | user.setTenantId(tenantId); | 402 | user.setTenantId(tenantId); |
374 | - String suffix = RandomStringUtils.randomAlphanumeric((int)(5 + Math.random()*10)); | ||
375 | - String email = email1+suffix+ "@thingsboard.org"; | 403 | + String suffix = RandomStringUtils.randomAlphanumeric((int) (5 + Math.random() * 10)); |
404 | + String email = email1 + suffix + "@thingsboard.org"; | ||
376 | email = i % 2 == 0 ? email.toLowerCase() : email.toUpperCase(); | 405 | email = i % 2 == 0 ? email.toLowerCase() : email.toUpperCase(); |
377 | user.setEmail(email); | 406 | user.setEmail(email); |
378 | tenantAdminsEmail1.add(doPost("/api/user", user, User.class)); | 407 | tenantAdminsEmail1.add(doPost("/api/user", user, User.class)); |
379 | } | 408 | } |
380 | - | ||
381 | - String email2 = "testEmail2"; | 409 | + |
410 | + String email2 = "testEmail2"; | ||
382 | List<User> tenantAdminsEmail2 = new ArrayList<>(); | 411 | List<User> tenantAdminsEmail2 = new ArrayList<>(); |
383 | - | ||
384 | - for (int i=0;i<112;i++) { | 412 | + |
413 | + for (int i = 0; i < 112; i++) { | ||
385 | User user = new User(); | 414 | User user = new User(); |
386 | user.setAuthority(Authority.TENANT_ADMIN); | 415 | user.setAuthority(Authority.TENANT_ADMIN); |
387 | user.setTenantId(tenantId); | 416 | user.setTenantId(tenantId); |
388 | - String suffix = RandomStringUtils.randomAlphanumeric((int)(5 + Math.random()*10)); | ||
389 | - String email = email2+suffix+ "@thingsboard.org"; | 417 | + String suffix = RandomStringUtils.randomAlphanumeric((int) (5 + Math.random() * 10)); |
418 | + String email = email2 + suffix + "@thingsboard.org"; | ||
390 | email = i % 2 == 0 ? email.toLowerCase() : email.toUpperCase(); | 419 | email = i % 2 == 0 ? email.toLowerCase() : email.toUpperCase(); |
391 | user.setEmail(email); | 420 | user.setEmail(email); |
392 | tenantAdminsEmail2.add(doPost("/api/user", user, User.class)); | 421 | tenantAdminsEmail2.add(doPost("/api/user", user, User.class)); |
393 | } | 422 | } |
394 | - | 423 | + |
395 | List<User> loadedTenantAdminsEmail1 = new ArrayList<>(); | 424 | List<User> loadedTenantAdminsEmail1 = new ArrayList<>(); |
396 | TextPageLink pageLink = new TextPageLink(33, email1); | 425 | TextPageLink pageLink = new TextPageLink(33, email1); |
397 | TextPageData<User> pageData = null; | 426 | TextPageData<User> pageData = null; |
398 | do { | 427 | do { |
399 | - pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | ||
400 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 428 | + pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
429 | + new TypeReference<TextPageData<User>>() { | ||
430 | + }, pageLink); | ||
401 | loadedTenantAdminsEmail1.addAll(pageData.getData()); | 431 | loadedTenantAdminsEmail1.addAll(pageData.getData()); |
402 | if (pageData.hasNext()) { | 432 | if (pageData.hasNext()) { |
403 | pageLink = pageData.getNextPageLink(); | 433 | pageLink = pageData.getNextPageLink(); |
404 | } | 434 | } |
405 | } while (pageData.hasNext()); | 435 | } while (pageData.hasNext()); |
406 | - | 436 | + |
407 | Collections.sort(tenantAdminsEmail1, idComparator); | 437 | Collections.sort(tenantAdminsEmail1, idComparator); |
408 | Collections.sort(loadedTenantAdminsEmail1, idComparator); | 438 | Collections.sort(loadedTenantAdminsEmail1, idComparator); |
409 | - | 439 | + |
410 | Assert.assertEquals(tenantAdminsEmail1, loadedTenantAdminsEmail1); | 440 | Assert.assertEquals(tenantAdminsEmail1, loadedTenantAdminsEmail1); |
411 | - | 441 | + |
412 | List<User> loadedTenantAdminsEmail2 = new ArrayList<>(); | 442 | List<User> loadedTenantAdminsEmail2 = new ArrayList<>(); |
413 | pageLink = new TextPageLink(16, email2); | 443 | pageLink = new TextPageLink(16, email2); |
414 | do { | 444 | do { |
415 | - pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | ||
416 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 445 | + pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
446 | + new TypeReference<TextPageData<User>>() { | ||
447 | + }, pageLink); | ||
417 | loadedTenantAdminsEmail2.addAll(pageData.getData()); | 448 | loadedTenantAdminsEmail2.addAll(pageData.getData()); |
418 | if (pageData.hasNext()) { | 449 | if (pageData.hasNext()) { |
419 | pageLink = pageData.getNextPageLink(); | 450 | pageLink = pageData.getNextPageLink(); |
420 | } | 451 | } |
421 | } while (pageData.hasNext()); | 452 | } while (pageData.hasNext()); |
422 | - | 453 | + |
423 | Collections.sort(tenantAdminsEmail2, idComparator); | 454 | Collections.sort(tenantAdminsEmail2, idComparator); |
424 | Collections.sort(loadedTenantAdminsEmail2, idComparator); | 455 | Collections.sort(loadedTenantAdminsEmail2, idComparator); |
425 | - | 456 | + |
426 | Assert.assertEquals(tenantAdminsEmail2, loadedTenantAdminsEmail2); | 457 | Assert.assertEquals(tenantAdminsEmail2, loadedTenantAdminsEmail2); |
427 | - | 458 | + |
428 | for (User user : loadedTenantAdminsEmail1) { | 459 | for (User user : loadedTenantAdminsEmail1) { |
429 | - doDelete("/api/user/"+user.getId().getId().toString()) | ||
430 | - .andExpect(status().isOk()); | 460 | + doDelete("/api/user/" + user.getId().getId().toString()) |
461 | + .andExpect(status().isOk()); | ||
431 | } | 462 | } |
432 | - | 463 | + |
433 | pageLink = new TextPageLink(4, email1); | 464 | pageLink = new TextPageLink(4, email1); |
434 | - pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | ||
435 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 465 | + pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
466 | + new TypeReference<TextPageData<User>>() { | ||
467 | + }, pageLink); | ||
436 | Assert.assertFalse(pageData.hasNext()); | 468 | Assert.assertFalse(pageData.hasNext()); |
437 | Assert.assertEquals(0, pageData.getData().size()); | 469 | Assert.assertEquals(0, pageData.getData().size()); |
438 | - | 470 | + |
439 | for (User user : loadedTenantAdminsEmail2) { | 471 | for (User user : loadedTenantAdminsEmail2) { |
440 | - doDelete("/api/user/"+user.getId().getId().toString()) | ||
441 | - .andExpect(status().isOk()); | 472 | + doDelete("/api/user/" + user.getId().getId().toString()) |
473 | + .andExpect(status().isOk()); | ||
442 | } | 474 | } |
443 | - | 475 | + |
444 | pageLink = new TextPageLink(4, email2); | 476 | pageLink = new TextPageLink(4, email2); |
445 | - pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | ||
446 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 477 | + pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
478 | + new TypeReference<TextPageData<User>>() { | ||
479 | + }, pageLink); | ||
447 | Assert.assertFalse(pageData.hasNext()); | 480 | Assert.assertFalse(pageData.hasNext()); |
448 | Assert.assertEquals(0, pageData.getData().size()); | 481 | Assert.assertEquals(0, pageData.getData().size()); |
449 | - | ||
450 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
451 | - .andExpect(status().isOk()); | 482 | + |
483 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
484 | + .andExpect(status().isOk()); | ||
452 | } | 485 | } |
453 | - | 486 | + |
454 | @Test | 487 | @Test |
455 | public void testFindCustomerUsers() throws Exception { | 488 | public void testFindCustomerUsers() throws Exception { |
456 | - | 489 | + |
457 | loginSysAdmin(); | 490 | loginSysAdmin(); |
458 | Tenant tenant = new Tenant(); | 491 | Tenant tenant = new Tenant(); |
459 | tenant.setTitle("My tenant"); | 492 | tenant.setTitle("My tenant"); |
460 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 493 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
461 | Assert.assertNotNull(savedTenant); | 494 | Assert.assertNotNull(savedTenant); |
462 | - | 495 | + |
463 | TenantId tenantId = savedTenant.getId(); | 496 | TenantId tenantId = savedTenant.getId(); |
464 | User tenantAdmin = new User(); | 497 | User tenantAdmin = new User(); |
465 | tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | 498 | tenantAdmin.setAuthority(Authority.TENANT_ADMIN); |
@@ -467,59 +500,60 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -467,59 +500,60 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
467 | tenantAdmin.setEmail("tenant2@thingsboard.org"); | 500 | tenantAdmin.setEmail("tenant2@thingsboard.org"); |
468 | tenantAdmin.setFirstName("Joe"); | 501 | tenantAdmin.setFirstName("Joe"); |
469 | tenantAdmin.setLastName("Downs"); | 502 | tenantAdmin.setLastName("Downs"); |
470 | - | 503 | + |
471 | tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | 504 | tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); |
472 | - | 505 | + |
473 | Customer customer = new Customer(); | 506 | Customer customer = new Customer(); |
474 | customer.setTitle("My customer"); | 507 | customer.setTitle("My customer"); |
475 | Customer savedCustomer = doPost("/api/customer", customer, Customer.class); | 508 | Customer savedCustomer = doPost("/api/customer", customer, Customer.class); |
476 | 509 | ||
477 | CustomerId customerId = savedCustomer.getId(); | 510 | CustomerId customerId = savedCustomer.getId(); |
478 | - | 511 | + |
479 | List<User> customerUsers = new ArrayList<>(); | 512 | List<User> customerUsers = new ArrayList<>(); |
480 | - for (int i=0;i<56;i++) { | 513 | + for (int i = 0; i < 56; i++) { |
481 | User user = new User(); | 514 | User user = new User(); |
482 | user.setAuthority(Authority.CUSTOMER_USER); | 515 | user.setAuthority(Authority.CUSTOMER_USER); |
483 | user.setCustomerId(customerId); | 516 | user.setCustomerId(customerId); |
484 | user.setEmail("testCustomer" + i + "@thingsboard.org"); | 517 | user.setEmail("testCustomer" + i + "@thingsboard.org"); |
485 | customerUsers.add(doPost("/api/user", user, User.class)); | 518 | customerUsers.add(doPost("/api/user", user, User.class)); |
486 | } | 519 | } |
487 | - | 520 | + |
488 | List<User> loadedCustomerUsers = new ArrayList<>(); | 521 | List<User> loadedCustomerUsers = new ArrayList<>(); |
489 | TextPageLink pageLink = new TextPageLink(33); | 522 | TextPageLink pageLink = new TextPageLink(33); |
490 | TextPageData<User> pageData = null; | 523 | TextPageData<User> pageData = null; |
491 | do { | 524 | do { |
492 | - pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", | ||
493 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 525 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", |
526 | + new TypeReference<TextPageData<User>>() { | ||
527 | + }, pageLink); | ||
494 | loadedCustomerUsers.addAll(pageData.getData()); | 528 | loadedCustomerUsers.addAll(pageData.getData()); |
495 | if (pageData.hasNext()) { | 529 | if (pageData.hasNext()) { |
496 | pageLink = pageData.getNextPageLink(); | 530 | pageLink = pageData.getNextPageLink(); |
497 | } | 531 | } |
498 | } while (pageData.hasNext()); | 532 | } while (pageData.hasNext()); |
499 | - | 533 | + |
500 | Collections.sort(customerUsers, idComparator); | 534 | Collections.sort(customerUsers, idComparator); |
501 | Collections.sort(loadedCustomerUsers, idComparator); | 535 | Collections.sort(loadedCustomerUsers, idComparator); |
502 | - | 536 | + |
503 | Assert.assertEquals(customerUsers, loadedCustomerUsers); | 537 | Assert.assertEquals(customerUsers, loadedCustomerUsers); |
504 | - | ||
505 | - doDelete("/api/customer/"+customerId.getId().toString()) | ||
506 | - .andExpect(status().isOk()); | ||
507 | - | 538 | + |
539 | + doDelete("/api/customer/" + customerId.getId().toString()) | ||
540 | + .andExpect(status().isOk()); | ||
541 | + | ||
508 | loginSysAdmin(); | 542 | loginSysAdmin(); |
509 | - | ||
510 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
511 | - .andExpect(status().isOk()); | 543 | + |
544 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
545 | + .andExpect(status().isOk()); | ||
512 | } | 546 | } |
513 | - | 547 | + |
514 | @Test | 548 | @Test |
515 | public void testFindCustomerUsersByEmail() throws Exception { | 549 | public void testFindCustomerUsersByEmail() throws Exception { |
516 | - | 550 | + |
517 | loginSysAdmin(); | 551 | loginSysAdmin(); |
518 | Tenant tenant = new Tenant(); | 552 | Tenant tenant = new Tenant(); |
519 | tenant.setTitle("My tenant"); | 553 | tenant.setTitle("My tenant"); |
520 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); | 554 | Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
521 | Assert.assertNotNull(savedTenant); | 555 | Assert.assertNotNull(savedTenant); |
522 | - | 556 | + |
523 | TenantId tenantId = savedTenant.getId(); | 557 | TenantId tenantId = savedTenant.getId(); |
524 | User tenantAdmin = new User(); | 558 | User tenantAdmin = new User(); |
525 | tenantAdmin.setAuthority(Authority.TENANT_ADMIN); | 559 | tenantAdmin.setAuthority(Authority.TENANT_ADMIN); |
@@ -527,105 +561,109 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -527,105 +561,109 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
527 | tenantAdmin.setEmail("tenant2@thingsboard.org"); | 561 | tenantAdmin.setEmail("tenant2@thingsboard.org"); |
528 | tenantAdmin.setFirstName("Joe"); | 562 | tenantAdmin.setFirstName("Joe"); |
529 | tenantAdmin.setLastName("Downs"); | 563 | tenantAdmin.setLastName("Downs"); |
530 | - | 564 | + |
531 | tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); | 565 | tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); |
532 | - | 566 | + |
533 | Customer customer = new Customer(); | 567 | Customer customer = new Customer(); |
534 | customer.setTitle("My customer"); | 568 | customer.setTitle("My customer"); |
535 | Customer savedCustomer = doPost("/api/customer", customer, Customer.class); | 569 | Customer savedCustomer = doPost("/api/customer", customer, Customer.class); |
536 | 570 | ||
537 | CustomerId customerId = savedCustomer.getId(); | 571 | CustomerId customerId = savedCustomer.getId(); |
538 | - | ||
539 | - String email1 = "testEmail1"; | 572 | + |
573 | + String email1 = "testEmail1"; | ||
540 | List<User> customerUsersEmail1 = new ArrayList<>(); | 574 | List<User> customerUsersEmail1 = new ArrayList<>(); |
541 | - | ||
542 | - for (int i=0;i<74;i++) { | 575 | + |
576 | + for (int i = 0; i < 74; i++) { | ||
543 | User user = new User(); | 577 | User user = new User(); |
544 | user.setAuthority(Authority.CUSTOMER_USER); | 578 | user.setAuthority(Authority.CUSTOMER_USER); |
545 | user.setCustomerId(customerId); | 579 | user.setCustomerId(customerId); |
546 | - String suffix = RandomStringUtils.randomAlphanumeric((int)(5 + Math.random()*10)); | ||
547 | - String email = email1+suffix+ "@thingsboard.org"; | 580 | + String suffix = RandomStringUtils.randomAlphanumeric((int) (5 + Math.random() * 10)); |
581 | + String email = email1 + suffix + "@thingsboard.org"; | ||
548 | email = i % 2 == 0 ? email.toLowerCase() : email.toUpperCase(); | 582 | email = i % 2 == 0 ? email.toLowerCase() : email.toUpperCase(); |
549 | user.setEmail(email); | 583 | user.setEmail(email); |
550 | customerUsersEmail1.add(doPost("/api/user", user, User.class)); | 584 | customerUsersEmail1.add(doPost("/api/user", user, User.class)); |
551 | } | 585 | } |
552 | - | ||
553 | - String email2 = "testEmail2"; | 586 | + |
587 | + String email2 = "testEmail2"; | ||
554 | List<User> customerUsersEmail2 = new ArrayList<>(); | 588 | List<User> customerUsersEmail2 = new ArrayList<>(); |
555 | - | ||
556 | - for (int i=0;i<92;i++) { | 589 | + |
590 | + for (int i = 0; i < 92; i++) { | ||
557 | User user = new User(); | 591 | User user = new User(); |
558 | user.setAuthority(Authority.CUSTOMER_USER); | 592 | user.setAuthority(Authority.CUSTOMER_USER); |
559 | user.setCustomerId(customerId); | 593 | user.setCustomerId(customerId); |
560 | - String suffix = RandomStringUtils.randomAlphanumeric((int)(5 + Math.random()*10)); | ||
561 | - String email = email2+suffix+ "@thingsboard.org"; | 594 | + String suffix = RandomStringUtils.randomAlphanumeric((int) (5 + Math.random() * 10)); |
595 | + String email = email2 + suffix + "@thingsboard.org"; | ||
562 | email = i % 2 == 0 ? email.toLowerCase() : email.toUpperCase(); | 596 | email = i % 2 == 0 ? email.toLowerCase() : email.toUpperCase(); |
563 | user.setEmail(email); | 597 | user.setEmail(email); |
564 | customerUsersEmail2.add(doPost("/api/user", user, User.class)); | 598 | customerUsersEmail2.add(doPost("/api/user", user, User.class)); |
565 | } | 599 | } |
566 | - | 600 | + |
567 | List<User> loadedCustomerUsersEmail1 = new ArrayList<>(); | 601 | List<User> loadedCustomerUsersEmail1 = new ArrayList<>(); |
568 | TextPageLink pageLink = new TextPageLink(33, email1); | 602 | TextPageLink pageLink = new TextPageLink(33, email1); |
569 | TextPageData<User> pageData = null; | 603 | TextPageData<User> pageData = null; |
570 | do { | 604 | do { |
571 | - pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", | ||
572 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 605 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", |
606 | + new TypeReference<TextPageData<User>>() { | ||
607 | + }, pageLink); | ||
573 | loadedCustomerUsersEmail1.addAll(pageData.getData()); | 608 | loadedCustomerUsersEmail1.addAll(pageData.getData()); |
574 | if (pageData.hasNext()) { | 609 | if (pageData.hasNext()) { |
575 | pageLink = pageData.getNextPageLink(); | 610 | pageLink = pageData.getNextPageLink(); |
576 | } | 611 | } |
577 | } while (pageData.hasNext()); | 612 | } while (pageData.hasNext()); |
578 | - | 613 | + |
579 | Collections.sort(customerUsersEmail1, idComparator); | 614 | Collections.sort(customerUsersEmail1, idComparator); |
580 | Collections.sort(loadedCustomerUsersEmail1, idComparator); | 615 | Collections.sort(loadedCustomerUsersEmail1, idComparator); |
581 | - | 616 | + |
582 | Assert.assertEquals(customerUsersEmail1, loadedCustomerUsersEmail1); | 617 | Assert.assertEquals(customerUsersEmail1, loadedCustomerUsersEmail1); |
583 | - | 618 | + |
584 | List<User> loadedCustomerUsersEmail2 = new ArrayList<>(); | 619 | List<User> loadedCustomerUsersEmail2 = new ArrayList<>(); |
585 | pageLink = new TextPageLink(16, email2); | 620 | pageLink = new TextPageLink(16, email2); |
586 | do { | 621 | do { |
587 | - pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", | ||
588 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 622 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", |
623 | + new TypeReference<TextPageData<User>>() { | ||
624 | + }, pageLink); | ||
589 | loadedCustomerUsersEmail2.addAll(pageData.getData()); | 625 | loadedCustomerUsersEmail2.addAll(pageData.getData()); |
590 | if (pageData.hasNext()) { | 626 | if (pageData.hasNext()) { |
591 | pageLink = pageData.getNextPageLink(); | 627 | pageLink = pageData.getNextPageLink(); |
592 | } | 628 | } |
593 | } while (pageData.hasNext()); | 629 | } while (pageData.hasNext()); |
594 | - | 630 | + |
595 | Collections.sort(customerUsersEmail2, idComparator); | 631 | Collections.sort(customerUsersEmail2, idComparator); |
596 | Collections.sort(loadedCustomerUsersEmail2, idComparator); | 632 | Collections.sort(loadedCustomerUsersEmail2, idComparator); |
597 | - | 633 | + |
598 | Assert.assertEquals(customerUsersEmail2, loadedCustomerUsersEmail2); | 634 | Assert.assertEquals(customerUsersEmail2, loadedCustomerUsersEmail2); |
599 | - | 635 | + |
600 | for (User user : loadedCustomerUsersEmail1) { | 636 | for (User user : loadedCustomerUsersEmail1) { |
601 | - doDelete("/api/user/"+user.getId().getId().toString()) | ||
602 | - .andExpect(status().isOk()); | 637 | + doDelete("/api/user/" + user.getId().getId().toString()) |
638 | + .andExpect(status().isOk()); | ||
603 | } | 639 | } |
604 | - | 640 | + |
605 | pageLink = new TextPageLink(4, email1); | 641 | pageLink = new TextPageLink(4, email1); |
606 | - pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", | ||
607 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 642 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", |
643 | + new TypeReference<TextPageData<User>>() { | ||
644 | + }, pageLink); | ||
608 | Assert.assertFalse(pageData.hasNext()); | 645 | Assert.assertFalse(pageData.hasNext()); |
609 | Assert.assertEquals(0, pageData.getData().size()); | 646 | Assert.assertEquals(0, pageData.getData().size()); |
610 | - | 647 | + |
611 | for (User user : loadedCustomerUsersEmail2) { | 648 | for (User user : loadedCustomerUsersEmail2) { |
612 | - doDelete("/api/user/"+user.getId().getId().toString()) | ||
613 | - .andExpect(status().isOk()); | 649 | + doDelete("/api/user/" + user.getId().getId().toString()) |
650 | + .andExpect(status().isOk()); | ||
614 | } | 651 | } |
615 | - | 652 | + |
616 | pageLink = new TextPageLink(4, email2); | 653 | pageLink = new TextPageLink(4, email2); |
617 | - pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", | ||
618 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 654 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", |
655 | + new TypeReference<TextPageData<User>>() { | ||
656 | + }, pageLink); | ||
619 | Assert.assertFalse(pageData.hasNext()); | 657 | Assert.assertFalse(pageData.hasNext()); |
620 | Assert.assertEquals(0, pageData.getData().size()); | 658 | Assert.assertEquals(0, pageData.getData().size()); |
621 | - | ||
622 | - doDelete("/api/customer/"+customerId.getId().toString()) | ||
623 | - .andExpect(status().isOk()); | ||
624 | - | 659 | + |
660 | + doDelete("/api/customer/" + customerId.getId().toString()) | ||
661 | + .andExpect(status().isOk()); | ||
662 | + | ||
625 | loginSysAdmin(); | 663 | loginSysAdmin(); |
626 | - | ||
627 | - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | ||
628 | - .andExpect(status().isOk()); | 664 | + |
665 | + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) | ||
666 | + .andExpect(status().isOk()); | ||
629 | } | 667 | } |
630 | - | 668 | + |
631 | } | 669 | } |
@@ -64,7 +64,6 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes | @@ -64,7 +64,6 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes | ||
64 | WidgetsBundle widgetsBundle = new WidgetsBundle(); | 64 | WidgetsBundle widgetsBundle = new WidgetsBundle(); |
65 | widgetsBundle.setTitle("My widgets bundle"); | 65 | widgetsBundle.setTitle("My widgets bundle"); |
66 | savedWidgetsBundle = doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class); | 66 | savedWidgetsBundle = doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class); |
67 | - | ||
68 | } | 67 | } |
69 | 68 | ||
70 | @After | 69 | @After |
@@ -101,6 +100,19 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes | @@ -101,6 +100,19 @@ public abstract class BaseWidgetTypeControllerTest extends AbstractControllerTes | ||
101 | } | 100 | } |
102 | 101 | ||
103 | @Test | 102 | @Test |
103 | + public void testUpdateWidgetTypeFromDifferentTenant() throws Exception { | ||
104 | + WidgetType widgetType = new WidgetType(); | ||
105 | + widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); | ||
106 | + widgetType.setName("Widget Type"); | ||
107 | + widgetType.setDescriptor(new ObjectMapper().readValue("{ \"someKey\": \"someValue\" }", JsonNode.class)); | ||
108 | + WidgetType savedWidgetType = doPost("/api/widgetType", widgetType, WidgetType.class); | ||
109 | + | ||
110 | + loginDifferentTenant(); | ||
111 | + doPost("/api/widgetType", savedWidgetType, WidgetType.class, status().isForbidden()); | ||
112 | + deleteDifferentTenant(); | ||
113 | + } | ||
114 | + | ||
115 | + @Test | ||
104 | public void testFindWidgetTypeById() throws Exception { | 116 | public void testFindWidgetTypeById() throws Exception { |
105 | WidgetType widgetType = new WidgetType(); | 117 | WidgetType widgetType = new WidgetType(); |
106 | widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); | 118 | widgetType.setBundleAlias(savedWidgetsBundle.getAlias()); |
@@ -89,6 +89,17 @@ public abstract class BaseWidgetsBundleControllerTest extends AbstractController | @@ -89,6 +89,17 @@ public abstract class BaseWidgetsBundleControllerTest extends AbstractController | ||
89 | } | 89 | } |
90 | 90 | ||
91 | @Test | 91 | @Test |
92 | + public void testUpdateWidgetsBundleFromDifferentTenant() throws Exception { | ||
93 | + WidgetsBundle widgetsBundle = new WidgetsBundle(); | ||
94 | + widgetsBundle.setTitle("My widgets bundle"); | ||
95 | + WidgetsBundle savedWidgetsBundle = doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class); | ||
96 | + | ||
97 | + loginDifferentTenant(); | ||
98 | + doPost("/api/widgetsBundle", savedWidgetsBundle, WidgetsBundle.class, status().isForbidden()); | ||
99 | + deleteDifferentTenant(); | ||
100 | + } | ||
101 | + | ||
102 | + @Test | ||
92 | public void testFindWidgetsBundleById() throws Exception { | 103 | public void testFindWidgetsBundleById() throws Exception { |
93 | WidgetsBundle widgetsBundle = new WidgetsBundle(); | 104 | WidgetsBundle widgetsBundle = new WidgetsBundle(); |
94 | widgetsBundle.setTitle("My widgets bundle"); | 105 | widgetsBundle.setTitle("My widgets bundle"); |
application/src/test/java/org/thingsboard/server/rules/RuleEngineNoSqlTestSuite.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2020 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.rules; | ||
17 | - | ||
18 | -import org.cassandraunit.dataset.cql.ClassPathCQLDataSet; | ||
19 | -import org.junit.BeforeClass; | ||
20 | -import org.junit.ClassRule; | ||
21 | -import org.junit.extensions.cpsuite.ClasspathSuite; | ||
22 | -import org.junit.runner.RunWith; | ||
23 | -import org.thingsboard.server.dao.CustomCassandraCQLUnit; | ||
24 | -import org.thingsboard.server.dao.CustomSqlUnit; | ||
25 | -import org.thingsboard.server.queue.memory.InMemoryStorage; | ||
26 | - | ||
27 | -import java.util.Arrays; | ||
28 | - | ||
29 | -@RunWith(ClasspathSuite.class) | ||
30 | -@ClasspathSuite.ClassnameFilters({ | ||
31 | - "org.thingsboard.server.rules.flow.nosql.*Test", | ||
32 | - "org.thingsboard.server.rules.lifecycle.nosql.*Test" | ||
33 | -}) | ||
34 | -public class RuleEngineNoSqlTestSuite { | ||
35 | - | ||
36 | - @ClassRule | ||
37 | - public static CustomCassandraCQLUnit cassandraUnit = | ||
38 | - new CustomCassandraCQLUnit( | ||
39 | - Arrays.asList( | ||
40 | - new ClassPathCQLDataSet("cassandra/schema-ts.cql", false, false), | ||
41 | - new ClassPathCQLDataSet("cassandra/schema-entities.cql", false, false), | ||
42 | - new ClassPathCQLDataSet("cassandra/system-data.cql", false, false)), | ||
43 | - "cassandra-test.yaml", 30000l); | ||
44 | - | ||
45 | - @BeforeClass | ||
46 | - public static void cleanupInMemStorage(){ | ||
47 | - InMemoryStorage.getInstance().cleanup(); | ||
48 | - } | ||
49 | - | ||
50 | -} |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -28,4 +28,6 @@ public class OAuth2User { | @@ -28,4 +28,6 @@ public class OAuth2User { | ||
28 | private String email; | 28 | private String email; |
29 | private String firstName; | 29 | private String firstName; |
30 | private String lastName; | 30 | private String lastName; |
31 | + private boolean alwaysFullScreen; | ||
32 | + private String defaultDashboardName; | ||
31 | } | 33 | } |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -40,6 +40,7 @@ import java.util.UUID; | @@ -40,6 +40,7 @@ import java.util.UUID; | ||
40 | public final class TbMsg implements Serializable { | 40 | public final class TbMsg implements Serializable { |
41 | 41 | ||
42 | private final UUID id; | 42 | private final UUID id; |
43 | + private final long ts; | ||
43 | private final String type; | 44 | private final String type; |
44 | private final EntityId originator; | 45 | private final EntityId originator; |
45 | private final TbMsgMetaData metaData; | 46 | private final TbMsgMetaData metaData; |
@@ -51,38 +52,43 @@ public final class TbMsg implements Serializable { | @@ -51,38 +52,43 @@ public final class TbMsg implements Serializable { | ||
51 | transient private final TbMsgCallback callback; | 52 | transient private final TbMsgCallback callback; |
52 | 53 | ||
53 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data) { | 54 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data) { |
54 | - return new TbMsg(UUID.randomUUID(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, null, null, TbMsgCallback.EMPTY); | 55 | + return new TbMsg(UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, null, null, TbMsgCallback.EMPTY); |
55 | } | 56 | } |
56 | 57 | ||
57 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { | 58 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { |
58 | - return new TbMsg(UUID.randomUUID(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); | 59 | + return new TbMsg(UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); |
59 | } | 60 | } |
60 | 61 | ||
61 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data) { | 62 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data) { |
62 | - return new TbMsg(UUID.randomUUID(), type, originator, metaData.copy(), dataType, data, null, null, TbMsgCallback.EMPTY); | 63 | + return new TbMsg(UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), dataType, data, null, null, TbMsgCallback.EMPTY); |
63 | } | 64 | } |
64 | 65 | ||
65 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { | 66 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { |
66 | - return new TbMsg(UUID.randomUUID(), type, originator, metaData.copy(), dataType, data, ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); | 67 | + return new TbMsg(UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), dataType, data, ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); |
67 | } | 68 | } |
68 | 69 | ||
69 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data, TbMsgCallback callback) { | 70 | public static TbMsg newMsg(String type, EntityId originator, TbMsgMetaData metaData, String data, TbMsgCallback callback) { |
70 | - return new TbMsg(UUID.randomUUID(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, null, null, callback); | 71 | + return new TbMsg(UUID.randomUUID(), System.currentTimeMillis(), type, originator, metaData.copy(), TbMsgDataType.JSON, data, null, null, callback); |
71 | } | 72 | } |
72 | 73 | ||
73 | public static TbMsg transformMsg(TbMsg origMsg, String type, EntityId originator, TbMsgMetaData metaData, String data) { | 74 | public static TbMsg transformMsg(TbMsg origMsg, String type, EntityId originator, TbMsgMetaData metaData, String data) { |
74 | - return new TbMsg(origMsg.getId(), type, originator, metaData.copy(), origMsg.getDataType(), | 75 | + return new TbMsg(origMsg.getId(), origMsg.getTs(), type, originator, metaData.copy(), origMsg.getDataType(), |
75 | data, origMsg.getRuleChainId(), origMsg.getRuleNodeId(), origMsg.getCallback()); | 76 | data, origMsg.getRuleChainId(), origMsg.getRuleNodeId(), origMsg.getCallback()); |
76 | } | 77 | } |
77 | 78 | ||
78 | public static TbMsg newMsg(TbMsg tbMsg, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { | 79 | public static TbMsg newMsg(TbMsg tbMsg, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { |
79 | - return new TbMsg(UUID.randomUUID(), tbMsg.getType(), tbMsg.getOriginator(), tbMsg.getMetaData().copy(), | 80 | + return new TbMsg(UUID.randomUUID(), tbMsg.getTs(), tbMsg.getType(), tbMsg.getOriginator(), tbMsg.getMetaData().copy(), |
80 | tbMsg.getDataType(), tbMsg.getData(), ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); | 81 | tbMsg.getDataType(), tbMsg.getData(), ruleChainId, ruleNodeId, TbMsgCallback.EMPTY); |
81 | } | 82 | } |
82 | 83 | ||
83 | - private TbMsg(UUID id, String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data, | 84 | + private TbMsg(UUID id, long ts, String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data, |
84 | RuleChainId ruleChainId, RuleNodeId ruleNodeId, TbMsgCallback callback) { | 85 | RuleChainId ruleChainId, RuleNodeId ruleNodeId, TbMsgCallback callback) { |
85 | this.id = id; | 86 | this.id = id; |
87 | + if (ts > 0) { | ||
88 | + this.ts = ts; | ||
89 | + } else { | ||
90 | + this.ts = System.currentTimeMillis(); | ||
91 | + } | ||
86 | this.type = type; | 92 | this.type = type; |
87 | this.originator = originator; | 93 | this.originator = originator; |
88 | this.metaData = metaData; | 94 | this.metaData = metaData; |
@@ -105,6 +111,7 @@ public final class TbMsg implements Serializable { | @@ -105,6 +111,7 @@ public final class TbMsg implements Serializable { | ||
105 | public static byte[] toByteArray(TbMsg msg) { | 111 | public static byte[] toByteArray(TbMsg msg) { |
106 | MsgProtos.TbMsgProto.Builder builder = MsgProtos.TbMsgProto.newBuilder(); | 112 | MsgProtos.TbMsgProto.Builder builder = MsgProtos.TbMsgProto.newBuilder(); |
107 | builder.setId(msg.getId().toString()); | 113 | builder.setId(msg.getId().toString()); |
114 | + builder.setTs(msg.getTs()); | ||
108 | builder.setType(msg.getType()); | 115 | builder.setType(msg.getType()); |
109 | builder.setEntityType(msg.getOriginator().getEntityType().name()); | 116 | builder.setEntityType(msg.getOriginator().getEntityType().name()); |
110 | builder.setEntityIdMSB(msg.getOriginator().getId().getMostSignificantBits()); | 117 | builder.setEntityIdMSB(msg.getOriginator().getId().getMostSignificantBits()); |
@@ -124,7 +131,6 @@ public final class TbMsg implements Serializable { | @@ -124,7 +131,6 @@ public final class TbMsg implements Serializable { | ||
124 | builder.setMetaData(MsgProtos.TbMsgMetaDataProto.newBuilder().putAllData(msg.getMetaData().getData()).build()); | 131 | builder.setMetaData(MsgProtos.TbMsgMetaDataProto.newBuilder().putAllData(msg.getMetaData().getData()).build()); |
125 | } | 132 | } |
126 | 133 | ||
127 | - | ||
128 | builder.setDataType(msg.getDataType().ordinal()); | 134 | builder.setDataType(msg.getDataType().ordinal()); |
129 | builder.setData(msg.getData()); | 135 | builder.setData(msg.getData()); |
130 | return builder.build().toByteArray(); | 136 | return builder.build().toByteArray(); |
@@ -144,18 +150,18 @@ public final class TbMsg implements Serializable { | @@ -144,18 +150,18 @@ public final class TbMsg implements Serializable { | ||
144 | ruleNodeId = new RuleNodeId(new UUID(proto.getRuleNodeIdMSB(), proto.getRuleNodeIdLSB())); | 150 | ruleNodeId = new RuleNodeId(new UUID(proto.getRuleNodeIdMSB(), proto.getRuleNodeIdLSB())); |
145 | } | 151 | } |
146 | TbMsgDataType dataType = TbMsgDataType.values()[proto.getDataType()]; | 152 | TbMsgDataType dataType = TbMsgDataType.values()[proto.getDataType()]; |
147 | - return new TbMsg(UUID.fromString(proto.getId()), proto.getType(), entityId, metaData, dataType, proto.getData(), ruleChainId, ruleNodeId, callback); | 153 | + return new TbMsg(UUID.fromString(proto.getId()), proto.getTs(), proto.getType(), entityId, metaData, dataType, proto.getData(), ruleChainId, ruleNodeId, callback); |
148 | } catch (InvalidProtocolBufferException e) { | 154 | } catch (InvalidProtocolBufferException e) { |
149 | throw new IllegalStateException("Could not parse protobuf for TbMsg", e); | 155 | throw new IllegalStateException("Could not parse protobuf for TbMsg", e); |
150 | } | 156 | } |
151 | } | 157 | } |
152 | 158 | ||
153 | public TbMsg copyWithRuleChainId(RuleChainId ruleChainId) { | 159 | public TbMsg copyWithRuleChainId(RuleChainId ruleChainId) { |
154 | - return new TbMsg(this.id, this.type, this.originator, this.metaData, this.dataType, this.data, ruleChainId, null, callback); | 160 | + return new TbMsg(this.id, this.ts, this.type, this.originator, this.metaData, this.dataType, this.data, ruleChainId, null, callback); |
155 | } | 161 | } |
156 | 162 | ||
157 | public TbMsg copyWithRuleNodeId(RuleChainId ruleChainId, RuleNodeId ruleNodeId) { | 163 | public TbMsg copyWithRuleNodeId(RuleChainId ruleChainId, RuleNodeId ruleNodeId) { |
158 | - return new TbMsg(this.id, this.type, this.originator, this.metaData, this.dataType, this.data, ruleChainId, ruleNodeId, callback); | 164 | + return new TbMsg(this.id, this.ts, this.type, this.originator, this.metaData, this.dataType, this.data, ruleChainId, ruleNodeId, callback); |
159 | } | 165 | } |
160 | 166 | ||
161 | public TbMsgCallback getCallback() { | 167 | public TbMsgCallback getCallback() { |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>thingsboard</artifactId> | 24 | <artifactId>thingsboard</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <artifactId>common</artifactId> | 26 | <artifactId>common</artifactId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -101,7 +101,7 @@ public class TbServiceBusConsumerTemplate<T extends TbQueueMsg> extends Abstract | @@ -101,7 +101,7 @@ public class TbServiceBusConsumerTemplate<T extends TbQueueMsg> extends Abstract | ||
101 | @Override | 101 | @Override |
102 | protected void doSubscribe(List<String> topicNames) { | 102 | protected void doSubscribe(List<String> topicNames) { |
103 | createReceivers(); | 103 | createReceivers(); |
104 | - messagesPerQueue = receivers.size() / partitions.size(); | 104 | + messagesPerQueue = receivers.size() / Math.max(partitions.size(), 1); |
105 | } | 105 | } |
106 | 106 | ||
107 | @Override | 107 | @Override |
@@ -85,7 +85,12 @@ public abstract class AbstractTbQueueConsumerTemplate<R, T extends TbQueueMsg> i | @@ -85,7 +85,12 @@ public abstract class AbstractTbQueueConsumerTemplate<R, T extends TbQueueMsg> i | ||
85 | subscribed = true; | 85 | subscribed = true; |
86 | } | 86 | } |
87 | 87 | ||
88 | - List<R> records = doPoll(durationInMillis); | 88 | + List<R> records; |
89 | + if (partitions.isEmpty()) { | ||
90 | + records = Collections.emptyList(); | ||
91 | + } else { | ||
92 | + records = doPoll(durationInMillis); | ||
93 | + } | ||
89 | if (!records.isEmpty()) { | 94 | if (!records.isEmpty()) { |
90 | List<T> result = new ArrayList<>(records.size()); | 95 | List<T> result = new ArrayList<>(records.size()); |
91 | records.forEach(record -> { | 96 | records.forEach(record -> { |
@@ -36,6 +36,7 @@ import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; | @@ -36,6 +36,7 @@ import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; | ||
36 | import javax.annotation.PostConstruct; | 36 | import javax.annotation.PostConstruct; |
37 | import java.nio.charset.StandardCharsets; | 37 | import java.nio.charset.StandardCharsets; |
38 | import java.util.ArrayList; | 38 | import java.util.ArrayList; |
39 | +import java.util.Collections; | ||
39 | import java.util.Comparator; | 40 | import java.util.Comparator; |
40 | import java.util.HashMap; | 41 | import java.util.HashMap; |
41 | import java.util.HashSet; | 42 | import java.util.HashSet; |
@@ -148,6 +149,14 @@ public class HashPartitionService implements PartitionService { | @@ -148,6 +149,14 @@ public class HashPartitionService implements PartitionService { | ||
148 | } | 149 | } |
149 | } | 150 | } |
150 | }); | 151 | }); |
152 | + | ||
153 | + oldPartitions.forEach((serviceQueueKey, partitions) -> { | ||
154 | + if (!myPartitions.containsKey(serviceQueueKey)) { | ||
155 | + log.info("[{}] NO MORE PARTITIONS FOR CURRENT KEY", serviceQueueKey); | ||
156 | + applicationEventPublisher.publishEvent(new PartitionChangeEvent(this, serviceQueueKey, Collections.emptySet())); | ||
157 | + } | ||
158 | + }); | ||
159 | + | ||
151 | myPartitions.forEach((serviceQueueKey, partitions) -> { | 160 | myPartitions.forEach((serviceQueueKey, partitions) -> { |
152 | if (!partitions.equals(oldPartitions.get(serviceQueueKey))) { | 161 | if (!partitions.equals(oldPartitions.get(serviceQueueKey))) { |
153 | log.info("[{}] NEW PARTITIONS: {}", serviceQueueKey, partitions); | 162 | log.info("[{}] NEW PARTITIONS: {}", serviceQueueKey, partitions); |
@@ -71,8 +71,12 @@ public class TbKafkaConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQue | @@ -71,8 +71,12 @@ public class TbKafkaConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQue | ||
71 | 71 | ||
72 | @Override | 72 | @Override |
73 | protected void doSubscribe(List<String> topicNames) { | 73 | protected void doSubscribe(List<String> topicNames) { |
74 | - topicNames.forEach(admin::createTopicIfNotExists); | ||
75 | - consumer.subscribe(topicNames); | 74 | + if (!topicNames.isEmpty()) { |
75 | + topicNames.forEach(admin::createTopicIfNotExists); | ||
76 | + consumer.subscribe(topicNames); | ||
77 | + } else { | ||
78 | + consumer.unsubscribe(); | ||
79 | + } | ||
76 | } | 80 | } |
77 | 81 | ||
78 | @Override | 82 | @Override |
@@ -200,7 +200,7 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi | @@ -200,7 +200,7 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi | ||
200 | consumerBuilder.settings(kafkaSettings); | 200 | consumerBuilder.settings(kafkaSettings); |
201 | consumerBuilder.topic(transportApiSettings.getRequestsTopic()); | 201 | consumerBuilder.topic(transportApiSettings.getRequestsTopic()); |
202 | consumerBuilder.clientId("monolith-transport-api-consumer-" + serviceInfoProvider.getServiceId()); | 202 | consumerBuilder.clientId("monolith-transport-api-consumer-" + serviceInfoProvider.getServiceId()); |
203 | - consumerBuilder.groupId("monolith-transport-api-consumer-" + serviceInfoProvider.getServiceId()); | 203 | + consumerBuilder.groupId("monolith-transport-api-consumer"); |
204 | consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); | 204 | consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
205 | consumerBuilder.admin(transportApiAdmin); | 205 | consumerBuilder.admin(transportApiAdmin); |
206 | return consumerBuilder.build(); | 206 | return consumerBuilder.build(); |
@@ -170,7 +170,7 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory { | @@ -170,7 +170,7 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory { | ||
170 | consumerBuilder.settings(kafkaSettings); | 170 | consumerBuilder.settings(kafkaSettings); |
171 | consumerBuilder.topic(transportApiSettings.getRequestsTopic()); | 171 | consumerBuilder.topic(transportApiSettings.getRequestsTopic()); |
172 | consumerBuilder.clientId("tb-core-transport-api-consumer-" + serviceInfoProvider.getServiceId()); | 172 | consumerBuilder.clientId("tb-core-transport-api-consumer-" + serviceInfoProvider.getServiceId()); |
173 | - consumerBuilder.groupId("tb-core-transport-api-consumer-" + serviceInfoProvider.getServiceId()); | 173 | + consumerBuilder.groupId("tb-core-transport-api-consumer"); |
174 | consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); | 174 | consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), TransportApiRequestMsg.parseFrom(msg.getData()), msg.getHeaders())); |
175 | consumerBuilder.admin(transportApiAdmin); | 175 | consumerBuilder.admin(transportApiAdmin); |
176 | return consumerBuilder.build(); | 176 | return consumerBuilder.build(); |
@@ -106,7 +106,7 @@ public class TbPubSubConsumerTemplate<T extends TbQueueMsg> extends AbstractPara | @@ -106,7 +106,7 @@ public class TbPubSubConsumerTemplate<T extends TbQueueMsg> extends AbstractPara | ||
106 | subscriptionNames = new LinkedHashSet<>(topicNames); | 106 | subscriptionNames = new LinkedHashSet<>(topicNames); |
107 | subscriptionNames.forEach(admin::createTopicIfNotExists); | 107 | subscriptionNames.forEach(admin::createTopicIfNotExists); |
108 | initNewExecutor(subscriptionNames.size() + 1); | 108 | initNewExecutor(subscriptionNames.size() + 1); |
109 | - messagesPerTopic = pubSubSettings.getMaxMessages() / subscriptionNames.size(); | 109 | + messagesPerTopic = pubSubSettings.getMaxMessages() / Math.max(subscriptionNames.size(), 1); |
110 | } | 110 | } |
111 | 111 | ||
112 | @Override | 112 | @Override |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -294,7 +294,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | @@ -294,7 +294,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement | ||
294 | break; | 294 | break; |
295 | } | 295 | } |
296 | } catch (Exception e) { | 296 | } catch (Exception e) { |
297 | - log.warn("[{}] Failed to subscribe to [{}][{}]", sessionId, topic, reqQoS); | 297 | + log.warn("[{}] Failed to subscribe to [{}][{}]", sessionId, topic, reqQoS, e); |
298 | grantedQoSList.add(FAILURE.value()); | 298 | grantedQoSList.add(FAILURE.value()); |
299 | } | 299 | } |
300 | } | 300 | } |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -53,10 +53,6 @@ | @@ -53,10 +53,6 @@ | ||
53 | <artifactId>util</artifactId> | 53 | <artifactId>util</artifactId> |
54 | </dependency> | 54 | </dependency> |
55 | <dependency> | 55 | <dependency> |
56 | - <groupId>org.thingsboard.common</groupId> | ||
57 | - <artifactId>queue</artifactId> | ||
58 | - </dependency> | ||
59 | - <dependency> | ||
60 | <groupId>com.google.code.gson</groupId> | 56 | <groupId>com.google.code.gson</groupId> |
61 | <artifactId>gson</artifactId> | 57 | <artifactId>gson</artifactId> |
62 | </dependency> | 58 | </dependency> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>2.5.1-SNAPSHOT</version> |
24 | <artifactId>thingsboard</artifactId> | 24 | <artifactId>thingsboard</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <artifactId>dao</artifactId> | 26 | <artifactId>dao</artifactId> |
@@ -112,7 +112,7 @@ public class EventEntity extends BaseSqlEntity<Event> implements BaseEntity<Eve | @@ -112,7 +112,7 @@ public class EventEntity extends BaseSqlEntity<Event> implements BaseEntity<Eve | ||
112 | return event; | 112 | return event; |
113 | } | 113 | } |
114 | 114 | ||
115 | - private long getTs(UUID uuid) { | 115 | + private static long getTs(UUID uuid) { |
116 | return (uuid.timestamp() - EPOCH_DIFF) / 10000; | 116 | return (uuid.timestamp() - EPOCH_DIFF) / 10000; |
117 | } | 117 | } |
118 | } | 118 | } |
@@ -34,6 +34,8 @@ public class OAuth2ClientMapperConfig { | @@ -34,6 +34,8 @@ public class OAuth2ClientMapperConfig { | ||
34 | private String tenantNameStrategy; | 34 | private String tenantNameStrategy; |
35 | private String tenantNamePattern; | 35 | private String tenantNamePattern; |
36 | private String customerNamePattern; | 36 | private String customerNamePattern; |
37 | + private boolean alwaysFullScreen; | ||
38 | + private String defaultDashboardName; | ||
37 | } | 39 | } |
38 | 40 | ||
39 | @Data | 41 | @Data |
@@ -90,7 +90,7 @@ public class JpaPsqlTimeseriesDao extends AbstractChunkedAggregationTimeseriesDa | @@ -90,7 +90,7 @@ public class JpaPsqlTimeseriesDao extends AbstractChunkedAggregationTimeseriesDa | ||
90 | } | 90 | } |
91 | 91 | ||
92 | private void savePartitionIfNotExist(long ts) { | 92 | private void savePartitionIfNotExist(long ts) { |
93 | - if (!tsFormat.equals(SqlTsPartitionDate.INDEFINITE)) { | 93 | + if (!tsFormat.equals(SqlTsPartitionDate.INDEFINITE) && ts >= 0) { |
94 | LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(ts), ZoneOffset.UTC); | 94 | LocalDateTime time = LocalDateTime.ofInstant(Instant.ofEpochMilli(ts), ZoneOffset.UTC); |
95 | LocalDateTime localDateTimeStart = tsFormat.trancateTo(time); | 95 | LocalDateTime localDateTimeStart = tsFormat.trancateTo(time); |
96 | long partitionStartTs = toMills(localDateTimeStart); | 96 | long partitionStartTs = toMills(localDateTimeStart); |
@@ -52,7 +52,7 @@ CREATE TABLE IF NOT EXISTS tb_schema_settings | @@ -52,7 +52,7 @@ CREATE TABLE IF NOT EXISTS tb_schema_settings | ||
52 | CONSTRAINT tb_schema_settings_pkey PRIMARY KEY (schema_version) | 52 | CONSTRAINT tb_schema_settings_pkey PRIMARY KEY (schema_version) |
53 | ); | 53 | ); |
54 | 54 | ||
55 | -INSERT INTO tb_schema_settings (schema_version) VALUES (2005000) ON CONFLICT (schema_version) DO UPDATE SET schema_version = 2005000; | 55 | +INSERT INTO tb_schema_settings (schema_version) VALUES (2005001) ON CONFLICT (schema_version) DO UPDATE SET schema_version = 2005001; |
56 | 56 | ||
57 | CREATE OR REPLACE FUNCTION to_uuid(IN entity_id varchar, OUT uuid_id uuid) AS | 57 | CREATE OR REPLACE FUNCTION to_uuid(IN entity_id varchar, OUT uuid_id uuid) AS |
58 | $$ | 58 | $$ |
@@ -53,7 +53,7 @@ CREATE TABLE IF NOT EXISTS tb_schema_settings | @@ -53,7 +53,7 @@ CREATE TABLE IF NOT EXISTS tb_schema_settings | ||
53 | CONSTRAINT tb_schema_settings_pkey PRIMARY KEY (schema_version) | 53 | CONSTRAINT tb_schema_settings_pkey PRIMARY KEY (schema_version) |
54 | ); | 54 | ); |
55 | 55 | ||
56 | -INSERT INTO tb_schema_settings (schema_version) VALUES (2005000) ON CONFLICT (schema_version) DO UPDATE SET schema_version = 2005000; | 56 | +INSERT INTO tb_schema_settings (schema_version) VALUES (2005001) ON CONFLICT (schema_version) DO UPDATE SET schema_version = 2005001; |
57 | 57 | ||
58 | CREATE OR REPLACE PROCEDURE drop_partitions_by_max_ttl(IN partition_type varchar, IN system_ttl bigint, INOUT deleted bigint) | 58 | CREATE OR REPLACE PROCEDURE drop_partitions_by_max_ttl(IN partition_type varchar, IN system_ttl bigint, INOUT deleted bigint) |
59 | LANGUAGE plpgsql AS | 59 | LANGUAGE plpgsql AS |
@@ -32,6 +32,32 @@ function additionalComposeArgs() { | @@ -32,6 +32,32 @@ function additionalComposeArgs() { | ||
32 | echo $ADDITIONAL_COMPOSE_ARGS | 32 | echo $ADDITIONAL_COMPOSE_ARGS |
33 | } | 33 | } |
34 | 34 | ||
35 | +function additionalComposeQueueArgs() { | ||
36 | + source .env | ||
37 | + ADDITIONAL_COMPOSE_QUEUE_ARGS="" | ||
38 | + case $TB_QUEUE_TYPE in | ||
39 | + kafka) | ||
40 | + ADDITIONAL_COMPOSE_QUEUE_ARGS="-f docker-compose.kafka.yml" | ||
41 | + ;; | ||
42 | + aws-sqs) | ||
43 | + ADDITIONAL_COMPOSE_QUEUE_ARGS="-f docker-compose.aws-sqs.yml" | ||
44 | + ;; | ||
45 | + pubsub) | ||
46 | + ADDITIONAL_COMPOSE_QUEUE_ARGS="-f docker-compose.pubsub.yml" | ||
47 | + ;; | ||
48 | + rabbitmq) | ||
49 | + ADDITIONAL_COMPOSE_QUEUE_ARGS="-f docker-compose.rabbitmq.yml" | ||
50 | + ;; | ||
51 | + service-bus) | ||
52 | + ADDITIONAL_COMPOSE_QUEUE_ARGS="-f docker-compose.service-bus.yml" | ||
53 | + ;; | ||
54 | + *) | ||
55 | + echo "Unknown Queue service value specified: '${TB_QUEUE_TYPE}'. Should be either kafka or aws-sqs or pubsub or rabbitmq or service-bus." >&2 | ||
56 | + exit 1 | ||
57 | + esac | ||
58 | + echo $ADDITIONAL_COMPOSE_QUEUE_ARGS | ||
59 | +} | ||
60 | + | ||
35 | function additionalStartupServices() { | 61 | function additionalStartupServices() { |
36 | source .env | 62 | source .env |
37 | ADDITIONAL_STARTUP_SERVICES="" | 63 | ADDITIONAL_STARTUP_SERVICES="" |
docker/docker-compose.aws-sqs.yml
0 → 100644
1 | +# | ||
2 | +# Copyright © 2016-2020 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 | + | ||
17 | +version: '2.2' | ||
18 | + | ||
19 | +services: | ||
20 | + tb-js-executor: | ||
21 | + env_file: | ||
22 | + - queue-aws-sqs.env | ||
23 | + tb-core1: | ||
24 | + env_file: | ||
25 | + - queue-aws-sqs.env | ||
26 | + depends_on: | ||
27 | + - zookeeper | ||
28 | + - redis | ||
29 | + tb-core2: | ||
30 | + env_file: | ||
31 | + - queue-aws-sqs.env | ||
32 | + depends_on: | ||
33 | + - zookeeper | ||
34 | + - redis | ||
35 | + tb-rule-engine1: | ||
36 | + env_file: | ||
37 | + - queue-aws-sqs.env | ||
38 | + depends_on: | ||
39 | + - zookeeper | ||
40 | + - redis | ||
41 | + tb-rule-engine2: | ||
42 | + env_file: | ||
43 | + - queue-aws-sqs.env | ||
44 | + depends_on: | ||
45 | + - zookeeper | ||
46 | + - redis | ||
47 | + tb-mqtt-transport1: | ||
48 | + env_file: | ||
49 | + - queue-aws-sqs.env | ||
50 | + depends_on: | ||
51 | + - zookeeper | ||
52 | + tb-mqtt-transport2: | ||
53 | + env_file: | ||
54 | + - queue-aws-sqs.env | ||
55 | + depends_on: | ||
56 | + - zookeeper | ||
57 | + tb-http-transport1: | ||
58 | + env_file: | ||
59 | + - queue-aws-sqs.env | ||
60 | + depends_on: | ||
61 | + - zookeeper | ||
62 | + tb-http-transport2: | ||
63 | + env_file: | ||
64 | + - queue-aws-sqs.env | ||
65 | + depends_on: | ||
66 | + - zookeeper | ||
67 | + tb-coap-transport: | ||
68 | + env_file: | ||
69 | + - queue-aws-sqs.env | ||
70 | + depends_on: | ||
71 | + - zookeeper |
@@ -28,27 +28,27 @@ services: | @@ -28,27 +28,27 @@ services: | ||
28 | env_file: | 28 | env_file: |
29 | - tb-node.cassandra.env | 29 | - tb-node.cassandra.env |
30 | depends_on: | 30 | depends_on: |
31 | - - kafka | 31 | + - zookeeper |
32 | - redis | 32 | - redis |
33 | - cassandra | 33 | - cassandra |
34 | tb-core2: | 34 | tb-core2: |
35 | env_file: | 35 | env_file: |
36 | - tb-node.cassandra.env | 36 | - tb-node.cassandra.env |
37 | depends_on: | 37 | depends_on: |
38 | - - kafka | 38 | + - zookeeper |
39 | - redis | 39 | - redis |
40 | - cassandra | 40 | - cassandra |
41 | tb-rule-engine1: | 41 | tb-rule-engine1: |
42 | env_file: | 42 | env_file: |
43 | - tb-node.cassandra.env | 43 | - tb-node.cassandra.env |
44 | depends_on: | 44 | depends_on: |
45 | - - kafka | 45 | + - zookeeper |
46 | - redis | 46 | - redis |
47 | - cassandra | 47 | - cassandra |
48 | tb-rule-engine2: | 48 | tb-rule-engine2: |
49 | env_file: | 49 | env_file: |
50 | - tb-node.cassandra.env | 50 | - tb-node.cassandra.env |
51 | depends_on: | 51 | depends_on: |
52 | - - kafka | 52 | + - zookeeper |
53 | - redis | 53 | - redis |
54 | - cassandra | 54 | - cassandra |
docker/docker-compose.kafka.yml
0 → 100644
1 | +# | ||
2 | +# Copyright © 2016-2020 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 | + | ||
17 | +version: '2.2' | ||
18 | + | ||
19 | +services: | ||
20 | + kafka: | ||
21 | + restart: always | ||
22 | + image: "wurstmeister/kafka:2.12-2.3.0" | ||
23 | + ports: | ||
24 | + - "9092:9092" | ||
25 | + env_file: | ||
26 | + - kafka.env | ||
27 | + depends_on: | ||
28 | + - zookeeper | ||
29 | + tb-js-executor: | ||
30 | + env_file: | ||
31 | + - queue-kafka.env | ||
32 | + depends_on: | ||
33 | + - kafka | ||
34 | + tb-core1: | ||
35 | + env_file: | ||
36 | + - queue-kafka.env | ||
37 | + depends_on: | ||
38 | + - kafka | ||
39 | + - redis | ||
40 | + tb-core2: | ||
41 | + env_file: | ||
42 | + - queue-kafka.env | ||
43 | + depends_on: | ||
44 | + - kafka | ||
45 | + - redis | ||
46 | + tb-rule-engine1: | ||
47 | + env_file: | ||
48 | + - queue-kafka.env | ||
49 | + depends_on: | ||
50 | + - kafka | ||
51 | + - redis | ||
52 | + tb-rule-engine2: | ||
53 | + env_file: | ||
54 | + - queue-kafka.env | ||
55 | + depends_on: | ||
56 | + - kafka | ||
57 | + - redis | ||
58 | + tb-mqtt-transport1: | ||
59 | + env_file: | ||
60 | + - queue-kafka.env | ||
61 | + depends_on: | ||
62 | + - kafka | ||
63 | + tb-mqtt-transport2: | ||
64 | + env_file: | ||
65 | + - queue-kafka.env | ||
66 | + depends_on: | ||
67 | + - kafka | ||
68 | + tb-http-transport1: | ||
69 | + env_file: | ||
70 | + - queue-kafka.env | ||
71 | + depends_on: | ||
72 | + - kafka | ||
73 | + tb-http-transport2: | ||
74 | + env_file: | ||
75 | + - queue-kafka.env | ||
76 | + depends_on: | ||
77 | + - kafka | ||
78 | + tb-coap-transport: | ||
79 | + env_file: | ||
80 | + - queue-kafka.env | ||
81 | + depends_on: | ||
82 | + - kafka |
@@ -31,27 +31,27 @@ services: | @@ -31,27 +31,27 @@ services: | ||
31 | env_file: | 31 | env_file: |
32 | - tb-node.postgres.env | 32 | - tb-node.postgres.env |
33 | depends_on: | 33 | depends_on: |
34 | - - kafka | 34 | + - zookeeper |
35 | - redis | 35 | - redis |
36 | - postgres | 36 | - postgres |
37 | tb-core2: | 37 | tb-core2: |
38 | env_file: | 38 | env_file: |
39 | - tb-node.postgres.env | 39 | - tb-node.postgres.env |
40 | depends_on: | 40 | depends_on: |
41 | - - kafka | 41 | + - zookeeper |
42 | - redis | 42 | - redis |
43 | - postgres | 43 | - postgres |
44 | tb-rule-engine1: | 44 | tb-rule-engine1: |
45 | env_file: | 45 | env_file: |
46 | - tb-node.postgres.env | 46 | - tb-node.postgres.env |
47 | depends_on: | 47 | depends_on: |
48 | - - kafka | 48 | + - zookeeper |
49 | - redis | 49 | - redis |
50 | - postgres | 50 | - postgres |
51 | tb-rule-engine2: | 51 | tb-rule-engine2: |
52 | env_file: | 52 | env_file: |
53 | - tb-node.postgres.env | 53 | - tb-node.postgres.env |
54 | depends_on: | 54 | depends_on: |
55 | - - kafka | 55 | + - zookeeper |
56 | - redis | 56 | - redis |
57 | - postgres | 57 | - postgres |
docker/docker-compose.pubsub.yml
0 → 100644
1 | +# | ||
2 | +# Copyright © 2016-2020 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 | + | ||
17 | +version: '2.2' | ||
18 | + | ||
19 | +services: | ||
20 | + tb-js-executor: | ||
21 | + env_file: | ||
22 | + - queue-pubsub.env | ||
23 | + tb-core1: | ||
24 | + env_file: | ||
25 | + - queue-pubsub.env | ||
26 | + depends_on: | ||
27 | + - zookeeper | ||
28 | + - redis | ||
29 | + tb-core2: | ||
30 | + env_file: | ||
31 | + - queue-pubsub.env | ||
32 | + depends_on: | ||
33 | + - zookeeper | ||
34 | + - redis | ||
35 | + tb-rule-engine1: | ||
36 | + env_file: | ||
37 | + - queue-pubsub.env | ||
38 | + depends_on: | ||
39 | + - zookeeper | ||
40 | + - redis | ||
41 | + tb-rule-engine2: | ||
42 | + env_file: | ||
43 | + - queue-pubsub.env | ||
44 | + depends_on: | ||
45 | + - zookeeper | ||
46 | + - redis | ||
47 | + tb-mqtt-transport1: | ||
48 | + env_file: | ||
49 | + - queue-pubsub.env | ||
50 | + depends_on: | ||
51 | + - zookeeper | ||
52 | + tb-mqtt-transport2: | ||
53 | + env_file: | ||
54 | + - queue-pubsub.env | ||
55 | + depends_on: | ||
56 | + - zookeeper | ||
57 | + tb-http-transport1: | ||
58 | + env_file: | ||
59 | + - queue-pubsub.env | ||
60 | + depends_on: | ||
61 | + - zookeeper | ||
62 | + tb-http-transport2: | ||
63 | + env_file: | ||
64 | + - queue-pubsub.env | ||
65 | + depends_on: | ||
66 | + - zookeeper | ||
67 | + tb-coap-transport: | ||
68 | + env_file: | ||
69 | + - queue-pubsub.env | ||
70 | + depends_on: | ||
71 | + - zookeeper |
docker/docker-compose.rabbitmq.yml
0 → 100644
1 | +# | ||
2 | +# Copyright © 2016-2020 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 | + | ||
17 | +version: '2.2' | ||
18 | + | ||
19 | +services: | ||
20 | + tb-js-executor: | ||
21 | + env_file: | ||
22 | + - queue-rabbitmq.env | ||
23 | + tb-core1: | ||
24 | + env_file: | ||
25 | + - queue-rabbitmq.env | ||
26 | + depends_on: | ||
27 | + - zookeeper | ||
28 | + - redis | ||
29 | + tb-core2: | ||
30 | + env_file: | ||
31 | + - queue-rabbitmq.env | ||
32 | + depends_on: | ||
33 | + - zookeeper | ||
34 | + - redis | ||
35 | + tb-rule-engine1: | ||
36 | + env_file: | ||
37 | + - queue-rabbitmq.env | ||
38 | + depends_on: | ||
39 | + - zookeeper | ||
40 | + - redis | ||
41 | + tb-rule-engine2: | ||
42 | + env_file: | ||
43 | + - queue-rabbitmq.env | ||
44 | + depends_on: | ||
45 | + - zookeeper | ||
46 | + - redis | ||
47 | + tb-mqtt-transport1: | ||
48 | + env_file: | ||
49 | + - queue-rabbitmq.env | ||
50 | + depends_on: | ||
51 | + - zookeeper | ||
52 | + tb-mqtt-transport2: | ||
53 | + env_file: | ||
54 | + - queue-rabbitmq.env | ||
55 | + depends_on: | ||
56 | + - zookeeper | ||
57 | + tb-http-transport1: | ||
58 | + env_file: | ||
59 | + - queue-rabbitmq.env | ||
60 | + depends_on: | ||
61 | + - zookeeper | ||
62 | + tb-http-transport2: | ||
63 | + env_file: | ||
64 | + - queue-rabbitmq.env | ||
65 | + depends_on: | ||
66 | + - zookeeper | ||
67 | + tb-coap-transport: | ||
68 | + env_file: | ||
69 | + - queue-rabbitmq.env | ||
70 | + depends_on: | ||
71 | + - zookeeper |
docker/docker-compose.service-bus.yml
0 → 100644
1 | +# | ||
2 | +# Copyright © 2016-2020 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 | + | ||
17 | +version: '2.2' | ||
18 | + | ||
19 | +services: | ||
20 | + tb-js-executor: | ||
21 | + env_file: | ||
22 | + - queue-service-bus.env | ||
23 | + tb-core1: | ||
24 | + env_file: | ||
25 | + - queue-service-bus.env | ||
26 | + depends_on: | ||
27 | + - zookeeper | ||
28 | + - redis | ||
29 | + tb-core2: | ||
30 | + env_file: | ||
31 | + - queue-service-bus.env | ||
32 | + depends_on: | ||
33 | + - zookeeper | ||
34 | + - redis | ||
35 | + tb-rule-engine1: | ||
36 | + env_file: | ||
37 | + - queue-service-bus.env | ||
38 | + depends_on: | ||
39 | + - zookeeper | ||
40 | + - redis | ||
41 | + tb-rule-engine2: | ||
42 | + env_file: | ||
43 | + - queue-service-bus.env | ||
44 | + depends_on: | ||
45 | + - zookeeper | ||
46 | + - redis | ||
47 | + tb-mqtt-transport1: | ||
48 | + env_file: | ||
49 | + - queue-service-bus.env | ||
50 | + depends_on: | ||
51 | + - zookeeper | ||
52 | + tb-mqtt-transport2: | ||
53 | + env_file: | ||
54 | + - queue-service-bus.env | ||
55 | + depends_on: | ||
56 | + - zookeeper | ||
57 | + tb-http-transport1: | ||
58 | + env_file: | ||
59 | + - queue-service-bus.env | ||
60 | + depends_on: | ||
61 | + - zookeeper | ||
62 | + tb-http-transport2: | ||
63 | + env_file: | ||
64 | + - queue-service-bus.env | ||
65 | + depends_on: | ||
66 | + - zookeeper | ||
67 | + tb-coap-transport: | ||
68 | + env_file: | ||
69 | + - queue-service-bus.env | ||
70 | + depends_on: | ||
71 | + - zookeeper |
@@ -26,15 +26,6 @@ services: | @@ -26,15 +26,6 @@ services: | ||
26 | environment: | 26 | environment: |
27 | ZOO_MY_ID: 1 | 27 | ZOO_MY_ID: 1 |
28 | ZOO_SERVERS: server.1=zookeeper:2888:3888;zookeeper:2181 | 28 | ZOO_SERVERS: server.1=zookeeper:2888:3888;zookeeper:2181 |
29 | - kafka: | ||
30 | - restart: always | ||
31 | - image: "wurstmeister/kafka:2.12-2.3.0" | ||
32 | - ports: | ||
33 | - - "9092:9092" | ||
34 | - env_file: | ||
35 | - - kafka.env | ||
36 | - depends_on: | ||
37 | - - zookeeper | ||
38 | redis: | 29 | redis: |
39 | restart: always | 30 | restart: always |
40 | image: redis:4.0 | 31 | image: redis:4.0 |
@@ -46,8 +37,6 @@ services: | @@ -46,8 +37,6 @@ services: | ||
46 | scale: 20 | 37 | scale: 20 |
47 | env_file: | 38 | env_file: |
48 | - tb-js-executor.env | 39 | - tb-js-executor.env |
49 | - depends_on: | ||
50 | - - kafka | ||
51 | tb-core1: | 40 | tb-core1: |
52 | restart: always | 41 | restart: always |
53 | image: "${DOCKER_REPO}/${TB_NODE_DOCKER_NAME}:${TB_VERSION}" | 42 | image: "${DOCKER_REPO}/${TB_NODE_DOCKER_NAME}:${TB_VERSION}" |
@@ -67,7 +56,7 @@ services: | @@ -67,7 +56,7 @@ services: | ||
67 | - ./tb-node/conf:/config | 56 | - ./tb-node/conf:/config |
68 | - ./tb-node/log:/var/log/thingsboard | 57 | - ./tb-node/log:/var/log/thingsboard |
69 | depends_on: | 58 | depends_on: |
70 | - - kafka | 59 | + - zookeeper |
71 | - redis | 60 | - redis |
72 | - tb-js-executor | 61 | - tb-js-executor |
73 | - tb-rule-engine1 | 62 | - tb-rule-engine1 |
@@ -91,7 +80,7 @@ services: | @@ -91,7 +80,7 @@ services: | ||
91 | - ./tb-node/conf:/config | 80 | - ./tb-node/conf:/config |
92 | - ./tb-node/log:/var/log/thingsboard | 81 | - ./tb-node/log:/var/log/thingsboard |
93 | depends_on: | 82 | depends_on: |
94 | - - kafka | 83 | + - zookeeper |
95 | - redis | 84 | - redis |
96 | - tb-js-executor | 85 | - tb-js-executor |
97 | - tb-rule-engine1 | 86 | - tb-rule-engine1 |
@@ -115,7 +104,7 @@ services: | @@ -115,7 +104,7 @@ services: | ||
115 | - ./tb-node/conf:/config | 104 | - ./tb-node/conf:/config |
116 | - ./tb-node/log:/var/log/thingsboard | 105 | - ./tb-node/log:/var/log/thingsboard |
117 | depends_on: | 106 | depends_on: |
118 | - - kafka | 107 | + - zookeeper |
119 | - redis | 108 | - redis |
120 | - tb-js-executor | 109 | - tb-js-executor |
121 | tb-rule-engine2: | 110 | tb-rule-engine2: |
@@ -137,7 +126,7 @@ services: | @@ -137,7 +126,7 @@ services: | ||
137 | - ./tb-node/conf:/config | 126 | - ./tb-node/conf:/config |
138 | - ./tb-node/log:/var/log/thingsboard | 127 | - ./tb-node/log:/var/log/thingsboard |
139 | depends_on: | 128 | depends_on: |
140 | - - kafka | 129 | + - zookeeper |
141 | - redis | 130 | - redis |
142 | - tb-js-executor | 131 | - tb-js-executor |
143 | tb-mqtt-transport1: | 132 | tb-mqtt-transport1: |
@@ -153,7 +142,7 @@ services: | @@ -153,7 +142,7 @@ services: | ||
153 | - ./tb-transports/mqtt/conf:/config | 142 | - ./tb-transports/mqtt/conf:/config |
154 | - ./tb-transports/mqtt/log:/var/log/tb-mqtt-transport | 143 | - ./tb-transports/mqtt/log:/var/log/tb-mqtt-transport |
155 | depends_on: | 144 | depends_on: |
156 | - - kafka | 145 | + - zookeeper |
157 | tb-mqtt-transport2: | 146 | tb-mqtt-transport2: |
158 | restart: always | 147 | restart: always |
159 | image: "${DOCKER_REPO}/${MQTT_TRANSPORT_DOCKER_NAME}:${TB_VERSION}" | 148 | image: "${DOCKER_REPO}/${MQTT_TRANSPORT_DOCKER_NAME}:${TB_VERSION}" |
@@ -167,7 +156,7 @@ services: | @@ -167,7 +156,7 @@ services: | ||
167 | - ./tb-transports/mqtt/conf:/config | 156 | - ./tb-transports/mqtt/conf:/config |
168 | - ./tb-transports/mqtt/log:/var/log/tb-mqtt-transport | 157 | - ./tb-transports/mqtt/log:/var/log/tb-mqtt-transport |
169 | depends_on: | 158 | depends_on: |
170 | - - kafka | 159 | + - zookeeper |
171 | tb-http-transport1: | 160 | tb-http-transport1: |
172 | restart: always | 161 | restart: always |
173 | image: "${DOCKER_REPO}/${HTTP_TRANSPORT_DOCKER_NAME}:${TB_VERSION}" | 162 | image: "${DOCKER_REPO}/${HTTP_TRANSPORT_DOCKER_NAME}:${TB_VERSION}" |
@@ -181,7 +170,7 @@ services: | @@ -181,7 +170,7 @@ services: | ||
181 | - ./tb-transports/http/conf:/config | 170 | - ./tb-transports/http/conf:/config |
182 | - ./tb-transports/http/log:/var/log/tb-http-transport | 171 | - ./tb-transports/http/log:/var/log/tb-http-transport |
183 | depends_on: | 172 | depends_on: |
184 | - - kafka | 173 | + - zookeeper |
185 | tb-http-transport2: | 174 | tb-http-transport2: |
186 | restart: always | 175 | restart: always |
187 | image: "${DOCKER_REPO}/${HTTP_TRANSPORT_DOCKER_NAME}:${TB_VERSION}" | 176 | image: "${DOCKER_REPO}/${HTTP_TRANSPORT_DOCKER_NAME}:${TB_VERSION}" |
@@ -195,7 +184,7 @@ services: | @@ -195,7 +184,7 @@ services: | ||
195 | - ./tb-transports/http/conf:/config | 184 | - ./tb-transports/http/conf:/config |
196 | - ./tb-transports/http/log:/var/log/tb-http-transport | 185 | - ./tb-transports/http/log:/var/log/tb-http-transport |
197 | depends_on: | 186 | depends_on: |
198 | - - kafka | 187 | + - zookeeper |
199 | tb-coap-transport: | 188 | tb-coap-transport: |
200 | restart: always | 189 | restart: always |
201 | image: "${DOCKER_REPO}/${COAP_TRANSPORT_DOCKER_NAME}:${TB_VERSION}" | 190 | image: "${DOCKER_REPO}/${COAP_TRANSPORT_DOCKER_NAME}:${TB_VERSION}" |
@@ -209,7 +198,7 @@ services: | @@ -209,7 +198,7 @@ services: | ||
209 | - ./tb-transports/coap/conf:/config | 198 | - ./tb-transports/coap/conf:/config |
210 | - ./tb-transports/coap/log:/var/log/tb-coap-transport | 199 | - ./tb-transports/coap/log:/var/log/tb-coap-transport |
211 | depends_on: | 200 | depends_on: |
212 | - - kafka | 201 | + - zookeeper |
213 | tb-web-ui1: | 202 | tb-web-ui1: |
214 | restart: always | 203 | restart: always |
215 | image: "${DOCKER_REPO}/${WEB_UI_DOCKER_NAME}:${TB_VERSION}" | 204 | image: "${DOCKER_REPO}/${WEB_UI_DOCKER_NAME}:${TB_VERSION}" |
@@ -41,14 +41,16 @@ set -e | @@ -41,14 +41,16 @@ set -e | ||
41 | 41 | ||
42 | source compose-utils.sh | 42 | source compose-utils.sh |
43 | 43 | ||
44 | +ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? | ||
45 | + | ||
44 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? | 46 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? |
45 | 47 | ||
46 | ADDITIONAL_STARTUP_SERVICES=$(additionalStartupServices) || exit $? | 48 | ADDITIONAL_STARTUP_SERVICES=$(additionalStartupServices) || exit $? |
47 | 49 | ||
48 | if [ ! -z "${ADDITIONAL_STARTUP_SERVICES// }" ]; then | 50 | if [ ! -z "${ADDITIONAL_STARTUP_SERVICES// }" ]; then |
49 | - docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS up -d redis $ADDITIONAL_STARTUP_SERVICES | 51 | + docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS up -d redis $ADDITIONAL_STARTUP_SERVICES |
50 | fi | 52 | fi |
51 | 53 | ||
52 | -docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS run --no-deps --rm -e INSTALL_TB=true -e LOAD_DEMO=${loadDemo} tb-core1 | 54 | +docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS run --no-deps --rm -e INSTALL_TB=true -e LOAD_DEMO=${loadDemo} tb-core1 |
53 | 55 | ||
54 | 56 |
@@ -19,6 +19,8 @@ set -e | @@ -19,6 +19,8 @@ set -e | ||
19 | 19 | ||
20 | source compose-utils.sh | 20 | source compose-utils.sh |
21 | 21 | ||
22 | +ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? | ||
23 | + | ||
22 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? | 24 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? |
23 | 25 | ||
24 | -docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS down -v | 26 | +docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS down -v |
@@ -19,6 +19,8 @@ set -e | @@ -19,6 +19,8 @@ set -e | ||
19 | 19 | ||
20 | source compose-utils.sh | 20 | source compose-utils.sh |
21 | 21 | ||
22 | +ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? | ||
23 | + | ||
22 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? | 24 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? |
23 | 25 | ||
24 | -docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS up -d | 26 | +docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS up -d |
@@ -19,6 +19,8 @@ set -e | @@ -19,6 +19,8 @@ set -e | ||
19 | 19 | ||
20 | source compose-utils.sh | 20 | source compose-utils.sh |
21 | 21 | ||
22 | +ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? | ||
23 | + | ||
22 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? | 24 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? |
23 | 25 | ||
24 | -docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS stop | 26 | +docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS stop |
@@ -19,7 +19,9 @@ set -e | @@ -19,7 +19,9 @@ set -e | ||
19 | 19 | ||
20 | source compose-utils.sh | 20 | source compose-utils.sh |
21 | 21 | ||
22 | +ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? | ||
23 | + | ||
22 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? | 24 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? |
23 | 25 | ||
24 | -docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS pull $@ | ||
25 | -docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS up -d --no-deps --build $@ | 26 | +docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS pull $@ |
27 | +docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS up -d --no-deps --build $@ |
@@ -40,12 +40,14 @@ set -e | @@ -40,12 +40,14 @@ set -e | ||
40 | 40 | ||
41 | source compose-utils.sh | 41 | source compose-utils.sh |
42 | 42 | ||
43 | +ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? | ||
44 | + | ||
43 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? | 45 | ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? |
44 | 46 | ||
45 | ADDITIONAL_STARTUP_SERVICES=$(additionalStartupServices) || exit $? | 47 | ADDITIONAL_STARTUP_SERVICES=$(additionalStartupServices) || exit $? |
46 | 48 | ||
47 | -docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS pull tb-core1 | 49 | +docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS pull tb-core1 |
48 | 50 | ||
49 | -docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS up -d redis $ADDITIONAL_STARTUP_SERVICES | 51 | +docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS up -d redis $ADDITIONAL_STARTUP_SERVICES |
50 | 52 | ||
51 | -docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS run --no-deps --rm -e UPGRADE_TB=true -e FROM_VERSION=${fromVersion} tb-core1 | 53 | +docker-compose -f docker-compose.yml $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS run --no-deps --rm -e UPGRADE_TB=true -e FROM_VERSION=${fromVersion} tb-core1 |
docker/queue-aws-sqs.env
0 → 100644
docker/queue-kafka.env
0 → 100644
docker/queue-pubsub.env
0 → 100644
docker/queue-rabbitmq.env
0 → 100644
docker/queue-service-bus.env
0 → 100644