Commit a9a864e81f2ae89f60cac743ab5e4add9afc09af
Committed by
GitHub
Merge pull request #5065 from volodymyr-babak/mail-setting-fix
[3.3.0] Fixed fetch of admin settings
Showing
6 changed files
with
99 additions
and
28 deletions
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.service.edge; |
17 | 17 | |
18 | +import freemarker.template.Configuration; | |
18 | 19 | import lombok.Data; |
19 | 20 | import org.springframework.beans.factory.annotation.Autowired; |
20 | 21 | import org.springframework.context.annotation.Lazy; |
... | ... | @@ -66,6 +67,9 @@ public class EdgeContextComponent { |
66 | 67 | private AdminSettingsService adminSettingsService; |
67 | 68 | |
68 | 69 | @Autowired |
70 | + private Configuration freemarkerConfig; | |
71 | + | |
72 | + @Autowired | |
69 | 73 | private AssetService assetService; |
70 | 74 | |
71 | 75 | @Autowired | ... | ... |
... | ... | @@ -50,7 +50,7 @@ public class EdgeSyncCursor { |
50 | 50 | fetchers.add(new CustomerEdgeEventFetcher()); |
51 | 51 | fetchers.add(new CustomerUsersEdgeEventFetcher(ctx.getUserService(), edge.getCustomerId())); |
52 | 52 | } |
53 | - fetchers.add(new AdminSettingsEdgeEventFetcher(ctx.getAdminSettingsService())); | |
53 | + fetchers.add(new AdminSettingsEdgeEventFetcher(ctx.getAdminSettingsService(), ctx.getFreemarkerConfig())); | |
54 | 54 | fetchers.add(new AssetsEdgeEventFetcher(ctx.getAssetService())); |
55 | 55 | fetchers.add(new DashboardsEdgeEventFetcher(ctx.getDashboardService())); |
56 | 56 | } | ... | ... |
... | ... | @@ -19,12 +19,12 @@ import com.datastax.oss.driver.api.core.uuid.Uuids; |
19 | 19 | import com.fasterxml.jackson.databind.JsonNode; |
20 | 20 | import com.fasterxml.jackson.databind.ObjectMapper; |
21 | 21 | import com.fasterxml.jackson.databind.node.ObjectNode; |
22 | +import freemarker.template.Configuration; | |
23 | +import freemarker.template.Template; | |
22 | 24 | import lombok.AllArgsConstructor; |
23 | 25 | import lombok.extern.slf4j.Slf4j; |
24 | -import org.apache.commons.io.FileUtils; | |
25 | 26 | import org.apache.commons.lang3.StringUtils; |
26 | 27 | import org.apache.commons.lang3.text.WordUtils; |
27 | -import org.springframework.core.io.DefaultResourceLoader; | |
28 | 28 | import org.thingsboard.server.common.data.AdminSettings; |
29 | 29 | import org.thingsboard.server.common.data.edge.Edge; |
30 | 30 | import org.thingsboard.server.common.data.edge.EdgeEvent; |
... | ... | @@ -37,9 +37,8 @@ import org.thingsboard.server.common.data.page.PageLink; |
37 | 37 | import org.thingsboard.server.dao.settings.AdminSettingsService; |
38 | 38 | import org.thingsboard.server.service.edge.rpc.EdgeEventUtils; |
39 | 39 | |
40 | -import java.io.File; | |
41 | -import java.nio.charset.StandardCharsets; | |
42 | 40 | import java.util.ArrayList; |
41 | +import java.util.Arrays; | |
43 | 42 | import java.util.HashMap; |
44 | 43 | import java.util.List; |
45 | 44 | import java.util.Map; |
... | ... | @@ -53,6 +52,23 @@ public class AdminSettingsEdgeEventFetcher implements EdgeEventFetcher { |
53 | 52 | private static final ObjectMapper mapper = new ObjectMapper(); |
54 | 53 | |
55 | 54 | private final AdminSettingsService adminSettingsService; |
55 | + private final Configuration freemarkerConfig; | |
56 | + | |
57 | + private static Pattern startPattern = Pattern.compile("<div class=\"content\".*?>"); | |
58 | + private static Pattern endPattern = Pattern.compile("<div class=\"footer\".*?>"); | |
59 | + | |
60 | + private static List<String> templatesNames = Arrays.asList( | |
61 | + "account.activated.ftl", | |
62 | + "account.lockout.ftl", | |
63 | + "activation.ftl", | |
64 | + "password.was.reset.ftl", | |
65 | + "reset.password.ftl", | |
66 | + "test.ftl"); | |
67 | + | |
68 | + // TODO: fix format of next templates | |
69 | + // "state.disabled.ftl", | |
70 | + // "state.enabled.ftl", | |
71 | + // "state.warning.ftl", | |
56 | 72 | |
57 | 73 | @Override |
58 | 74 | public PageLink getPageLink(int pageSize) { |
... | ... | @@ -85,23 +101,16 @@ public class AdminSettingsEdgeEventFetcher implements EdgeEventFetcher { |
85 | 101 | |
86 | 102 | private AdminSettings loadMailTemplates() throws Exception { |
87 | 103 | Map<String, Object> mailTemplates = new HashMap<>(); |
88 | - Pattern startPattern = Pattern.compile("<div class=\"content\".*?>"); | |
89 | - Pattern endPattern = Pattern.compile("<div class=\"footer\".*?>"); | |
90 | - File[] files = new DefaultResourceLoader().getResource("classpath:/templates/").getFile().listFiles(); | |
91 | - for (File file : files) { | |
92 | - Map<String, String> mailTemplate = new HashMap<>(); | |
93 | - String name = validateName(file.getName()); | |
94 | - String stringTemplate = FileUtils.readFileToString(file, StandardCharsets.UTF_8); | |
95 | - Matcher start = startPattern.matcher(stringTemplate); | |
96 | - Matcher end = endPattern.matcher(stringTemplate); | |
97 | - if (start.find() && end.find()) { | |
98 | - String body = StringUtils.substringBetween(stringTemplate, start.group(), end.group()).replaceAll("\t", ""); | |
99 | - String subject = StringUtils.substringBetween(body, "<h2>", "</h2>"); | |
100 | - mailTemplate.put("subject", subject); | |
101 | - mailTemplate.put("body", body); | |
102 | - mailTemplates.put(name, mailTemplate); | |
103 | - } else { | |
104 | - log.error("Can't load mail template from file {}", file.getName()); | |
104 | + for (String templatesName : templatesNames) { | |
105 | + Template template = freemarkerConfig.getTemplate(templatesName); | |
106 | + if (template != null) { | |
107 | + String name = validateName(template.getName()); | |
108 | + Map<String, String> mailTemplate = getMailTemplateFromFile(template.getRootTreeNode().toString()); | |
109 | + if (mailTemplate != null) { | |
110 | + mailTemplates.put(name, mailTemplate); | |
111 | + } else { | |
112 | + log.error("Can't load mail template from file {}", template.getName()); | |
113 | + } | |
105 | 114 | } |
106 | 115 | } |
107 | 116 | AdminSettings adminSettings = new AdminSettings(); |
... | ... | @@ -111,9 +120,24 @@ public class AdminSettingsEdgeEventFetcher implements EdgeEventFetcher { |
111 | 120 | return adminSettings; |
112 | 121 | } |
113 | 122 | |
123 | + private Map<String, String> getMailTemplateFromFile(String stringTemplate) { | |
124 | + Map<String, String> mailTemplate = new HashMap<>(); | |
125 | + Matcher start = startPattern.matcher(stringTemplate); | |
126 | + Matcher end = endPattern.matcher(stringTemplate); | |
127 | + if (start.find() && end.find()) { | |
128 | + String body = StringUtils.substringBetween(stringTemplate, start.group(), end.group()).replaceAll("\t", ""); | |
129 | + String subject = StringUtils.substringBetween(body, "<h2>", "</h2>"); | |
130 | + mailTemplate.put("subject", subject); | |
131 | + mailTemplate.put("body", body); | |
132 | + } else { | |
133 | + return null; | |
134 | + } | |
135 | + return mailTemplate; | |
136 | + } | |
137 | + | |
114 | 138 | private String validateName(String name) throws Exception { |
115 | 139 | StringBuilder nameBuilder = new StringBuilder(); |
116 | - name = name.replace(".vm", ""); | |
140 | + name = name.replace(".ftl", ""); | |
117 | 141 | String[] nameParts = name.split("\\."); |
118 | 142 | if (nameParts.length >= 1) { |
119 | 143 | nameBuilder.append(nameParts[0]); | ... | ... |
... | ... | @@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.page.PageLink; |
37 | 37 | import org.thingsboard.server.common.data.security.Authority; |
38 | 38 | import org.thingsboard.server.dao.model.ModelConstants; |
39 | 39 | import org.thingsboard.server.edge.imitator.EdgeImitator; |
40 | +import org.thingsboard.server.gen.edge.v1.AdminSettingsUpdateMsg; | |
40 | 41 | import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg; |
41 | 42 | import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg; |
42 | 43 | import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; |
... | ... | @@ -672,26 +673,26 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest { |
672 | 673 | EdgeImitator edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); |
673 | 674 | edgeImitator.ignoreType(UserCredentialsUpdateMsg.class); |
674 | 675 | |
675 | - edgeImitator.expectMessageAmount(7); | |
676 | + edgeImitator.expectMessageAmount(11); | |
676 | 677 | edgeImitator.connect(); |
677 | 678 | Assert.assertTrue(edgeImitator.waitForMessages()); |
678 | 679 | |
679 | - Assert.assertEquals(7, edgeImitator.getDownlinkMsgs().size()); | |
680 | 680 | Assert.assertEquals(2, edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class).size()); // one msg during sync process, another from edge creation |
681 | 681 | Assert.assertEquals(1, edgeImitator.findAllMessagesByType(DeviceProfileUpdateMsg.class).size()); // one msg during sync process for 'default' device profile |
682 | 682 | Assert.assertEquals(1, edgeImitator.findAllMessagesByType(DeviceUpdateMsg.class).size()); // one msg once device assigned to edge |
683 | 683 | Assert.assertEquals(2, edgeImitator.findAllMessagesByType(AssetUpdateMsg.class).size()); // two msgs - one during sync process, and one more once asset assigned to edge |
684 | 684 | Assert.assertEquals(1, edgeImitator.findAllMessagesByType(UserUpdateMsg.class).size()); // one msg during sync process for tenant admin user |
685 | + Assert.assertEquals(4, edgeImitator.findAllMessagesByType(AdminSettingsUpdateMsg.class).size()); | |
685 | 686 | |
686 | - edgeImitator.expectMessageAmount(4); | |
687 | + edgeImitator.expectMessageAmount(8); | |
687 | 688 | doPost("/api/edge/sync/" + edge.getId()); |
688 | 689 | Assert.assertTrue(edgeImitator.waitForMessages()); |
689 | 690 | |
690 | - Assert.assertEquals(4, edgeImitator.getDownlinkMsgs().size()); | |
691 | 691 | Assert.assertEquals(1, edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class).size()); |
692 | 692 | Assert.assertEquals(1, edgeImitator.findAllMessagesByType(DeviceProfileUpdateMsg.class).size()); |
693 | 693 | Assert.assertEquals(1, edgeImitator.findAllMessagesByType(AssetUpdateMsg.class).size()); |
694 | 694 | Assert.assertEquals(1, edgeImitator.findAllMessagesByType(UserUpdateMsg.class).size()); |
695 | + Assert.assertEquals(4, edgeImitator.findAllMessagesByType(AdminSettingsUpdateMsg.class).size()); | |
695 | 696 | |
696 | 697 | edgeImitator.allowIgnoredTypes(); |
697 | 698 | try { | ... | ... |
... | ... | @@ -86,6 +86,7 @@ import org.thingsboard.server.common.transport.adaptor.JsonConverter; |
86 | 86 | import org.thingsboard.server.controller.AbstractControllerTest; |
87 | 87 | import org.thingsboard.server.dao.edge.EdgeEventService; |
88 | 88 | import org.thingsboard.server.edge.imitator.EdgeImitator; |
89 | +import org.thingsboard.server.gen.edge.v1.AdminSettingsUpdateMsg; | |
89 | 90 | import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg; |
90 | 91 | import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg; |
91 | 92 | import org.thingsboard.server.gen.edge.v1.AttributeDeleteMsg; |
... | ... | @@ -172,7 +173,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
172 | 173 | installation(); |
173 | 174 | |
174 | 175 | edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); |
175 | - edgeImitator.expectMessageAmount(9); | |
176 | + edgeImitator.expectMessageAmount(13); | |
176 | 177 | edgeImitator.connect(); |
177 | 178 | |
178 | 179 | testReceivedInitialData(); |
... | ... | @@ -328,9 +329,44 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { |
328 | 329 | |
329 | 330 | testAutoGeneratedCodeByProtobuf(ruleChainUpdateMsg); |
330 | 331 | |
332 | + validateAdminSettings(); | |
333 | + | |
331 | 334 | log.info("Received data checked"); |
332 | 335 | } |
333 | 336 | |
337 | + private void validateAdminSettings() throws JsonProcessingException { | |
338 | + List<AdminSettingsUpdateMsg> adminSettingsUpdateMsgs = edgeImitator.findAllMessagesByType(AdminSettingsUpdateMsg.class); | |
339 | + Assert.assertEquals(4, adminSettingsUpdateMsgs.size()); | |
340 | + | |
341 | + for (AdminSettingsUpdateMsg adminSettingsUpdateMsg : adminSettingsUpdateMsgs) { | |
342 | + if (adminSettingsUpdateMsg.getKey().equals("mail")) { | |
343 | + validateMailAdminSettings(adminSettingsUpdateMsg); | |
344 | + } | |
345 | + if (adminSettingsUpdateMsg.getKey().equals("mailTemplates")) { | |
346 | + validateMailTemplatesAdminSettings(adminSettingsUpdateMsg); | |
347 | + } | |
348 | + } | |
349 | + } | |
350 | + | |
351 | + private void validateMailAdminSettings(AdminSettingsUpdateMsg adminSettingsUpdateMsg) throws JsonProcessingException { | |
352 | + JsonNode jsonNode = mapper.readTree(adminSettingsUpdateMsg.getJsonValue()); | |
353 | + Assert.assertNotNull(jsonNode.get("mailFrom")); | |
354 | + Assert.assertNotNull(jsonNode.get("smtpProtocol")); | |
355 | + Assert.assertNotNull(jsonNode.get("smtpHost")); | |
356 | + Assert.assertNotNull(jsonNode.get("smtpPort")); | |
357 | + Assert.assertNotNull(jsonNode.get("timeout")); | |
358 | + } | |
359 | + | |
360 | + private void validateMailTemplatesAdminSettings(AdminSettingsUpdateMsg adminSettingsUpdateMsg) throws JsonProcessingException { | |
361 | + JsonNode jsonNode = mapper.readTree(adminSettingsUpdateMsg.getJsonValue()); | |
362 | + Assert.assertNotNull(jsonNode.get("accountActivated")); | |
363 | + Assert.assertNotNull(jsonNode.get("accountLockout")); | |
364 | + Assert.assertNotNull(jsonNode.get("activation")); | |
365 | + Assert.assertNotNull(jsonNode.get("passwordWasReset")); | |
366 | + Assert.assertNotNull(jsonNode.get("resetPassword")); | |
367 | + Assert.assertNotNull(jsonNode.get("test")); | |
368 | + } | |
369 | + | |
334 | 370 | private void testDevices() throws Exception { |
335 | 371 | log.info("Testing devices"); |
336 | 372 | ... | ... |
... | ... | @@ -26,6 +26,7 @@ import lombok.extern.slf4j.Slf4j; |
26 | 26 | import org.checkerframework.checker.nullness.qual.Nullable; |
27 | 27 | import org.thingsboard.edge.rpc.EdgeGrpcClient; |
28 | 28 | import org.thingsboard.edge.rpc.EdgeRpcClient; |
29 | +import org.thingsboard.server.gen.edge.v1.AdminSettingsUpdateMsg; | |
29 | 30 | import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg; |
30 | 31 | import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg; |
31 | 32 | import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg; |
... | ... | @@ -167,6 +168,11 @@ public class EdgeImitator { |
167 | 168 | |
168 | 169 | private ListenableFuture<List<Void>> processDownlinkMsg(DownlinkMsg downlinkMsg) { |
169 | 170 | List<ListenableFuture<Void>> result = new ArrayList<>(); |
171 | + if (downlinkMsg.getAdminSettingsUpdateMsgCount() > 0) { | |
172 | + for (AdminSettingsUpdateMsg adminSettingsUpdateMsg : downlinkMsg.getAdminSettingsUpdateMsgList()) { | |
173 | + result.add(saveDownlinkMsg(adminSettingsUpdateMsg)); | |
174 | + } | |
175 | + } | |
170 | 176 | if (downlinkMsg.getDeviceUpdateMsgCount() > 0) { |
171 | 177 | for (DeviceUpdateMsg deviceUpdateMsg : downlinkMsg.getDeviceUpdateMsgList()) { |
172 | 178 | result.add(saveDownlinkMsg(deviceUpdateMsg)); | ... | ... |