Browse Source

Merge pull request #14818 from thingsboard/rc

RC
pull/14973/head
Viacheslav Klimov 7 months ago
committed by GitHub
parent
commit
07a72b2dbb
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java
  2. 4
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/function/AvgAggEntry.java
  3. 4
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/function/MaxAggEntry.java
  4. 4
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/function/MinAggEntry.java
  5. 4
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/function/SumAggEntry.java
  6. 4
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/single/EntityAggregationCalculatedFieldState.java
  7. 84
      application/src/test/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateServiceTest.java
  8. 39
      common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java
  9. 34
      common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java
  10. 49
      common/util/src/main/java/org/thingsboard/common/util/NumberUtils.java
  11. 61
      common/util/src/test/java/org/thingsboard/common/util/NumberUtilsTest.java
  12. 28
      dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java
  13. 5
      ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts
  14. 7
      ui-ngx/src/app/modules/home/pages/admin/two-factor-auth-settings.component.ts
  15. 4
      ui-ngx/src/assets/dashboard/api_usage.json

4
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java

@ -22,13 +22,13 @@ import com.google.common.util.concurrent.ListenableFuture;
import lombok.EqualsAndHashCode;
import net.objecthunter.exp4j.Expression;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.script.api.tbel.TbUtils;
import org.thingsboard.server.actors.TbActorRef;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.cf.configuration.Output;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.service.cf.CalculatedFieldResult;
import org.thingsboard.server.service.cf.TelemetryCalculatedFieldResult;
import org.thingsboard.common.util.NumberUtils;
import java.util.Map;
@ -52,7 +52,7 @@ public class SimpleCalculatedFieldState extends BaseCalculatedFieldState {
double expressionResult = ctx.evaluateSimpleExpression(expression.get(), this);
Output output = ctx.getOutput();
Object result = TbUtils.roundResult(expressionResult, output.getDecimalsByDefault());
Object result = NumberUtils.roundResult(expressionResult, output.getDecimalsByDefault());
JsonNode outputResult = createResultJson(ctx.isUseLatestTs(), output.getName(), result);
return Futures.immediateFuture(TelemetryCalculatedFieldResult.builder()

4
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/function/AvgAggEntry.java

@ -15,8 +15,8 @@
*/
package org.thingsboard.server.service.cf.ctx.state.aggregation.function;
import org.thingsboard.script.api.tbel.TbUtils;
import org.thingsboard.server.common.data.cf.configuration.aggregation.AggFunction;
import org.thingsboard.common.util.NumberUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
@ -37,7 +37,7 @@ public class AvgAggEntry extends BaseAggEntry {
@Override
protected Object prepareResult(Integer precision) {
double result = sum.divide(BigDecimal.valueOf(count), RoundingMode.HALF_UP).doubleValue();
return TbUtils.roundResult(result, precision);
return NumberUtils.roundResult(result, precision);
}
@Override

4
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/function/MaxAggEntry.java

@ -15,8 +15,8 @@
*/
package org.thingsboard.server.service.cf.ctx.state.aggregation.function;
import org.thingsboard.script.api.tbel.TbUtils;
import org.thingsboard.server.common.data.cf.configuration.aggregation.AggFunction;
import org.thingsboard.common.util.NumberUtils;
public class MaxAggEntry extends BaseAggEntry {
@ -31,7 +31,7 @@ public class MaxAggEntry extends BaseAggEntry {
@Override
protected Object prepareResult(Integer precision) {
return TbUtils.roundResult(max, precision);
return NumberUtils.roundResult(max, precision);
}
@Override

4
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/function/MinAggEntry.java

@ -15,8 +15,8 @@
*/
package org.thingsboard.server.service.cf.ctx.state.aggregation.function;
import org.thingsboard.script.api.tbel.TbUtils;
import org.thingsboard.server.common.data.cf.configuration.aggregation.AggFunction;
import org.thingsboard.common.util.NumberUtils;
public class MinAggEntry extends BaseAggEntry {
@ -31,7 +31,7 @@ public class MinAggEntry extends BaseAggEntry {
@Override
protected Object prepareResult(Integer precision) {
return TbUtils.roundResult(min, precision);
return NumberUtils.roundResult(min, precision);
}
@Override

4
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/function/SumAggEntry.java

@ -15,8 +15,8 @@
*/
package org.thingsboard.server.service.cf.ctx.state.aggregation.function;
import org.thingsboard.script.api.tbel.TbUtils;
import org.thingsboard.server.common.data.cf.configuration.aggregation.AggFunction;
import org.thingsboard.common.util.NumberUtils;
import java.math.BigDecimal;
@ -33,7 +33,7 @@ public class SumAggEntry extends BaseAggEntry {
@Override
protected Object prepareResult(Integer precision) {
return TbUtils.roundResult(sum.doubleValue(), precision);
return NumberUtils.roundResult(sum.doubleValue(), precision);
}
@Override

4
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/aggregation/single/EntityAggregationCalculatedFieldState.java

@ -23,7 +23,6 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.common.util.DebugModeUtil;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.script.api.tbel.TbUtils;
import org.thingsboard.script.api.tbel.TbelCfArg;
import org.thingsboard.server.actors.TbActorRef;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
@ -41,6 +40,7 @@ import org.thingsboard.server.service.cf.ctx.state.ArgumentEntry;
import org.thingsboard.server.service.cf.ctx.state.BaseCalculatedFieldState;
import org.thingsboard.server.service.cf.ctx.state.CalculatedFieldCtx;
import org.thingsboard.server.service.cf.ctx.state.SingleValueArgumentEntry;
import org.thingsboard.common.util.NumberUtils;
import java.time.Instant;
import java.time.ZoneId;
@ -291,7 +291,7 @@ public class EntityAggregationCalculatedFieldState extends BaseCalculatedFieldSt
ArgumentEntry argumentEntry = entry.getValue();
if (!argumentEntry.isEmpty()) {
Object resultValue = argumentEntry.getValue() instanceof Number number
? TbUtils.roundResult(number.doubleValue(), precision)
? NumberUtils.roundResult(number.doubleValue(), precision)
: argumentEntry.getValue();
metricsNode.put(metricName, JacksonUtil.toString(resultValue));
}

84
application/src/test/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateServiceTest.java

@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.ApiUsageStateId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileData;
import org.thingsboard.server.common.msg.queue.TbCallback;
@ -40,6 +41,7 @@ import java.lang.reflect.Field;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@ -47,7 +49,10 @@ import static java.time.ZoneOffset.UTC;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoUnit.MONTHS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import static org.junit.Assert.assertEquals;
import static org.thingsboard.server.common.data.ApiFeature.SMS;
import static org.thingsboard.server.common.data.ApiUsageRecordKey.SMS_EXEC_COUNT;
@DaoSqlTest
public class DefaultTbApiUsageStateServiceTest extends AbstractControllerTest {
@ -157,6 +162,85 @@ public class DefaultTbApiUsageStateServiceTest extends AbstractControllerTest {
assertThat(tenantApiUsageState.getNextCycleTs()).isEqualTo(firstOfNextMonth);
}
@Test
public void checkTenantCreatedWithSmsDisabledApiUsage() throws Exception {
TenantProfile tenantProfile = new TenantProfile();
tenantProfile.setName("Test profile");
TenantProfileData tenantProfileData = new TenantProfileData();
DefaultTenantProfileConfiguration config = DefaultTenantProfileConfiguration.builder()
.smsEnabled(false)
.build();
tenantProfileData.setConfiguration(config);
tenantProfile.setProfileData(tenantProfileData);
tenantProfile = doPost("/api/tenantProfile", tenantProfile, TenantProfile.class);
Tenant tenant = new Tenant();
tenant.setTitle("My test tenant");
tenant.setTenantProfileId(tenantProfile.getId());
tenant = saveTenant(tenant);
ApiUsageState apiUsageState = apiUsageStateService.findApiUsageStateByEntityId(tenant.getId());
assertThat(apiUsageState.getSmsExecState()).isEqualTo(ApiUsageStateValue.DISABLED);
TenantId finalTenantId = tenant.getId();
ApiUsageStateId finalApiUsageStateId = apiUsageState.getId();
await().atMost(5, TimeUnit.SECONDS).until(() -> {
Optional<TsKvEntry> smsApiState = tsService.findLatest(finalTenantId, finalApiUsageStateId, SMS.getApiStateKey()).get();
return smsApiState.isPresent() && smsApiState.get().getValueAsString().equals(ApiUsageStateValue.DISABLED.name());
});
await().atMost(5, TimeUnit.SECONDS).until(() -> {
Optional<TsKvEntry> smsApiState = tsService.findLatest(finalTenantId, finalApiUsageStateId, SMS_EXEC_COUNT.getApiLimitKey()).get();
return smsApiState.isPresent() && smsApiState.get().getLongValue().get().equals(0L);
});
// enable SMS and check that the ApiUsageState is updated accordingly
config = DefaultTenantProfileConfiguration.builder()
.smsEnabled(true)
.maxSms(10)
.build();
tenantProfileData.setConfiguration(config);
tenantProfile.setProfileData(tenantProfileData);
doPost("/api/tenantProfile", tenantProfile, TenantProfile.class);
await().atMost(5, TimeUnit.SECONDS).until(() ->
apiUsageStateService.findApiUsageStateByEntityId(finalTenantId).getSmsExecState() == ApiUsageStateValue.ENABLED);
await().atMost(5, TimeUnit.SECONDS).until(() -> {
Optional<TsKvEntry> smsApiState = tsService.findLatest(finalTenantId, finalApiUsageStateId, SMS.getApiStateKey()).get();
return smsApiState.isPresent() && smsApiState.get().getValueAsString().equals(ApiUsageStateValue.ENABLED.name());
});
await().atMost(5, TimeUnit.SECONDS).until(() -> {
Optional<TsKvEntry> smsApiState = tsService.findLatest(finalTenantId, finalApiUsageStateId, SMS_EXEC_COUNT.getApiLimitKey()).get();
return smsApiState.isPresent() && smsApiState.get().getLongValue().get().equals(10L);
});
//disable SMS and check that the ApiUsageState is updated accordingly
config = DefaultTenantProfileConfiguration.builder()
.smsEnabled(false)
.build();
tenantProfileData.setConfiguration(config);
tenantProfile.setProfileData(tenantProfileData);
doPost("/api/tenantProfile", tenantProfile, TenantProfile.class);
await().atMost(5, TimeUnit.SECONDS).until(() ->
apiUsageStateService.findApiUsageStateByEntityId(finalTenantId).getSmsExecState() == ApiUsageStateValue.DISABLED);
await().atMost(5, TimeUnit.SECONDS).until(() -> {
Optional<TsKvEntry> smsApiState = tsService.findLatest(finalTenantId, finalApiUsageStateId, SMS.getApiStateKey()).get();
return smsApiState.isPresent() && smsApiState.get().getValueAsString().equals(ApiUsageStateValue.DISABLED.name());
});
await().atMost(5, TimeUnit.SECONDS).until(() -> {
Optional<TsKvEntry> smsApiState = tsService.findLatest(finalTenantId, finalApiUsageStateId, SMS_EXEC_COUNT.getApiLimitKey()).get();
return smsApiState.isPresent() && smsApiState.get().getLongValue().get().equals(0L);
});
}
private TenantProfile createTenantProfile() {
TenantProfile tenantProfile = new TenantProfile();
tenantProfile.setName("Tenant Profile");

39
common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java

@ -26,6 +26,7 @@ import org.mvel2.execution.ExecutionHashMap;
import org.mvel2.execution.ExecutionLinkedHashSet;
import org.mvel2.util.MethodStub;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.common.util.NumberUtils;
import org.thingsboard.common.util.geo.Coordinates;
import org.thingsboard.common.util.geo.GeoUtil;
import org.thingsboard.common.util.geo.RangeUnit;
@ -35,7 +36,6 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
@ -258,15 +258,13 @@ public class TbUtils {
byte[].class, int.class, int.class)));
parserConfig.addImport("parseBytesLongToDouble", new MethodStub(TbUtils.class.getMethod("parseBytesLongToDouble",
byte[].class, int.class, int.class, boolean.class)));
parserConfig.addImport("toFixed", new MethodStub(TbUtils.class.getMethod("toFixed",
parserConfig.addImport("toFixed", new MethodStub(NumberUtils.class.getMethod("toFixed",
double.class, int.class)));
parserConfig.addImport("toFixed", new MethodStub(TbUtils.class.getMethod("toFixed",
parserConfig.addImport("toFixed", new MethodStub(NumberUtils.class.getMethod("toFixed",
float.class, int.class)));
parserConfig.addImport("toInt", new MethodStub(TbUtils.class.getMethod("toInt",
parserConfig.addImport("toInt", new MethodStub(NumberUtils.class.getMethod("toInt",
double.class)));
parserConfig.addImport("roundResult", new MethodStub(TbUtils.class.getMethod("roundResult",
double.class, Integer.class)));
parserConfig.addImport("isNaN", new MethodStub(TbUtils.class.getMethod("isNaN",
parserConfig.addImport("isNaN", new MethodStub(NumberUtils.class.getMethod("isNaN",
double.class)));
parserConfig.addImport("hexToBytes", new MethodStub(TbUtils.class.getMethod("hexToBytes",
ExecutionContext.class, String.class)));
@ -1176,32 +1174,6 @@ public class TbUtils {
return new String(hexChars, StandardCharsets.UTF_8);
}
public static double toFixed(double value, int precision) {
return BigDecimal.valueOf(value).setScale(precision, RoundingMode.HALF_UP).doubleValue();
}
public static float toFixed(float value, int precision) {
return BigDecimal.valueOf(value).setScale(precision, RoundingMode.HALF_UP).floatValue();
}
public static int toInt(double value) {
return BigDecimal.valueOf(value).setScale(0, RoundingMode.HALF_UP).intValue();
}
public static Object roundResult(double value, Integer precision) {
if (precision == null) {
return value;
}
if (precision.equals(0)) {
return toInt(value);
}
return toFixed(value, precision);
}
public static boolean isNaN(double value) {
return Double.isNaN(value);
}
public static ExecutionHashMap<String, Object> toFlatMap(ExecutionContext ctx, Map<String, Object> json) {
return toFlatMap(ctx, json, new ArrayList<>(), true);
}
@ -1220,7 +1192,6 @@ public class TbUtils {
return map;
}
public static String encodeURI(String uri) {
String encoded = URLEncoder.encode(uri, StandardCharsets.UTF_8);
for (var entry : mdnEncodingReplacements.entrySet()) {

34
common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java

@ -279,13 +279,6 @@ public class TbUtilsTest {
Assertions.assertEquals(0, Float.compare(floatVal, TbUtils.parseLittleEndianHexToFloat(floatValHexRev)));
}
@Test
public void toFixedFloat() {
float actualF = TbUtils.toFixed(floatVal, 3);
Assertions.assertEquals(1, Float.compare(floatVal, actualF));
Assertions.assertEquals(0, Float.compare(29.298f, actualF));
}
@Test
public void parseBytesToFloat() {
byte[] floatValByte = {0x0A};
@ -461,13 +454,6 @@ public class TbUtilsTest {
Assertions.assertEquals(0, Double.compare(doubleVal, TbUtils.parseLittleEndianHexToDouble(longValHexRev)));
}
@Test
public void toFixedDouble() {
double actualD = TbUtils.toFixed(doubleVal, 3);
Assertions.assertEquals(-1, Double.compare(doubleVal, actualD));
Assertions.assertEquals(0, Double.compare(1729.173, actualD));
}
@Test
public void parseBytesToDouble() {
byte[] doubleValByte = {0x0A};
@ -1147,26 +1133,6 @@ public class TbUtilsTest {
Assertions.assertEquals(expected, actual);
}
@Test
public void toInt() {
Assertions.assertEquals(1729, TbUtils.toInt(doubleVal));
Assertions.assertEquals(13, TbUtils.toInt(12.8));
Assertions.assertEquals(28, TbUtils.toInt(28.0));
}
@Test
public void roundResult() {
Assertions.assertEquals(1729.1729, TbUtils.roundResult(doubleVal, null));
Assertions.assertEquals(1729, TbUtils.roundResult(doubleVal, 0));
Assertions.assertEquals(1729.17, TbUtils.roundResult(doubleVal, 2));
}
@Test
public void isNaN() {
assertFalse(TbUtils.isNaN(doubleVal));
assertTrue(TbUtils.isNaN(Double.NaN));
}
@Test
public void isInsidePolygon() {
// outside the polygon

49
common/util/src/main/java/org/thingsboard/common/util/NumberUtils.java

@ -0,0 +1,49 @@
/**
* Copyright © 2016-2026 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.common.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class NumberUtils {
public static boolean isNaN(double value) {
return Double.isNaN(value);
}
public static double toFixed(double value, int precision) {
return BigDecimal.valueOf(value).setScale(precision, RoundingMode.HALF_UP).doubleValue();
}
public static float toFixed(float value, int precision) {
return BigDecimal.valueOf(value).setScale(precision, RoundingMode.HALF_UP).floatValue();
}
public static int toInt(double value) {
return BigDecimal.valueOf(value).setScale(0, RoundingMode.HALF_UP).intValue();
}
public static Object roundResult(double value, Integer precision) {
if (precision == null) {
return value;
}
if (precision.equals(0)) {
return toInt(value);
}
return toFixed(value, precision);
}
}

61
common/util/src/test/java/org/thingsboard/common/util/NumberUtilsTest.java

@ -0,0 +1,61 @@
/**
* Copyright © 2016-2026 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.common.util;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class NumberUtilsTest {
private final Float floatVal = 29.29824f;
private final double doubleVal = 1729.1729;
@Test
public void isNaN() {
assertThat(NumberUtils.isNaN(doubleVal)).isFalse();
assertThat(NumberUtils.isNaN(Double.NaN)).isTrue();
}
@Test
public void toFixedFloat() {
float actualF = NumberUtils.toFixed(floatVal, 3);
assertThat(Float.compare(floatVal, actualF)).isEqualTo(1);
assertThat(Float.compare(29.298f, actualF)).isEqualTo(0);
}
@Test
public void toFixedDouble() {
double actualD = NumberUtils.toFixed(doubleVal, 3);
assertThat(Double.compare(doubleVal, actualD)).isEqualTo(-1);
assertThat(Double.compare(1729.173, actualD)).isEqualTo(0);
}
@Test
public void toInt() {
assertThat(NumberUtils.toInt(doubleVal)).isEqualTo(1729);
assertThat(NumberUtils.toInt(12.8)).isEqualTo(13);
assertThat(NumberUtils.toInt(28.0)).isEqualTo(28);
}
@Test
public void roundResult() {
assertThat(NumberUtils.roundResult(doubleVal, null)).isEqualTo(1729.1729);
assertThat(NumberUtils.roundResult(doubleVal, 0)).isEqualTo(1729);
assertThat(NumberUtils.roundResult(doubleVal, 2)).isEqualTo(1729.17);
}
}

28
dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java

@ -35,7 +35,7 @@ import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
import org.thingsboard.server.common.data.kv.LongDataEntry;
import org.thingsboard.server.common.data.kv.StringDataEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileConfiguration;
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
@ -101,6 +101,21 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A
entityId = Objects.requireNonNullElse(entityId, tenantId);
log.trace("Executing createDefaultUsageRecord [{}]", entityId);
validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
ApiUsageStateValue smsApiUsageState = ApiUsageStateValue.ENABLED;
DefaultTenantProfileConfiguration configuration = null;
if (entityId.getEntityType() == EntityType.TENANT && !entityId.equals(TenantId.SYS_TENANT_ID)) {
tenantId = (TenantId) entityId;
Tenant tenant = tenantService.findTenantById(tenantId);
TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenant.getTenantProfileId().getId());
configuration = (DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration();
if (configuration.getSmsEnabled() != null && !configuration.getSmsEnabled()) {
smsApiUsageState = ApiUsageStateValue.DISABLED;
}
}
ApiUsageState apiUsageState = new ApiUsageState();
apiUsageState.setTenantId(tenantId);
apiUsageState.setEntityId(entityId);
@ -109,7 +124,7 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A
apiUsageState.setJsExecState(ApiUsageStateValue.ENABLED);
apiUsageState.setTbelExecState(ApiUsageStateValue.ENABLED);
apiUsageState.setDbStorageState(ApiUsageStateValue.ENABLED);
apiUsageState.setSmsExecState(ApiUsageStateValue.ENABLED);
apiUsageState.setSmsExecState(smsApiUsageState);
apiUsageState.setEmailExecState(ApiUsageStateValue.ENABLED);
apiUsageState.setAlarmExecState(ApiUsageStateValue.ENABLED);
apiUsageStateValidator.validate(apiUsageState, ApiUsageState::getTenantId);
@ -138,17 +153,12 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A
apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(),
new StringDataEntry(ApiFeature.EMAIL.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(),
new StringDataEntry(ApiFeature.SMS.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
new StringDataEntry(ApiFeature.SMS.getApiStateKey(), smsApiUsageState.name())));
apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(),
new StringDataEntry(ApiFeature.ALARM.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
tsService.save(tenantId, saved.getId(), apiUsageStates, 0L);
if (entityId.getEntityType() == EntityType.TENANT && !entityId.equals(TenantId.SYS_TENANT_ID)) {
tenantId = (TenantId) entityId;
Tenant tenant = tenantService.findTenantById(tenantId);
TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenant.getTenantProfileId().getId());
TenantProfileConfiguration configuration = tenantProfile.getProfileData().getConfiguration();
if (configuration != null) {
List<TsKvEntry> profileThresholds = new ArrayList<>();
for (ApiUsageRecordKey key : ApiUsageRecordKey.values()) {
if (key.getApiLimitKey() == null) continue;

5
ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts

@ -17,7 +17,7 @@
import { Component, forwardRef, Input } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { DefaultTenantProfileConfiguration, FormControlsFrom } from '@shared/models/tenant.model';
import { isDefinedAndNotNull } from '@core/utils';
import { isDefinedAndNotNull, isUndefinedOrNull} from '@core/utils';
import { RateLimitsType } from './rate-limits/rate-limits.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { coerceBoolean } from '@shared/decorators/coercion';
@ -170,6 +170,9 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA
writeValue(value: DefaultTenantProfileConfiguration | null): void {
if (isDefinedAndNotNull(value)) {
if (isUndefinedOrNull(value.smsEnabled)) {
value.smsEnabled = true;
}
this.maxSmsValidation(value.smsEnabled);
this.tenantProfileConfigurationForm.patchValue(value, {emitEvent: false});
}

7
ui-ngx/src/app/modules/home/pages/admin/two-factor-auth-settings.component.ts

@ -83,6 +83,11 @@ export class TwoFactorAuthSettingsComponent extends PageComponent implements OnI
const providers = setting.providers.filter(provider => provider.enable);
providers.forEach(provider => delete provider.enable);
const enforcedUsersFilter = this.twoFaFormGroup.get('enforcedUsersFilter').value;
if (enforcedUsersFilter.filterByTenants) {
enforcedUsersFilter.tenantProfilesIds = null;
} else {
enforcedUsersFilter.tenantsIds = null;
}
delete enforcedUsersFilter.filterByTenants;
const config = Object.assign(setting, {providers}, {enforcedUsersFilter});
this.filterByTenants = this.twoFaFormGroup.get('enforcedUsersFilter.filterByTenants').value;
@ -142,7 +147,7 @@ export class TwoFactorAuthSettingsComponent extends PageComponent implements OnI
verificationCodeCheckRateLimitEnable: [false],
verificationCodeCheckRateLimitNumber: [{value: 3, disabled: true}, this.posIntValidation],
verificationCodeCheckRateLimitTime: [{value: 900, disabled: true}, this.posIntValidation],
minVerificationCodeSendPeriod: ['30', [Validators.required, Validators.min(5), Validators.pattern(/^\d*$/)]],
minVerificationCodeSendPeriod: [30, [Validators.required, Validators.min(5), Validators.pattern(/^\d*$/)]],
providers: this.fb.array([])
});
Object.values(TwoFactorAuthProviderType).forEach(provider => {

4
ui-ngx/src/assets/dashboard/api_usage.json

@ -11412,8 +11412,8 @@
"label": "{i18n:api-usage.sms}",
"state": "sms",
"status": {
"name": "notificationApiState",
"label": "notificationApiState",
"name": "smsApiState",
"label": "smsApiState",
"type": "timeseries",
"settings": {},
"color": "#2196f3"

Loading…
Cancel
Save