Introduce Current user alias
This commit is contained in:
parent
c6f7862cbf
commit
7446e012a6
@ -246,6 +246,28 @@ public class UserController extends BaseController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
|
||||||
|
@RequestMapping(value = "/users", params = {"pageSize", "page"}, method = RequestMethod.GET)
|
||||||
|
@ResponseBody
|
||||||
|
public PageData<User> getUsers(
|
||||||
|
@RequestParam int pageSize,
|
||||||
|
@RequestParam int page,
|
||||||
|
@RequestParam(required = false) String textSearch,
|
||||||
|
@RequestParam(required = false) String sortProperty,
|
||||||
|
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
|
||||||
|
try {
|
||||||
|
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
|
||||||
|
SecurityUser currentUser = getCurrentUser();
|
||||||
|
if (Authority.TENANT_ADMIN.equals(currentUser.getAuthority())) {
|
||||||
|
return checkNotNull(userService.findUsersByTenantId(currentUser.getTenantId(), pageLink));
|
||||||
|
} else {
|
||||||
|
return checkNotNull(userService.findCustomerUsers(currentUser.getTenantId(), currentUser.getCustomerId(), pageLink));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw handleException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasAuthority('SYS_ADMIN')")
|
@PreAuthorize("hasAuthority('SYS_ADMIN')")
|
||||||
@RequestMapping(value = "/tenant/{tenantId}/users", params = {"pageSize", "page"}, method = RequestMethod.GET)
|
@RequestMapping(value = "/tenant/{tenantId}/users", params = {"pageSize", "page"}, method = RequestMethod.GET)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.Customer;
|
|||||||
import org.thingsboard.server.common.data.Device;
|
import org.thingsboard.server.common.data.Device;
|
||||||
import org.thingsboard.server.common.data.EntityView;
|
import org.thingsboard.server.common.data.EntityView;
|
||||||
import org.thingsboard.server.common.data.Tenant;
|
import org.thingsboard.server.common.data.Tenant;
|
||||||
|
import org.thingsboard.server.common.data.User;
|
||||||
import org.thingsboard.server.common.data.asset.Asset;
|
import org.thingsboard.server.common.data.asset.Asset;
|
||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||||
import org.thingsboard.server.common.data.id.AssetId;
|
import org.thingsboard.server.common.data.id.AssetId;
|
||||||
@ -40,6 +41,7 @@ import org.thingsboard.server.common.data.id.EntityViewId;
|
|||||||
import org.thingsboard.server.common.data.id.RuleChainId;
|
import org.thingsboard.server.common.data.id.RuleChainId;
|
||||||
import org.thingsboard.server.common.data.id.RuleNodeId;
|
import org.thingsboard.server.common.data.id.RuleNodeId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
import org.thingsboard.server.common.data.id.UserId;
|
||||||
import org.thingsboard.server.common.data.rule.RuleChain;
|
import org.thingsboard.server.common.data.rule.RuleChain;
|
||||||
import org.thingsboard.server.common.data.rule.RuleNode;
|
import org.thingsboard.server.common.data.rule.RuleNode;
|
||||||
import org.thingsboard.server.controller.HttpValidationCallback;
|
import org.thingsboard.server.controller.HttpValidationCallback;
|
||||||
@ -172,6 +174,9 @@ public class AccessValidator {
|
|||||||
case TENANT:
|
case TENANT:
|
||||||
validateTenant(currentUser, operation, entityId, callback);
|
validateTenant(currentUser, operation, entityId, callback);
|
||||||
return;
|
return;
|
||||||
|
case USER:
|
||||||
|
validateUser(currentUser, operation, entityId, callback);
|
||||||
|
return;
|
||||||
case ENTITY_VIEW:
|
case ENTITY_VIEW:
|
||||||
validateEntityView(currentUser, operation, entityId, callback);
|
validateEntityView(currentUser, operation, entityId, callback);
|
||||||
return;
|
return;
|
||||||
@ -308,6 +313,22 @@ public class AccessValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateUser(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback<ValidationResult> callback) {
|
||||||
|
ListenableFuture<User> userFuture = userService.findUserByIdAsync(currentUser.getTenantId(), new UserId(entityId.getId()));
|
||||||
|
Futures.addCallback(userFuture, getCallback(callback, user -> {
|
||||||
|
if (user == null) {
|
||||||
|
return ValidationResult.entityNotFound("User with requested id wasn't found!");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
accessControlService.checkPermission(currentUser, Resource.USER, operation, entityId, user);
|
||||||
|
} catch (ThingsboardException e) {
|
||||||
|
return ValidationResult.accessDenied(e.getMessage());
|
||||||
|
}
|
||||||
|
return ValidationResult.ok(user);
|
||||||
|
|
||||||
|
}), executor);
|
||||||
|
}
|
||||||
|
|
||||||
private void validateEntityView(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback<ValidationResult> callback) {
|
private void validateEntityView(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback<ValidationResult> callback) {
|
||||||
if (currentUser.isSystemAdmin()) {
|
if (currentUser.isSystemAdmin()) {
|
||||||
callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
|
callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
|
||||||
|
|||||||
@ -52,8 +52,10 @@ public interface UserService {
|
|||||||
UserCredentials replaceUserCredentials(TenantId tenantId, UserCredentials userCredentials);
|
UserCredentials replaceUserCredentials(TenantId tenantId, UserCredentials userCredentials);
|
||||||
|
|
||||||
void deleteUser(TenantId tenantId, UserId userId);
|
void deleteUser(TenantId tenantId, UserId userId);
|
||||||
|
|
||||||
PageData<User> findTenantAdmins(TenantId tenantId, PageLink pageLink);
|
PageData<User> findUsersByTenantId(TenantId tenantId, PageLink pageLink);
|
||||||
|
|
||||||
|
PageData<User> findTenantAdmins(TenantId tenantId, PageLink pageLink);
|
||||||
|
|
||||||
void deleteTenantAdmins(TenantId tenantId);
|
void deleteTenantAdmins(TenantId tenantId);
|
||||||
|
|
||||||
|
|||||||
@ -86,7 +86,7 @@ public class EntityKeyMapping {
|
|||||||
allowedEntityFieldMap.get(EntityType.TENANT).add(REGION);
|
allowedEntityFieldMap.get(EntityType.TENANT).add(REGION);
|
||||||
allowedEntityFieldMap.put(EntityType.CUSTOMER, new HashSet<>(contactBasedEntityFields));
|
allowedEntityFieldMap.put(EntityType.CUSTOMER, new HashSet<>(contactBasedEntityFields));
|
||||||
|
|
||||||
allowedEntityFieldMap.put(EntityType.USER, new HashSet<>(Arrays.asList(FIRST_NAME, LAST_NAME, EMAIL)));
|
allowedEntityFieldMap.put(EntityType.USER, new HashSet<>(Arrays.asList(CREATED_TIME, FIRST_NAME, LAST_NAME, EMAIL)));
|
||||||
|
|
||||||
allowedEntityFieldMap.put(EntityType.DASHBOARD, new HashSet<>(commonEntityFields));
|
allowedEntityFieldMap.put(EntityType.DASHBOARD, new HashSet<>(commonEntityFields));
|
||||||
allowedEntityFieldMap.put(EntityType.RULE_CHAIN, new HashSet<>(commonEntityFields));
|
allowedEntityFieldMap.put(EntityType.RULE_CHAIN, new HashSet<>(commonEntityFields));
|
||||||
@ -377,28 +377,30 @@ public class EntityKeyMapping {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String buildSimplePredicateQuery(EntityQueryContext ctx, String alias, EntityKey key, KeyFilterPredicate predicate) {
|
private String buildSimplePredicateQuery(EntityQueryContext ctx, String alias, EntityKey key, KeyFilterPredicate predicate) {
|
||||||
if (predicate.getType().equals(FilterPredicateType.NUMERIC)) {
|
if (key.getType().equals(EntityKeyType.ENTITY_FIELD)) {
|
||||||
if (key.getType().equals(EntityKeyType.ENTITY_FIELD)) {
|
String column = entityFieldColumnMap.get(key.getKey());
|
||||||
String column = entityFieldColumnMap.get(key.getKey());
|
|
||||||
return this.buildNumericPredicateQuery(ctx, alias + "." + column, (NumericFilterPredicate) predicate);
|
|
||||||
} else {
|
|
||||||
String longQuery = this.buildNumericPredicateQuery(ctx, alias + ".long_v", (NumericFilterPredicate) predicate);
|
|
||||||
String doubleQuery = this.buildNumericPredicateQuery(ctx, alias + ".dbl_v", (NumericFilterPredicate) predicate);
|
|
||||||
return String.format("(%s or %s)", longQuery, doubleQuery);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String column;
|
|
||||||
if (key.getType().equals(EntityKeyType.ENTITY_FIELD)) {
|
|
||||||
column = entityFieldColumnMap.get(key.getKey());
|
|
||||||
} else {
|
|
||||||
column = predicate.getType().equals(FilterPredicateType.STRING) ? "str_v" : "bool_v";
|
|
||||||
}
|
|
||||||
String field = alias + "." + column;
|
String field = alias + "." + column;
|
||||||
if (predicate.getType().equals(FilterPredicateType.STRING)) {
|
if (predicate.getType().equals(FilterPredicateType.NUMERIC)) {
|
||||||
|
return this.buildNumericPredicateQuery(ctx, field, (NumericFilterPredicate) predicate);
|
||||||
|
} else if (predicate.getType().equals(FilterPredicateType.STRING)) {
|
||||||
return this.buildStringPredicateQuery(ctx, field, (StringFilterPredicate) predicate);
|
return this.buildStringPredicateQuery(ctx, field, (StringFilterPredicate) predicate);
|
||||||
} else {
|
} else {
|
||||||
return this.buildBooleanPredicateQuery(ctx, field, (BooleanFilterPredicate) predicate);
|
return this.buildBooleanPredicateQuery(ctx, field, (BooleanFilterPredicate) predicate);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (predicate.getType().equals(FilterPredicateType.NUMERIC)) {
|
||||||
|
String longQuery = this.buildNumericPredicateQuery(ctx, alias + ".long_v", (NumericFilterPredicate) predicate);
|
||||||
|
String doubleQuery = this.buildNumericPredicateQuery(ctx, alias + ".dbl_v", (NumericFilterPredicate) predicate);
|
||||||
|
return String.format("(%s or %s)", longQuery, doubleQuery);
|
||||||
|
} else {
|
||||||
|
String column = predicate.getType().equals(FilterPredicateType.STRING) ? "str_v" : "bool_v";
|
||||||
|
String field = alias + "." + column;
|
||||||
|
if (predicate.getType().equals(FilterPredicateType.STRING)) {
|
||||||
|
return this.buildStringPredicateQuery(ctx, field, (StringFilterPredicate) predicate);
|
||||||
|
} else {
|
||||||
|
return this.buildBooleanPredicateQuery(ctx, field, (BooleanFilterPredicate) predicate);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,6 +59,16 @@ public class JpaUserDao extends JpaAbstractSearchTextDao<UserEntity, User> imple
|
|||||||
return DaoUtil.getData(userRepository.findByEmail(email));
|
return DaoUtil.getData(userRepository.findByEmail(email));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageData<User> findByTenantId(UUID tenantId, PageLink pageLink) {
|
||||||
|
return DaoUtil.toPageData(
|
||||||
|
userRepository
|
||||||
|
.findByTenantId(
|
||||||
|
tenantId,
|
||||||
|
Objects.toString(pageLink.getTextSearch(), ""),
|
||||||
|
DaoUtil.toPageable(pageLink)));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageData<User> findTenantAdmins(UUID tenantId, PageLink pageLink) {
|
public PageData<User> findTenantAdmins(UUID tenantId, PageLink pageLink) {
|
||||||
return DaoUtil.toPageData(
|
return DaoUtil.toPageData(
|
||||||
|
|||||||
@ -43,4 +43,10 @@ public interface UserRepository extends PagingAndSortingRepository<UserEntity, U
|
|||||||
@Param("authority") Authority authority,
|
@Param("authority") Authority authority,
|
||||||
Pageable pageable);
|
Pageable pageable);
|
||||||
|
|
||||||
|
@Query("SELECT u FROM UserEntity u WHERE u.tenantId = :tenantId " +
|
||||||
|
"AND LOWER(u.searchText) LIKE LOWER(CONCAT(:searchText, '%'))")
|
||||||
|
Page<UserEntity> findByTenantId(@Param("tenantId") UUID tenantId,
|
||||||
|
@Param("searchText") String searchText,
|
||||||
|
Pageable pageable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,15 @@ public interface UserDao extends Dao<User> {
|
|||||||
* @return the user entity
|
* @return the user entity
|
||||||
*/
|
*/
|
||||||
User findByEmail(TenantId tenantId, String email);
|
User findByEmail(TenantId tenantId, String email);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find users by tenantId and page link.
|
||||||
|
*
|
||||||
|
* @param tenantId the tenantId
|
||||||
|
* @param pageLink the page link
|
||||||
|
* @return the list of user entities
|
||||||
|
*/
|
||||||
|
PageData<User> findByTenantId(UUID tenantId, PageLink pageLink);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find tenant admin users by tenantId and page link.
|
* Find tenant admin users by tenantId and page link.
|
||||||
|
|||||||
@ -219,6 +219,14 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
|
|||||||
userDao.removeById(tenantId, userId.getId());
|
userDao.removeById(tenantId, userId.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageData<User> findUsersByTenantId(TenantId tenantId, PageLink pageLink) {
|
||||||
|
log.trace("Executing findUsersByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink);
|
||||||
|
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
|
||||||
|
validatePageLink(pageLink);
|
||||||
|
return userDao.findByTenantId(tenantId.getId(), pageLink);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageData<User> findTenantAdmins(TenantId tenantId, PageLink pageLink) {
|
public PageData<User> findTenantAdmins(TenantId tenantId, PageLink pageLink) {
|
||||||
log.trace("Executing findTenantAdmins, tenantId [{}], pageLink [{}]", tenantId, pageLink);
|
log.trace("Executing findTenantAdmins, tenantId [{}], pageLink [{}]", tenantId, pageLink);
|
||||||
|
|||||||
@ -310,7 +310,8 @@ export class EntityService {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EntityType.USER:
|
case EntityType.USER:
|
||||||
console.error('Get User Entities is not implemented!');
|
pageLink.sortOrder.property = 'email';
|
||||||
|
entitiesObservable = this.userService.getUsers(pageLink);
|
||||||
break;
|
break;
|
||||||
case EntityType.ALARM:
|
case EntityType.ALARM:
|
||||||
console.error('Get Alarm Entities is not implemented!');
|
console.error('Get Alarm Entities is not implemented!');
|
||||||
@ -548,6 +549,7 @@ export class EntityService {
|
|||||||
entityTypes.push(EntityType.ENTITY_VIEW);
|
entityTypes.push(EntityType.ENTITY_VIEW);
|
||||||
entityTypes.push(EntityType.TENANT);
|
entityTypes.push(EntityType.TENANT);
|
||||||
entityTypes.push(EntityType.CUSTOMER);
|
entityTypes.push(EntityType.CUSTOMER);
|
||||||
|
entityTypes.push(EntityType.USER);
|
||||||
entityTypes.push(EntityType.DASHBOARD);
|
entityTypes.push(EntityType.DASHBOARD);
|
||||||
if (useAliasEntityTypes) {
|
if (useAliasEntityTypes) {
|
||||||
entityTypes.push(AliasEntityType.CURRENT_CUSTOMER);
|
entityTypes.push(AliasEntityType.CURRENT_CUSTOMER);
|
||||||
@ -559,12 +561,16 @@ export class EntityService {
|
|||||||
entityTypes.push(EntityType.ASSET);
|
entityTypes.push(EntityType.ASSET);
|
||||||
entityTypes.push(EntityType.ENTITY_VIEW);
|
entityTypes.push(EntityType.ENTITY_VIEW);
|
||||||
entityTypes.push(EntityType.CUSTOMER);
|
entityTypes.push(EntityType.CUSTOMER);
|
||||||
|
entityTypes.push(EntityType.USER);
|
||||||
entityTypes.push(EntityType.DASHBOARD);
|
entityTypes.push(EntityType.DASHBOARD);
|
||||||
if (useAliasEntityTypes) {
|
if (useAliasEntityTypes) {
|
||||||
entityTypes.push(AliasEntityType.CURRENT_CUSTOMER);
|
entityTypes.push(AliasEntityType.CURRENT_CUSTOMER);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (useAliasEntityTypes) {
|
||||||
|
entityTypes.push(AliasEntityType.CURRENT_USER);
|
||||||
|
}
|
||||||
if (allowedEntityTypes && allowedEntityTypes.length) {
|
if (allowedEntityTypes && allowedEntityTypes.length) {
|
||||||
for (let index = entityTypes.length - 1; index >= 0; index--) {
|
for (let index = entityTypes.length - 1; index >= 0; index--) {
|
||||||
if (allowedEntityTypes.indexOf(entityTypes[index]) === -1) {
|
if (allowedEntityTypes.indexOf(entityTypes[index]) === -1) {
|
||||||
@ -961,6 +967,10 @@ export class EntityService {
|
|||||||
const authUser = getCurrentAuthUser(this.store);
|
const authUser = getCurrentAuthUser(this.store);
|
||||||
entityId.entityType = EntityType.TENANT;
|
entityId.entityType = EntityType.TENANT;
|
||||||
entityId.id = authUser.tenantId;
|
entityId.id = authUser.tenantId;
|
||||||
|
} else if (entityType === AliasEntityType.CURRENT_USER){
|
||||||
|
const authUser = getCurrentAuthUser(this.store);
|
||||||
|
entityId.entityType = EntityType.USER;
|
||||||
|
entityId.id = authUser.userId;
|
||||||
}
|
}
|
||||||
return entityId;
|
return entityId;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,12 @@ export class UserService {
|
|||||||
private http: HttpClient
|
private http: HttpClient
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
|
public getUsers(pageLink: PageLink,
|
||||||
|
config?: RequestConfig): Observable<PageData<User>> {
|
||||||
|
return this.http.get<PageData<User>>(`/api/users${pageLink.toQuery()}`,
|
||||||
|
defaultHttpOptionsFromConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
public getTenantAdmins(tenantId: string, pageLink: PageLink,
|
public getTenantAdmins(tenantId: string, pageLink: PageLink,
|
||||||
config?: RequestConfig): Observable<PageData<User>> {
|
config?: RequestConfig): Observable<PageData<User>> {
|
||||||
return this.http.get<PageData<User>>(`/api/tenant/${tenantId}/users${pageLink.toQuery()}`,
|
return this.http.get<PageData<User>>(`/api/tenant/${tenantId}/users${pageLink.toQuery()}`,
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import {
|
|||||||
AliasesEntitySelectPanelData
|
AliasesEntitySelectPanelData
|
||||||
} from './aliases-entity-select-panel.component';
|
} from './aliases-entity-select-panel.component';
|
||||||
import { deepClone } from '@core/utils';
|
import { deepClone } from '@core/utils';
|
||||||
|
import { AliasFilterType } from '@shared/models/alias.models';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-aliases-entity-select',
|
selector: 'tb-aliases-entity-select',
|
||||||
@ -178,7 +179,7 @@ export class AliasesEntitySelectComponent implements OnInit, OnDestroy {
|
|||||||
for (const aliasId of Object.keys(allEntityAliases)) {
|
for (const aliasId of Object.keys(allEntityAliases)) {
|
||||||
const aliasInfo = this.aliasController.getInstantAliasInfo(aliasId);
|
const aliasInfo = this.aliasController.getInstantAliasInfo(aliasId);
|
||||||
if (aliasInfo && !aliasInfo.resolveMultiple && aliasInfo.currentEntity
|
if (aliasInfo && !aliasInfo.resolveMultiple && aliasInfo.currentEntity
|
||||||
&& aliasInfo.entityFilter) {
|
&& aliasInfo.entityFilter && aliasInfo.entityFilter.type !== AliasFilterType.singleEntity) {
|
||||||
this.entityAliasesInfo[aliasId] = deepClone(aliasInfo);
|
this.entityAliasesInfo[aliasId] = deepClone(aliasInfo);
|
||||||
this.hasSelectableAliasEntities = true;
|
this.hasSelectableAliasEntities = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,6 +84,9 @@ import {
|
|||||||
KeyFilter
|
KeyFilter
|
||||||
} from '@shared/models/query/query.models';
|
} from '@shared/models/query/query.models';
|
||||||
import { sortItems } from '@shared/models/page/page-link';
|
import { sortItems } from '@shared/models/page/page-link';
|
||||||
|
import { entityFields } from '@shared/models/entity.models';
|
||||||
|
import { alarmFields } from '@shared/models/alarm.models';
|
||||||
|
import { DatePipe } from '@angular/common';
|
||||||
|
|
||||||
interface EntitiesTableWidgetSettings extends TableWidgetSettings {
|
interface EntitiesTableWidgetSettings extends TableWidgetSettings {
|
||||||
entitiesTitle: string;
|
entitiesTitle: string;
|
||||||
@ -153,6 +156,7 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
|
|||||||
private overlay: Overlay,
|
private overlay: Overlay,
|
||||||
private viewContainerRef: ViewContainerRef,
|
private viewContainerRef: ViewContainerRef,
|
||||||
private utils: UtilsService,
|
private utils: UtilsService,
|
||||||
|
private datePipe: DatePipe,
|
||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
private domSanitizer: DomSanitizer) {
|
private domSanitizer: DomSanitizer) {
|
||||||
super(store);
|
super(store);
|
||||||
@ -511,9 +515,7 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
|
|||||||
content = '' + value;
|
content = '' + value;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const decimals = (contentInfo.decimals || contentInfo.decimals === 0) ? contentInfo.decimals : this.ctx.widgetConfig.decimals;
|
content = this.defaultContent(key, contentInfo, value);
|
||||||
const units = contentInfo.units || this.ctx.widgetConfig.units;
|
|
||||||
content = this.ctx.utils.formatValue(value, decimals, units, true);
|
|
||||||
}
|
}
|
||||||
return isDefined(content) ? this.domSanitizer.bypassSecurityTrustHtml(content) : '';
|
return isDefined(content) ? this.domSanitizer.bypassSecurityTrustHtml(content) : '';
|
||||||
} else {
|
} else {
|
||||||
@ -521,6 +523,22 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private defaultContent(key: EntityColumn, contentInfo: CellContentInfo, value: any): any {
|
||||||
|
if (isDefined(value)) {
|
||||||
|
const entityField = entityFields[key.name];
|
||||||
|
if (entityField) {
|
||||||
|
if (entityField.time) {
|
||||||
|
return this.datePipe.transform(value, 'yyyy-MM-dd HH:mm:ss');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const decimals = (contentInfo.decimals || contentInfo.decimals === 0) ? contentInfo.decimals : this.ctx.widgetConfig.decimals;
|
||||||
|
const units = contentInfo.units || this.ctx.widgetConfig.units;
|
||||||
|
return this.ctx.utils.formatValue(value, decimals, units, true);
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public onRowClick($event: Event, entity: EntityData, isDouble?: boolean) {
|
public onRowClick($event: Event, entity: EntityData, isDouble?: boolean) {
|
||||||
if ($event) {
|
if ($event) {
|
||||||
$event.stopPropagation();
|
$event.stopPropagation();
|
||||||
|
|||||||
@ -15,6 +15,23 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
<mat-tab *ngIf="entity"
|
||||||
|
label="{{ 'attribute.attributes' | translate }}" #attributesTab="matTab">
|
||||||
|
<tb-attribute-table [defaultAttributeScope]="attributeScopes.SERVER_SCOPE"
|
||||||
|
[active]="attributesTab.isActive"
|
||||||
|
[entityId]="entity.id"
|
||||||
|
[entityName]="entity.name">
|
||||||
|
</tb-attribute-table>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab *ngIf="entity"
|
||||||
|
label="{{ 'attribute.latest-telemetry' | translate }}" #telemetryTab="matTab">
|
||||||
|
<tb-attribute-table [defaultAttributeScope]="latestTelemetryTypes.LATEST_TELEMETRY"
|
||||||
|
disableAttributeScopeSelection
|
||||||
|
[active]="telemetryTab.isActive"
|
||||||
|
[entityId]="entity.id"
|
||||||
|
[entityName]="entity.name">
|
||||||
|
</tb-attribute-table>
|
||||||
|
</mat-tab>
|
||||||
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
|
<mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN"
|
||||||
label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
|
label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab">
|
||||||
<tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.USER" [userId]="entity.id" detailsMode="true"></tb-audit-log-table>
|
<tb-audit-log-table [active]="auditLogsTab.isActive" [auditLogMode]="auditLogModes.USER" [userId]="entity.id" detailsMode="true"></tb-audit-log-table>
|
||||||
|
|||||||
@ -175,6 +175,7 @@ export class EntityAutocompleteComponent implements ControlValueAccessor, OnInit
|
|||||||
this.entityRequiredText = 'customer.customer-required';
|
this.entityRequiredText = 'customer.customer-required';
|
||||||
break;
|
break;
|
||||||
case EntityType.USER:
|
case EntityType.USER:
|
||||||
|
case AliasEntityType.CURRENT_USER:
|
||||||
this.entityText = 'user.user';
|
this.entityText = 'user.user';
|
||||||
this.noEntitiesMatchingText = 'user.no-users-matching';
|
this.noEntitiesMatchingText = 'user.no-users-matching';
|
||||||
this.entityRequiredText = 'user.user-required';
|
this.entityRequiredText = 'user.user-required';
|
||||||
@ -324,6 +325,8 @@ export class EntityAutocompleteComponent implements ControlValueAccessor, OnInit
|
|||||||
return EntityType.CUSTOMER;
|
return EntityType.CUSTOMER;
|
||||||
} else if (entityType === AliasEntityType.CURRENT_TENANT) {
|
} else if (entityType === AliasEntityType.CURRENT_TENANT) {
|
||||||
return EntityType.TENANT;
|
return EntityType.TENANT;
|
||||||
|
} else if (entityType === AliasEntityType.CURRENT_USER) {
|
||||||
|
return EntityType.USER;
|
||||||
}
|
}
|
||||||
return entityType;
|
return entityType;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,8 @@
|
|||||||
</tb-entity-type-select>
|
</tb-entity-type-select>
|
||||||
<tb-entity-autocomplete
|
<tb-entity-autocomplete
|
||||||
fxFlex
|
fxFlex
|
||||||
*ngIf="modelValue.entityType && modelValue.entityType !== AliasEntityType.CURRENT_TENANT"
|
*ngIf="modelValue.entityType && modelValue.entityType !== AliasEntityType.CURRENT_TENANT
|
||||||
|
&& modelValue.entityType !== AliasEntityType.CURRENT_USER"
|
||||||
[required]="required"
|
[required]="required"
|
||||||
[entityType]="modelValue.entityType"
|
[entityType]="modelValue.entityType"
|
||||||
formControlName="entityId">
|
formControlName="entityId">
|
||||||
|
|||||||
@ -97,7 +97,7 @@ export class EntitySelectComponent implements ControlValueAccessor, OnInit, Afte
|
|||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.entitySelectFormGroup.get('entityType').valueChanges.subscribe(
|
this.entitySelectFormGroup.get('entityType').valueChanges.subscribe(
|
||||||
(value) => {
|
(value) => {
|
||||||
if(value === AliasEntityType.CURRENT_TENANT){
|
if(value === AliasEntityType.CURRENT_TENANT || value === AliasEntityType.CURRENT_USER) {
|
||||||
this.modelValue.id = NULL_UUID;
|
this.modelValue.id = NULL_UUID;
|
||||||
}
|
}
|
||||||
this.updateView(value, this.modelValue.id);
|
this.updateView(value, this.modelValue.id);
|
||||||
@ -145,7 +145,9 @@ export class EntitySelectComponent implements ControlValueAccessor, OnInit, Afte
|
|||||||
entityType,
|
entityType,
|
||||||
id: this.modelValue.entityType !== entityType ? null : entityId
|
id: this.modelValue.entityType !== entityType ? null : entityId
|
||||||
};
|
};
|
||||||
if (this.modelValue.entityType && (this.modelValue.id || this.modelValue.entityType === AliasEntityType.CURRENT_TENANT)) {
|
if (this.modelValue.entityType && (this.modelValue.id ||
|
||||||
|
this.modelValue.entityType === AliasEntityType.CURRENT_TENANT ||
|
||||||
|
this.modelValue.entityType === AliasEntityType.CURRENT_USER)) {
|
||||||
this.propagateChange(this.modelValue);
|
this.propagateChange(this.modelValue);
|
||||||
} else {
|
} else {
|
||||||
this.propagateChange(null);
|
this.propagateChange(null);
|
||||||
|
|||||||
@ -50,7 +50,8 @@ export enum EntityType {
|
|||||||
|
|
||||||
export enum AliasEntityType {
|
export enum AliasEntityType {
|
||||||
CURRENT_CUSTOMER = 'CURRENT_CUSTOMER',
|
CURRENT_CUSTOMER = 'CURRENT_CUSTOMER',
|
||||||
CURRENT_TENANT = 'CURRENT_TENANT'
|
CURRENT_TENANT = 'CURRENT_TENANT',
|
||||||
|
CURRENT_USER = 'CURRENT_USER'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntityTypeTranslation {
|
export interface EntityTypeTranslation {
|
||||||
@ -229,6 +230,13 @@ export const entityTypeTranslations = new Map<EntityType | AliasEntityType, Enti
|
|||||||
type: 'entity.type-current-tenant',
|
type: 'entity.type-current-tenant',
|
||||||
list: 'entity.type-current-tenant'
|
list: 'entity.type-current-tenant'
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
AliasEntityType.CURRENT_USER,
|
||||||
|
{
|
||||||
|
type: 'entity.type-current-user',
|
||||||
|
list: 'entity.type-current-user'
|
||||||
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|||||||
@ -841,6 +841,7 @@
|
|||||||
"rulenode-name-starts-with": "Rule nodes whose names start with '{{prefix}}'",
|
"rulenode-name-starts-with": "Rule nodes whose names start with '{{prefix}}'",
|
||||||
"type-current-customer": "Current Customer",
|
"type-current-customer": "Current Customer",
|
||||||
"type-current-tenant": "Current Tenant",
|
"type-current-tenant": "Current Tenant",
|
||||||
|
"type-current-user": "Current User",
|
||||||
"search": "Search entities",
|
"search": "Search entities",
|
||||||
"selected-entities": "{ count, plural, 1 {1 entity} other {# entities} } selected",
|
"selected-entities": "{ count, plural, 1 {1 entity} other {# entities} } selected",
|
||||||
"entity-name": "Entity name",
|
"entity-name": "Entity name",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user