Showing
18 changed files
with
175 additions
and
28 deletions
... | ... | @@ -246,6 +246,28 @@ public class UserController extends BaseController { |
246 | 246 | } |
247 | 247 | } |
248 | 248 | |
249 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | |
250 | + @RequestMapping(value = "/users", params = {"pageSize", "page"}, method = RequestMethod.GET) | |
251 | + @ResponseBody | |
252 | + public PageData<User> getUsers( | |
253 | + @RequestParam int pageSize, | |
254 | + @RequestParam int page, | |
255 | + @RequestParam(required = false) String textSearch, | |
256 | + @RequestParam(required = false) String sortProperty, | |
257 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | |
258 | + try { | |
259 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | |
260 | + SecurityUser currentUser = getCurrentUser(); | |
261 | + if (Authority.TENANT_ADMIN.equals(currentUser.getAuthority())) { | |
262 | + return checkNotNull(userService.findUsersByTenantId(currentUser.getTenantId(), pageLink)); | |
263 | + } else { | |
264 | + return checkNotNull(userService.findCustomerUsers(currentUser.getTenantId(), currentUser.getCustomerId(), pageLink)); | |
265 | + } | |
266 | + } catch (Exception e) { | |
267 | + throw handleException(e); | |
268 | + } | |
269 | + } | |
270 | + | |
249 | 271 | @PreAuthorize("hasAuthority('SYS_ADMIN')") |
250 | 272 | @RequestMapping(value = "/tenant/{tenantId}/users", params = {"pageSize", "page"}, method = RequestMethod.GET) |
251 | 273 | @ResponseBody | ... | ... |
... | ... | @@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.Customer; |
29 | 29 | import org.thingsboard.server.common.data.Device; |
30 | 30 | import org.thingsboard.server.common.data.EntityView; |
31 | 31 | import org.thingsboard.server.common.data.Tenant; |
32 | +import org.thingsboard.server.common.data.User; | |
32 | 33 | import org.thingsboard.server.common.data.asset.Asset; |
33 | 34 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
34 | 35 | import org.thingsboard.server.common.data.id.AssetId; |
... | ... | @@ -40,6 +41,7 @@ import org.thingsboard.server.common.data.id.EntityViewId; |
40 | 41 | import org.thingsboard.server.common.data.id.RuleChainId; |
41 | 42 | import org.thingsboard.server.common.data.id.RuleNodeId; |
42 | 43 | import org.thingsboard.server.common.data.id.TenantId; |
44 | +import org.thingsboard.server.common.data.id.UserId; | |
43 | 45 | import org.thingsboard.server.common.data.rule.RuleChain; |
44 | 46 | import org.thingsboard.server.common.data.rule.RuleNode; |
45 | 47 | import org.thingsboard.server.controller.HttpValidationCallback; |
... | ... | @@ -172,6 +174,9 @@ public class AccessValidator { |
172 | 174 | case TENANT: |
173 | 175 | validateTenant(currentUser, operation, entityId, callback); |
174 | 176 | return; |
177 | + case USER: | |
178 | + validateUser(currentUser, operation, entityId, callback); | |
179 | + return; | |
175 | 180 | case ENTITY_VIEW: |
176 | 181 | validateEntityView(currentUser, operation, entityId, callback); |
177 | 182 | return; |
... | ... | @@ -308,6 +313,22 @@ public class AccessValidator { |
308 | 313 | } |
309 | 314 | } |
310 | 315 | |
316 | + private void validateUser(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback<ValidationResult> callback) { | |
317 | + ListenableFuture<User> userFuture = userService.findUserByIdAsync(currentUser.getTenantId(), new UserId(entityId.getId())); | |
318 | + Futures.addCallback(userFuture, getCallback(callback, user -> { | |
319 | + if (user == null) { | |
320 | + return ValidationResult.entityNotFound("User with requested id wasn't found!"); | |
321 | + } | |
322 | + try { | |
323 | + accessControlService.checkPermission(currentUser, Resource.USER, operation, entityId, user); | |
324 | + } catch (ThingsboardException e) { | |
325 | + return ValidationResult.accessDenied(e.getMessage()); | |
326 | + } | |
327 | + return ValidationResult.ok(user); | |
328 | + | |
329 | + }), executor); | |
330 | + } | |
331 | + | |
311 | 332 | private void validateEntityView(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback<ValidationResult> callback) { |
312 | 333 | if (currentUser.isSystemAdmin()) { |
313 | 334 | callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION)); | ... | ... |
... | ... | @@ -52,8 +52,10 @@ public interface UserService { |
52 | 52 | UserCredentials replaceUserCredentials(TenantId tenantId, UserCredentials userCredentials); |
53 | 53 | |
54 | 54 | void deleteUser(TenantId tenantId, UserId userId); |
55 | - | |
56 | - PageData<User> findTenantAdmins(TenantId tenantId, PageLink pageLink); | |
55 | + | |
56 | + PageData<User> findUsersByTenantId(TenantId tenantId, PageLink pageLink); | |
57 | + | |
58 | + PageData<User> findTenantAdmins(TenantId tenantId, PageLink pageLink); | |
57 | 59 | |
58 | 60 | void deleteTenantAdmins(TenantId tenantId); |
59 | 61 | ... | ... |
... | ... | @@ -86,7 +86,7 @@ public class EntityKeyMapping { |
86 | 86 | allowedEntityFieldMap.get(EntityType.TENANT).add(REGION); |
87 | 87 | allowedEntityFieldMap.put(EntityType.CUSTOMER, new HashSet<>(contactBasedEntityFields)); |
88 | 88 | |
89 | - allowedEntityFieldMap.put(EntityType.USER, new HashSet<>(Arrays.asList(FIRST_NAME, LAST_NAME, EMAIL))); | |
89 | + allowedEntityFieldMap.put(EntityType.USER, new HashSet<>(Arrays.asList(CREATED_TIME, FIRST_NAME, LAST_NAME, EMAIL))); | |
90 | 90 | |
91 | 91 | allowedEntityFieldMap.put(EntityType.DASHBOARD, new HashSet<>(commonEntityFields)); |
92 | 92 | allowedEntityFieldMap.put(EntityType.RULE_CHAIN, new HashSet<>(commonEntityFields)); |
... | ... | @@ -377,27 +377,29 @@ public class EntityKeyMapping { |
377 | 377 | } |
378 | 378 | |
379 | 379 | private String buildSimplePredicateQuery(EntityQueryContext ctx, String alias, EntityKey key, KeyFilterPredicate predicate) { |
380 | - if (predicate.getType().equals(FilterPredicateType.NUMERIC)) { | |
381 | - if (key.getType().equals(EntityKeyType.ENTITY_FIELD)) { | |
382 | - String column = entityFieldColumnMap.get(key.getKey()); | |
383 | - return this.buildNumericPredicateQuery(ctx, alias + "." + column, (NumericFilterPredicate) predicate); | |
380 | + if (key.getType().equals(EntityKeyType.ENTITY_FIELD)) { | |
381 | + String column = entityFieldColumnMap.get(key.getKey()); | |
382 | + String field = alias + "." + column; | |
383 | + if (predicate.getType().equals(FilterPredicateType.NUMERIC)) { | |
384 | + return this.buildNumericPredicateQuery(ctx, field, (NumericFilterPredicate) predicate); | |
385 | + } else if (predicate.getType().equals(FilterPredicateType.STRING)) { | |
386 | + return this.buildStringPredicateQuery(ctx, field, (StringFilterPredicate) predicate); | |
384 | 387 | } else { |
388 | + return this.buildBooleanPredicateQuery(ctx, field, (BooleanFilterPredicate) predicate); | |
389 | + } | |
390 | + } else { | |
391 | + if (predicate.getType().equals(FilterPredicateType.NUMERIC)) { | |
385 | 392 | String longQuery = this.buildNumericPredicateQuery(ctx, alias + ".long_v", (NumericFilterPredicate) predicate); |
386 | 393 | String doubleQuery = this.buildNumericPredicateQuery(ctx, alias + ".dbl_v", (NumericFilterPredicate) predicate); |
387 | 394 | return String.format("(%s or %s)", longQuery, doubleQuery); |
388 | - } | |
389 | - } else { | |
390 | - String column; | |
391 | - if (key.getType().equals(EntityKeyType.ENTITY_FIELD)) { | |
392 | - column = entityFieldColumnMap.get(key.getKey()); | |
393 | 395 | } else { |
394 | - column = predicate.getType().equals(FilterPredicateType.STRING) ? "str_v" : "bool_v"; | |
395 | - } | |
396 | - String field = alias + "." + column; | |
397 | - if (predicate.getType().equals(FilterPredicateType.STRING)) { | |
398 | - return this.buildStringPredicateQuery(ctx, field, (StringFilterPredicate) predicate); | |
399 | - } else { | |
400 | - return this.buildBooleanPredicateQuery(ctx, field, (BooleanFilterPredicate) predicate); | |
396 | + String column = predicate.getType().equals(FilterPredicateType.STRING) ? "str_v" : "bool_v"; | |
397 | + String field = alias + "." + column; | |
398 | + if (predicate.getType().equals(FilterPredicateType.STRING)) { | |
399 | + return this.buildStringPredicateQuery(ctx, field, (StringFilterPredicate) predicate); | |
400 | + } else { | |
401 | + return this.buildBooleanPredicateQuery(ctx, field, (BooleanFilterPredicate) predicate); | |
402 | + } | |
401 | 403 | } |
402 | 404 | } |
403 | 405 | } | ... | ... |
... | ... | @@ -60,6 +60,16 @@ public class JpaUserDao extends JpaAbstractSearchTextDao<UserEntity, User> imple |
60 | 60 | } |
61 | 61 | |
62 | 62 | @Override |
63 | + public PageData<User> findByTenantId(UUID tenantId, PageLink pageLink) { | |
64 | + return DaoUtil.toPageData( | |
65 | + userRepository | |
66 | + .findByTenantId( | |
67 | + tenantId, | |
68 | + Objects.toString(pageLink.getTextSearch(), ""), | |
69 | + DaoUtil.toPageable(pageLink))); | |
70 | + } | |
71 | + | |
72 | + @Override | |
63 | 73 | public PageData<User> findTenantAdmins(UUID tenantId, PageLink pageLink) { |
64 | 74 | return DaoUtil.toPageData( |
65 | 75 | userRepository | ... | ... |
... | ... | @@ -43,4 +43,10 @@ public interface UserRepository extends PagingAndSortingRepository<UserEntity, U |
43 | 43 | @Param("authority") Authority authority, |
44 | 44 | Pageable pageable); |
45 | 45 | |
46 | + @Query("SELECT u FROM UserEntity u WHERE u.tenantId = :tenantId " + | |
47 | + "AND LOWER(u.searchText) LIKE LOWER(CONCAT(:searchText, '%'))") | |
48 | + Page<UserEntity> findByTenantId(@Param("tenantId") UUID tenantId, | |
49 | + @Param("searchText") String searchText, | |
50 | + Pageable pageable); | |
51 | + | |
46 | 52 | } | ... | ... |
... | ... | @@ -40,6 +40,15 @@ public interface UserDao extends Dao<User> { |
40 | 40 | * @return the user entity |
41 | 41 | */ |
42 | 42 | User findByEmail(TenantId tenantId, String email); |
43 | + | |
44 | + /** | |
45 | + * Find users by tenantId and page link. | |
46 | + * | |
47 | + * @param tenantId the tenantId | |
48 | + * @param pageLink the page link | |
49 | + * @return the list of user entities | |
50 | + */ | |
51 | + PageData<User> findByTenantId(UUID tenantId, PageLink pageLink); | |
43 | 52 | |
44 | 53 | /** |
45 | 54 | * Find tenant admin users by tenantId and page link. | ... | ... |
... | ... | @@ -220,6 +220,14 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic |
220 | 220 | } |
221 | 221 | |
222 | 222 | @Override |
223 | + public PageData<User> findUsersByTenantId(TenantId tenantId, PageLink pageLink) { | |
224 | + log.trace("Executing findUsersByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); | |
225 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | |
226 | + validatePageLink(pageLink); | |
227 | + return userDao.findByTenantId(tenantId.getId(), pageLink); | |
228 | + } | |
229 | + | |
230 | + @Override | |
223 | 231 | public PageData<User> findTenantAdmins(TenantId tenantId, PageLink pageLink) { |
224 | 232 | log.trace("Executing findTenantAdmins, tenantId [{}], pageLink [{}]", tenantId, pageLink); |
225 | 233 | validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | ... | ... |
... | ... | @@ -310,7 +310,8 @@ export class EntityService { |
310 | 310 | } |
311 | 311 | break; |
312 | 312 | case EntityType.USER: |
313 | - console.error('Get User Entities is not implemented!'); | |
313 | + pageLink.sortOrder.property = 'email'; | |
314 | + entitiesObservable = this.userService.getUsers(pageLink); | |
314 | 315 | break; |
315 | 316 | case EntityType.ALARM: |
316 | 317 | console.error('Get Alarm Entities is not implemented!'); |
... | ... | @@ -548,6 +549,7 @@ export class EntityService { |
548 | 549 | entityTypes.push(EntityType.ENTITY_VIEW); |
549 | 550 | entityTypes.push(EntityType.TENANT); |
550 | 551 | entityTypes.push(EntityType.CUSTOMER); |
552 | + entityTypes.push(EntityType.USER); | |
551 | 553 | entityTypes.push(EntityType.DASHBOARD); |
552 | 554 | if (useAliasEntityTypes) { |
553 | 555 | entityTypes.push(AliasEntityType.CURRENT_CUSTOMER); |
... | ... | @@ -559,12 +561,16 @@ export class EntityService { |
559 | 561 | entityTypes.push(EntityType.ASSET); |
560 | 562 | entityTypes.push(EntityType.ENTITY_VIEW); |
561 | 563 | entityTypes.push(EntityType.CUSTOMER); |
564 | + entityTypes.push(EntityType.USER); | |
562 | 565 | entityTypes.push(EntityType.DASHBOARD); |
563 | 566 | if (useAliasEntityTypes) { |
564 | 567 | entityTypes.push(AliasEntityType.CURRENT_CUSTOMER); |
565 | 568 | } |
566 | 569 | break; |
567 | 570 | } |
571 | + if (useAliasEntityTypes) { | |
572 | + entityTypes.push(AliasEntityType.CURRENT_USER); | |
573 | + } | |
568 | 574 | if (allowedEntityTypes && allowedEntityTypes.length) { |
569 | 575 | for (let index = entityTypes.length - 1; index >= 0; index--) { |
570 | 576 | if (allowedEntityTypes.indexOf(entityTypes[index]) === -1) { |
... | ... | @@ -961,6 +967,10 @@ export class EntityService { |
961 | 967 | const authUser = getCurrentAuthUser(this.store); |
962 | 968 | entityId.entityType = EntityType.TENANT; |
963 | 969 | entityId.id = authUser.tenantId; |
970 | + } else if (entityType === AliasEntityType.CURRENT_USER){ | |
971 | + const authUser = getCurrentAuthUser(this.store); | |
972 | + entityId.entityType = EntityType.USER; | |
973 | + entityId.id = authUser.userId; | |
964 | 974 | } |
965 | 975 | return entityId; |
966 | 976 | } | ... | ... |
... | ... | @@ -32,6 +32,12 @@ export class UserService { |
32 | 32 | private http: HttpClient |
33 | 33 | ) { } |
34 | 34 | |
35 | + public getUsers(pageLink: PageLink, | |
36 | + config?: RequestConfig): Observable<PageData<User>> { | |
37 | + return this.http.get<PageData<User>>(`/api/users${pageLink.toQuery()}`, | |
38 | + defaultHttpOptionsFromConfig(config)); | |
39 | + } | |
40 | + | |
35 | 41 | public getTenantAdmins(tenantId: string, pageLink: PageLink, |
36 | 42 | config?: RequestConfig): Observable<PageData<User>> { |
37 | 43 | return this.http.get<PageData<User>>(`/api/tenant/${tenantId}/users${pageLink.toQuery()}`, | ... | ... |
... | ... | @@ -28,6 +28,7 @@ import { |
28 | 28 | AliasesEntitySelectPanelData |
29 | 29 | } from './aliases-entity-select-panel.component'; |
30 | 30 | import { deepClone } from '@core/utils'; |
31 | +import { AliasFilterType } from '@shared/models/alias.models'; | |
31 | 32 | |
32 | 33 | @Component({ |
33 | 34 | selector: 'tb-aliases-entity-select', |
... | ... | @@ -178,7 +179,7 @@ export class AliasesEntitySelectComponent implements OnInit, OnDestroy { |
178 | 179 | for (const aliasId of Object.keys(allEntityAliases)) { |
179 | 180 | const aliasInfo = this.aliasController.getInstantAliasInfo(aliasId); |
180 | 181 | if (aliasInfo && !aliasInfo.resolveMultiple && aliasInfo.currentEntity |
181 | - && aliasInfo.entityFilter) { | |
182 | + && aliasInfo.entityFilter && aliasInfo.entityFilter.type !== AliasFilterType.singleEntity) { | |
182 | 183 | this.entityAliasesInfo[aliasId] = deepClone(aliasInfo); |
183 | 184 | this.hasSelectableAliasEntities = true; |
184 | 185 | } | ... | ... |
... | ... | @@ -84,6 +84,9 @@ import { |
84 | 84 | KeyFilter |
85 | 85 | } from '@shared/models/query/query.models'; |
86 | 86 | import { sortItems } from '@shared/models/page/page-link'; |
87 | +import { entityFields } from '@shared/models/entity.models'; | |
88 | +import { alarmFields } from '@shared/models/alarm.models'; | |
89 | +import { DatePipe } from '@angular/common'; | |
87 | 90 | |
88 | 91 | interface EntitiesTableWidgetSettings extends TableWidgetSettings { |
89 | 92 | entitiesTitle: string; |
... | ... | @@ -153,6 +156,7 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni |
153 | 156 | private overlay: Overlay, |
154 | 157 | private viewContainerRef: ViewContainerRef, |
155 | 158 | private utils: UtilsService, |
159 | + private datePipe: DatePipe, | |
156 | 160 | private translate: TranslateService, |
157 | 161 | private domSanitizer: DomSanitizer) { |
158 | 162 | super(store); |
... | ... | @@ -511,9 +515,7 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni |
511 | 515 | content = '' + value; |
512 | 516 | } |
513 | 517 | } else { |
514 | - const decimals = (contentInfo.decimals || contentInfo.decimals === 0) ? contentInfo.decimals : this.ctx.widgetConfig.decimals; | |
515 | - const units = contentInfo.units || this.ctx.widgetConfig.units; | |
516 | - content = this.ctx.utils.formatValue(value, decimals, units, true); | |
518 | + content = this.defaultContent(key, contentInfo, value); | |
517 | 519 | } |
518 | 520 | return isDefined(content) ? this.domSanitizer.bypassSecurityTrustHtml(content) : ''; |
519 | 521 | } else { |
... | ... | @@ -521,6 +523,22 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni |
521 | 523 | } |
522 | 524 | } |
523 | 525 | |
526 | + private defaultContent(key: EntityColumn, contentInfo: CellContentInfo, value: any): any { | |
527 | + if (isDefined(value)) { | |
528 | + const entityField = entityFields[key.name]; | |
529 | + if (entityField) { | |
530 | + if (entityField.time) { | |
531 | + return this.datePipe.transform(value, 'yyyy-MM-dd HH:mm:ss'); | |
532 | + } | |
533 | + } | |
534 | + const decimals = (contentInfo.decimals || contentInfo.decimals === 0) ? contentInfo.decimals : this.ctx.widgetConfig.decimals; | |
535 | + const units = contentInfo.units || this.ctx.widgetConfig.units; | |
536 | + return this.ctx.utils.formatValue(value, decimals, units, true); | |
537 | + } else { | |
538 | + return ''; | |
539 | + } | |
540 | + } | |
541 | + | |
524 | 542 | public onRowClick($event: Event, entity: EntityData, isDouble?: boolean) { |
525 | 543 | if ($event) { |
526 | 544 | $event.stopPropagation(); | ... | ... |
... | ... | @@ -15,6 +15,23 @@ |
15 | 15 | limitations under the License. |
16 | 16 | |
17 | 17 | --> |
18 | +<mat-tab *ngIf="entity" | |
19 | + label="{{ 'attribute.attributes' | translate }}" #attributesTab="matTab"> | |
20 | + <tb-attribute-table [defaultAttributeScope]="attributeScopes.SERVER_SCOPE" | |
21 | + [active]="attributesTab.isActive" | |
22 | + [entityId]="entity.id" | |
23 | + [entityName]="entity.name"> | |
24 | + </tb-attribute-table> | |
25 | +</mat-tab> | |
26 | +<mat-tab *ngIf="entity" | |
27 | + label="{{ 'attribute.latest-telemetry' | translate }}" #telemetryTab="matTab"> | |
28 | + <tb-attribute-table [defaultAttributeScope]="latestTelemetryTypes.LATEST_TELEMETRY" | |
29 | + disableAttributeScopeSelection | |
30 | + [active]="telemetryTab.isActive" | |
31 | + [entityId]="entity.id" | |
32 | + [entityName]="entity.name"> | |
33 | + </tb-attribute-table> | |
34 | +</mat-tab> | |
18 | 35 | <mat-tab *ngIf="entity && authUser.authority === authorities.TENANT_ADMIN" |
19 | 36 | label="{{ 'audit-log.audit-logs' | translate }}" #auditLogsTab="matTab"> |
20 | 37 | <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 |
175 | 175 | this.entityRequiredText = 'customer.customer-required'; |
176 | 176 | break; |
177 | 177 | case EntityType.USER: |
178 | + case AliasEntityType.CURRENT_USER: | |
178 | 179 | this.entityText = 'user.user'; |
179 | 180 | this.noEntitiesMatchingText = 'user.no-users-matching'; |
180 | 181 | this.entityRequiredText = 'user.user-required'; |
... | ... | @@ -324,6 +325,8 @@ export class EntityAutocompleteComponent implements ControlValueAccessor, OnInit |
324 | 325 | return EntityType.CUSTOMER; |
325 | 326 | } else if (entityType === AliasEntityType.CURRENT_TENANT) { |
326 | 327 | return EntityType.TENANT; |
328 | + } else if (entityType === AliasEntityType.CURRENT_USER) { | |
329 | + return EntityType.USER; | |
327 | 330 | } |
328 | 331 | return entityType; |
329 | 332 | } | ... | ... |
... | ... | @@ -27,7 +27,8 @@ |
27 | 27 | </tb-entity-type-select> |
28 | 28 | <tb-entity-autocomplete |
29 | 29 | fxFlex |
30 | - *ngIf="modelValue.entityType && modelValue.entityType !== AliasEntityType.CURRENT_TENANT" | |
30 | + *ngIf="modelValue.entityType && modelValue.entityType !== AliasEntityType.CURRENT_TENANT | |
31 | + && modelValue.entityType !== AliasEntityType.CURRENT_USER" | |
31 | 32 | [required]="required" |
32 | 33 | [entityType]="modelValue.entityType" |
33 | 34 | formControlName="entityId"> | ... | ... |
... | ... | @@ -97,7 +97,7 @@ export class EntitySelectComponent implements ControlValueAccessor, OnInit, Afte |
97 | 97 | ngOnInit() { |
98 | 98 | this.entitySelectFormGroup.get('entityType').valueChanges.subscribe( |
99 | 99 | (value) => { |
100 | - if(value === AliasEntityType.CURRENT_TENANT){ | |
100 | + if(value === AliasEntityType.CURRENT_TENANT || value === AliasEntityType.CURRENT_USER) { | |
101 | 101 | this.modelValue.id = NULL_UUID; |
102 | 102 | } |
103 | 103 | this.updateView(value, this.modelValue.id); |
... | ... | @@ -145,7 +145,9 @@ export class EntitySelectComponent implements ControlValueAccessor, OnInit, Afte |
145 | 145 | entityType, |
146 | 146 | id: this.modelValue.entityType !== entityType ? null : entityId |
147 | 147 | }; |
148 | - if (this.modelValue.entityType && (this.modelValue.id || this.modelValue.entityType === AliasEntityType.CURRENT_TENANT)) { | |
148 | + if (this.modelValue.entityType && (this.modelValue.id || | |
149 | + this.modelValue.entityType === AliasEntityType.CURRENT_TENANT || | |
150 | + this.modelValue.entityType === AliasEntityType.CURRENT_USER)) { | |
149 | 151 | this.propagateChange(this.modelValue); |
150 | 152 | } else { |
151 | 153 | this.propagateChange(null); | ... | ... |
... | ... | @@ -50,7 +50,8 @@ export enum EntityType { |
50 | 50 | |
51 | 51 | export enum AliasEntityType { |
52 | 52 | CURRENT_CUSTOMER = 'CURRENT_CUSTOMER', |
53 | - CURRENT_TENANT = 'CURRENT_TENANT' | |
53 | + CURRENT_TENANT = 'CURRENT_TENANT', | |
54 | + CURRENT_USER = 'CURRENT_USER' | |
54 | 55 | } |
55 | 56 | |
56 | 57 | export interface EntityTypeTranslation { |
... | ... | @@ -229,6 +230,13 @@ export const entityTypeTranslations = new Map<EntityType | AliasEntityType, Enti |
229 | 230 | type: 'entity.type-current-tenant', |
230 | 231 | list: 'entity.type-current-tenant' |
231 | 232 | } |
233 | + ], | |
234 | + [ | |
235 | + AliasEntityType.CURRENT_USER, | |
236 | + { | |
237 | + type: 'entity.type-current-user', | |
238 | + list: 'entity.type-current-user' | |
239 | + } | |
232 | 240 | ] |
233 | 241 | ] |
234 | 242 | ); | ... | ... |
... | ... | @@ -841,6 +841,7 @@ |
841 | 841 | "rulenode-name-starts-with": "Rule nodes whose names start with '{{prefix}}'", |
842 | 842 | "type-current-customer": "Current Customer", |
843 | 843 | "type-current-tenant": "Current Tenant", |
844 | + "type-current-user": "Current User", | |
844 | 845 | "search": "Search entities", |
845 | 846 | "selected-entities": "{ count, plural, 1 {1 entity} other {# entities} } selected", |
846 | 847 | "entity-name": "Entity name", | ... | ... |