From 4ccade98afad207b3134cc37aa0c6c8f5dcdae38 Mon Sep 17 00:00:00 2001 From: Piotr Belke Date: Mon, 5 Aug 2024 09:48:26 +0200 Subject: [PATCH 1/6] IKC-394 User groups permissions --- .../kouncil/config/WebSocketConfig.java | 7 +- .../DefaultUserPermissionsReloader.java | 25 +++ .../security/UserPermissionsReloader.java | 6 + .../ad/ActiveDirectoryWebSecurityConfig.java | 8 + .../InMemoryUserPermissionsReloader.java | 67 ++++++++ .../security/ldap/LdapWebSecurityConfig.java | 8 + .../security/sso/SSOWebSecurityConfig.java | 9 +- .../kouncil/notifications/Notification.java | 16 ++ .../notifications/NotificationAction.java | 6 + .../notifications/NotificationType.java | 6 + .../security/group/UserGroupService.java | 3 + .../security/group/UserGroupsController.java | 8 + .../security/group/UserGroupsService.java | 7 + kouncil-frontend/angular.json | 1 + .../apps/kouncil/src/app/app.module.ts | 5 +- .../consumer-group.component.ts | 3 +- .../kouncil/src/app/routing/routing.module.ts | 10 +- .../src/app/rx-stomp-service-factory.ts | 2 +- .../src/app/sidebar/sidebar.component.ts | 7 +- .../src/app/toolbar/toolbar.component.ts | 8 +- .../kouncil/src/app/topic/topic.component.ts | 1 - .../track-result/track-result.component.ts | 10 +- .../src/app/track/track.backend.service.ts | 2 +- .../src/app/track/track.demo.service.ts | 18 +- .../libs/feat-notifications/.eslintrc.json | 38 +++++ .../libs/feat-notifications/jest.config.ts | 22 +++ .../libs/feat-notifications/project.json | 27 +++ .../libs/feat-notifications/src/index.ts | 4 + .../src/lib/feat-notifications.module.ts | 36 ++++ .../notification-button.component.scss | 0 .../notification-button.component.ts | 59 +++++++ .../src/lib/notification.model.ts | 13 ++ .../notification/notification.component.scss | 31 ++++ .../notification/notification.component.ts | 39 +++++ .../src/lib}/rx-stomp.service.ts | 4 +- .../libs/feat-notifications/src/test-setup.ts | 1 + .../libs/feat-notifications/tsconfig.json | 28 +++ .../libs/feat-notifications/tsconfig.lib.json | 17 ++ .../feat-notifications/tsconfig.spec.json | 10 ++ .../libs/feat-user-groups/src/index.ts | 11 +- .../src/lib/feat-user-groups.module.ts | 9 +- ...ser-groups-functions-matrix.component.scss | 74 ++++++++ .../user-groups-functions-matrix.component.ts | 161 ++++++++++++++++++ .../form/user-group-form.component.ts | 6 +- .../list/user-groups.backend.service.ts | 4 + .../user-groups/list/user-groups.component.ts | 4 +- .../list/user-groups.demo.service.ts | 4 + .../user-groups/list/user-groups.service.ts | 2 + kouncil-frontend/tsconfig.base.json | 1 + 49 files changed, 810 insertions(+), 38 deletions(-) create mode 100644 kouncil-backend/src/main/java/com/consdata/kouncil/config/security/DefaultUserPermissionsReloader.java create mode 100644 kouncil-backend/src/main/java/com/consdata/kouncil/config/security/UserPermissionsReloader.java create mode 100644 kouncil-backend/src/main/java/com/consdata/kouncil/config/security/inmemory/InMemoryUserPermissionsReloader.java create mode 100644 kouncil-backend/src/main/java/com/consdata/kouncil/notifications/Notification.java create mode 100644 kouncil-backend/src/main/java/com/consdata/kouncil/notifications/NotificationAction.java create mode 100644 kouncil-backend/src/main/java/com/consdata/kouncil/notifications/NotificationType.java create mode 100644 kouncil-frontend/libs/feat-notifications/.eslintrc.json create mode 100644 kouncil-frontend/libs/feat-notifications/jest.config.ts create mode 100644 kouncil-frontend/libs/feat-notifications/project.json create mode 100644 kouncil-frontend/libs/feat-notifications/src/index.ts create mode 100644 kouncil-frontend/libs/feat-notifications/src/lib/feat-notifications.module.ts create mode 100644 kouncil-frontend/libs/feat-notifications/src/lib/notification-button/notification-button.component.scss create mode 100644 kouncil-frontend/libs/feat-notifications/src/lib/notification-button/notification-button.component.ts create mode 100644 kouncil-frontend/libs/feat-notifications/src/lib/notification.model.ts create mode 100644 kouncil-frontend/libs/feat-notifications/src/lib/notification/notification.component.scss create mode 100644 kouncil-frontend/libs/feat-notifications/src/lib/notification/notification.component.ts rename kouncil-frontend/{apps/kouncil/src/app => libs/feat-notifications/src/lib}/rx-stomp.service.ts (50%) create mode 100644 kouncil-frontend/libs/feat-notifications/src/test-setup.ts create mode 100644 kouncil-frontend/libs/feat-notifications/tsconfig.json create mode 100644 kouncil-frontend/libs/feat-notifications/tsconfig.lib.json create mode 100644 kouncil-frontend/libs/feat-notifications/tsconfig.spec.json create mode 100644 kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.scss create mode 100644 kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.ts diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/config/WebSocketConfig.java b/kouncil-backend/src/main/java/com/consdata/kouncil/config/WebSocketConfig.java index 8843be20..c5f60804 100644 --- a/kouncil-backend/src/main/java/com/consdata/kouncil/config/WebSocketConfig.java +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/config/WebSocketConfig.java @@ -1,6 +1,8 @@ package com.consdata.kouncil.config; import com.consdata.kouncil.track.DestinationStore; +import java.util.ArrayList; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; @@ -15,9 +17,6 @@ import org.springframework.web.socket.messaging.SessionSubscribeEvent; import org.springframework.web.socket.messaging.SessionUnsubscribeEvent; -import java.util.ArrayList; -import java.util.List; - @Slf4j @Configuration @EnableWebSocketMessageBroker @@ -34,7 +33,7 @@ public WebSocketConfig(DestinationStore destinationStore) { @Override public void configureMessageBroker(MessageBrokerRegistry config) { - config.enableSimpleBroker("/topic"); + config.enableSimpleBroker("/topic", "/notifications"); config.setApplicationDestinationPrefixes("/app"); } diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/DefaultUserPermissionsReloader.java b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/DefaultUserPermissionsReloader.java new file mode 100644 index 00000000..7fa9d1c6 --- /dev/null +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/DefaultUserPermissionsReloader.java @@ -0,0 +1,25 @@ +package com.consdata.kouncil.config.security; + +import com.consdata.kouncil.notifications.Notification; +import com.consdata.kouncil.notifications.NotificationAction; +import com.consdata.kouncil.notifications.NotificationType; +import lombok.RequiredArgsConstructor; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.security.core.context.SecurityContextHolder; + +@RequiredArgsConstructor +public class DefaultUserPermissionsReloader implements UserPermissionsReloader { + + private final SimpMessagingTemplate eventSender; + + @Override + public void reloadPermissions() { + SecurityContextHolder.clearContext(); + + Notification notification = new Notification(); + notification.setMessage("User permissions were updated. You have to re-login."); + notification.setType(NotificationType.PUSH_WITH_ACTION_REQUIRED); + notification.setAction(NotificationAction.LOGOUT); + eventSender.convertAndSend("/notifications", notification); + } +} diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/UserPermissionsReloader.java b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/UserPermissionsReloader.java new file mode 100644 index 00000000..cd16a412 --- /dev/null +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/UserPermissionsReloader.java @@ -0,0 +1,6 @@ +package com.consdata.kouncil.config.security; + +public interface UserPermissionsReloader { + + void reloadPermissions(); +} diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/ad/ActiveDirectoryWebSecurityConfig.java b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/ad/ActiveDirectoryWebSecurityConfig.java index eb4244bc..140dcf3e 100644 --- a/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/ad/ActiveDirectoryWebSecurityConfig.java +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/ad/ActiveDirectoryWebSecurityConfig.java @@ -1,5 +1,6 @@ package com.consdata.kouncil.config.security.ad; +import com.consdata.kouncil.config.security.DefaultUserPermissionsReloader; import com.consdata.kouncil.security.UserRolesMapping; import java.util.List; import lombok.RequiredArgsConstructor; @@ -8,6 +9,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; @@ -28,6 +30,7 @@ public class ActiveDirectoryWebSecurityConfig { private final UserRolesMapping userRolesMapping; + private final SimpMessagingTemplate eventSender; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { @@ -55,6 +58,11 @@ GrantedAuthorityDefaults grantedAuthorityDefaults() { return new GrantedAuthorityDefaults(""); // Remove the ROLE_ prefix } + @Bean + public DefaultUserPermissionsReloader userPermissionsReloader(){ + return new DefaultUserPermissionsReloader(eventSender); + } + @Value("${kouncil.auth.ad.domain:}") public String domain; diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/inmemory/InMemoryUserPermissionsReloader.java b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/inmemory/InMemoryUserPermissionsReloader.java new file mode 100644 index 00000000..7dfef480 --- /dev/null +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/inmemory/InMemoryUserPermissionsReloader.java @@ -0,0 +1,67 @@ +package com.consdata.kouncil.config.security.inmemory; + +import static com.consdata.kouncil.config.security.inmemory.InMemoryConst.ADMIN_CONFIG; +import static com.consdata.kouncil.config.security.inmemory.InMemoryConst.ADMIN_USERNAME; +import static com.consdata.kouncil.config.security.inmemory.InMemoryConst.EDITOR_CONFIG; +import static com.consdata.kouncil.config.security.inmemory.InMemoryConst.EDITOR_USERNAME; +import static com.consdata.kouncil.config.security.inmemory.InMemoryConst.SUPERUSER_CONFIG; +import static com.consdata.kouncil.config.security.inmemory.InMemoryConst.SUPERUSER_USERNAME; +import static com.consdata.kouncil.config.security.inmemory.InMemoryConst.VIEWER_CONFIG; +import static com.consdata.kouncil.config.security.inmemory.InMemoryConst.VIEWER_USERNAME; + +import com.consdata.kouncil.KouncilRuntimeException; +import com.consdata.kouncil.config.security.DefaultUserPermissionsReloader; +import com.consdata.kouncil.security.UserRolesMapping; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Set; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.provisioning.UserDetailsManager; +import org.springframework.stereotype.Service; + +@Service +@ConditionalOnProperty(prefix = "kouncil.auth", name = "active-provider", havingValue = "inmemory") +public class InMemoryUserPermissionsReloader extends DefaultUserPermissionsReloader { + + private final UserDetailsManager userDetailsService; + private final UserRolesMapping userRolesMapping; + + public InMemoryUserPermissionsReloader(SimpMessagingTemplate eventSender, UserDetailsManager userDetailsService, + UserRolesMapping userRolesMapping) { + super(eventSender); + this.userDetailsService = userDetailsService; + this.userRolesMapping = userRolesMapping; + } + + @Override + public void reloadPermissions() { + super.reloadPermissions(); + List.of(ADMIN_USERNAME, EDITOR_USERNAME, VIEWER_USERNAME, SUPERUSER_USERNAME).forEach(user -> { + try { + String[] fileContent = Files.readString(getPath(user)).split(";"); + userDetailsService.updateUser(User.withUsername(user) + .password(String.format("{noop}%s", fileContent[0])) + .authorities(userRolesMapping.mapToKouncilRoles(Set.of(fileContent[1].split(",")))) + .build()); + } catch (IOException e) { + throw new KouncilRuntimeException(e); + } + }); + } + + private Path getPath(String username) { + return switch (username) { + case ADMIN_USERNAME -> Paths.get(ADMIN_CONFIG); + case EDITOR_USERNAME -> Paths.get(EDITOR_CONFIG); + case VIEWER_USERNAME -> Paths.get(VIEWER_CONFIG); + case SUPERUSER_USERNAME -> Paths.get(SUPERUSER_CONFIG); + default -> throw new IllegalStateException(String.format("Can't find user: %s", SecurityContextHolder.getContext().getAuthentication().getName())); + }; + } +} diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/ldap/LdapWebSecurityConfig.java b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/ldap/LdapWebSecurityConfig.java index 57cc848c..a741b16c 100644 --- a/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/ldap/LdapWebSecurityConfig.java +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/ldap/LdapWebSecurityConfig.java @@ -1,5 +1,6 @@ package com.consdata.kouncil.config.security.ldap; +import com.consdata.kouncil.config.security.DefaultUserPermissionsReloader; import com.consdata.kouncil.security.UserRolesMapping; import java.util.List; import lombok.RequiredArgsConstructor; @@ -9,6 +10,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.ldap.core.support.LdapContextSource; +import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; @@ -32,6 +34,7 @@ public class LdapWebSecurityConfig { private final UserRolesMapping userRolesMapping; + private final SimpMessagingTemplate eventSender; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { @@ -65,6 +68,11 @@ public AuthenticationManager authenticationManager(HttpSecurity http) throws Exc .build(); } + @Bean + public DefaultUserPermissionsReloader userPermissionsReloader(){ + return new DefaultUserPermissionsReloader(eventSender); + } + @Value("${kouncil.auth.ldap.provider-url:}") private String providerUrl; diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/sso/SSOWebSecurityConfig.java b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/sso/SSOWebSecurityConfig.java index 6ccc9d16..975381fd 100644 --- a/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/sso/SSOWebSecurityConfig.java +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/sso/SSOWebSecurityConfig.java @@ -1,5 +1,6 @@ package com.consdata.kouncil.config.security.sso; +import com.consdata.kouncil.config.security.DefaultUserPermissionsReloader; import com.consdata.kouncil.security.UserRolesMapping; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; @@ -14,6 +15,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -37,8 +39,8 @@ public class SSOWebSecurityConfig { private final ObjectMapper mapper; - private final UserRolesMapping userRolesMapping; + private final SimpMessagingTemplate eventSender; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { @@ -83,6 +85,11 @@ GrantedAuthorityDefaults grantedAuthorityDefaults() { return new GrantedAuthorityDefaults(""); // Remove the ROLE_ prefix } + @Bean + public DefaultUserPermissionsReloader userPermissionsReloader(){ + return new DefaultUserPermissionsReloader(eventSender); + } + private GrantedAuthoritiesMapper authoritiesMapper() { return authorities -> { Set mappedAuthorities = new HashSet<>(); diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/notifications/Notification.java b/kouncil-backend/src/main/java/com/consdata/kouncil/notifications/Notification.java new file mode 100644 index 00000000..748c637e --- /dev/null +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/notifications/Notification.java @@ -0,0 +1,16 @@ +package com.consdata.kouncil.notifications; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class Notification { + + private String message; + private NotificationType type; + private NotificationAction action; + +} diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/notifications/NotificationAction.java b/kouncil-backend/src/main/java/com/consdata/kouncil/notifications/NotificationAction.java new file mode 100644 index 00000000..fefe53ce --- /dev/null +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/notifications/NotificationAction.java @@ -0,0 +1,6 @@ +package com.consdata.kouncil.notifications; + +public enum NotificationAction { + + LOGOUT +} diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/notifications/NotificationType.java b/kouncil-backend/src/main/java/com/consdata/kouncil/notifications/NotificationType.java new file mode 100644 index 00000000..b79c8f4a --- /dev/null +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/notifications/NotificationType.java @@ -0,0 +1,6 @@ +package com.consdata.kouncil.notifications; + +public enum NotificationType { + PUSH_WITH_ACTION_REQUIRED, + PUSH +} diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupService.java b/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupService.java index 925b3da9..ae91c7c4 100644 --- a/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupService.java +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupService.java @@ -1,6 +1,7 @@ package com.consdata.kouncil.security.group; import com.consdata.kouncil.KouncilRuntimeException; +import com.consdata.kouncil.config.security.UserPermissionsReloader; import com.consdata.kouncil.model.admin.UserGroup; import com.consdata.kouncil.security.group.dto.UserGroupDto; import lombok.RequiredArgsConstructor; @@ -11,6 +12,7 @@ public class UserGroupService { private final UserGroupRepository userGroupRepository; + private final UserPermissionsReloader userPermissionsReloader; public UserGroupDto getUserGroup(Long id) { return UserGroupConverter.convertToUserGroupDto(findById(id)); @@ -26,6 +28,7 @@ public void createUserGroup(UserGroupDto userGroup) { public void updateUserGroup(UserGroupDto userGroup) { userGroupRepository.save(UserGroupConverter.updateUserGroup(userGroup, findById(userGroup.getId()))); + userPermissionsReloader.reloadPermissions(); } public void deleteUserGroup(Long id) { diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupsController.java b/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupsController.java index 53e4de69..a663855f 100644 --- a/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupsController.java +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupsController.java @@ -6,6 +6,8 @@ import javax.annotation.security.RolesAllowed; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -21,4 +23,10 @@ public class UserGroupsController { public List getUserGroups() { return userGroupsService.getUserGroups(); } + + @RolesAllowed(Fields.USER_GROUPS) + @PostMapping + public void updatePermissions(@RequestBody List userGroupDtoList) { + userGroupsService.saveAll(userGroupDtoList); + } } diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupsService.java b/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupsService.java index 9ba5abc7..e7ffe850 100644 --- a/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupsService.java +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupsService.java @@ -1,5 +1,6 @@ package com.consdata.kouncil.security.group; +import com.consdata.kouncil.config.security.UserPermissionsReloader; import com.consdata.kouncil.security.group.dto.UserGroupDto; import java.util.List; import java.util.stream.StreamSupport; @@ -11,10 +12,16 @@ public class UserGroupsService { private final UserGroupRepository userGroupRepository; + private final UserPermissionsReloader userPermissionsReloader; public List getUserGroups() { return StreamSupport.stream(userGroupRepository.findAll().spliterator(), false) .map(UserGroupConverter::convertToUserGroupDto) .toList(); } + + public void saveAll(List userGroupDtoList) { + userGroupRepository.saveAll(userGroupDtoList.stream().map(UserGroupConverter::convertToUserGroup).toList()); + userPermissionsReloader.reloadPermissions(); + } } diff --git a/kouncil-frontend/angular.json b/kouncil-frontend/angular.json index b7bfdc12..6548b4dc 100644 --- a/kouncil-frontend/angular.json +++ b/kouncil-frontend/angular.json @@ -10,6 +10,7 @@ "feat-confirm": "libs/feat-confirm", "feat-favourites": "libs/feat-favourites", "feat-no-data": "libs/feat-no-data", + "feat-notifications": "libs/feat-notifications", "feat-send": "libs/feat-send", "feat-topic-form": "libs/feat-topic-form", "feat-topics": "libs/feat-topics", diff --git a/kouncil-frontend/apps/kouncil/src/app/app.module.ts b/kouncil-frontend/apps/kouncil/src/app/app.module.ts index f9db63f2..28fb7835 100644 --- a/kouncil-frontend/apps/kouncil/src/app/app.module.ts +++ b/kouncil-frontend/apps/kouncil/src/app/app.module.ts @@ -113,8 +113,8 @@ import { UserGroupService, UserGroupsService } from '@app/feat-user-groups'; -import {RxStompService} from './rx-stomp.service'; import {RX_STOMP_CONFIG} from './rx-stomp.config'; +import {FeatNotificationsModule, RxStompService} from '@app/feat-notifications'; export const BASE_URL = new InjectionToken('BASE_URL'); @@ -231,7 +231,8 @@ export function authServiceFactory(http: HttpClient, baseUrl: string): AuthServi CommonAuthModule, FeatTopicFormModule, FeatClustersModule, - FeatUserGroupsModule + FeatUserGroupsModule, + FeatNotificationsModule ], providers: [ { diff --git a/kouncil-frontend/apps/kouncil/src/app/consumers/consumer-group/consumer-group.component.ts b/kouncil-frontend/apps/kouncil/src/app/consumers/consumer-group/consumer-group.component.ts index 1720c880..8ac6f392 100644 --- a/kouncil-frontend/apps/kouncil/src/app/consumers/consumer-group/consumer-group.component.ts +++ b/kouncil-frontend/apps/kouncil/src/app/consumers/consumer-group/consumer-group.component.ts @@ -1,5 +1,5 @@ import {Component, Inject, LOCALE_ID, OnDestroy, OnInit} from '@angular/core'; -import {interval, Observable, Subscription} from 'rxjs'; +import {interval, Subscription} from 'rxjs'; import {ActivatedRoute} from '@angular/router'; import {ConsumerGroupService} from './consumer-group.service'; import {switchMap, tap} from 'rxjs/operators'; @@ -61,7 +61,6 @@ export class ConsumerGroupComponent extends AbstractTableComponent implements On filteredAssignments: ConsumerGroupOffset[] = []; paused: boolean = false; lastLags: IHash = {}; - loading$: Observable = this.progressBarService.loading$; additionalColumns: TableColumn[] = [ { diff --git a/kouncil-frontend/apps/kouncil/src/app/routing/routing.module.ts b/kouncil-frontend/apps/kouncil/src/app/routing/routing.module.ts index 44f87371..c30fd9c2 100644 --- a/kouncil-frontend/apps/kouncil/src/app/routing/routing.module.ts +++ b/kouncil-frontend/apps/kouncil/src/app/routing/routing.module.ts @@ -32,7 +32,7 @@ import { ClusterFormViewComponent, ClustersComponent } from '@app/feat-clusters'; -import {UserGroupsComponent} from '@app/feat-user-groups'; +import {UserGroupsComponent, UserGroupsFunctionsMatrixComponent} from '@app/feat-user-groups'; @Injectable() export class ReloadingRouterStrategy extends RouteReuseStrategy { @@ -194,6 +194,14 @@ const routes: Routes = [ data: { roles: [KouncilRole.USER_GROUPS_LIST] } + }, + { + path: 'user-groups-permissions', + component: UserGroupsFunctionsMatrixComponent, + canActivate: [AuthGuard], + data: { + roles: [KouncilRole.USER_GROUPS] + } } ] }, diff --git a/kouncil-frontend/apps/kouncil/src/app/rx-stomp-service-factory.ts b/kouncil-frontend/apps/kouncil/src/app/rx-stomp-service-factory.ts index 2c88f3ec..6b9678c6 100644 --- a/kouncil-frontend/apps/kouncil/src/app/rx-stomp-service-factory.ts +++ b/kouncil-frontend/apps/kouncil/src/app/rx-stomp-service-factory.ts @@ -1,4 +1,4 @@ -import { RxStompService } from './rx-stomp.service'; +import {RxStompService} from '@app/feat-notifications'; import {RX_STOMP_CONFIG} from './rx-stomp.config'; export function rxStompServiceFactory(): RxStompService { diff --git a/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts b/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts index b1e416b6..0635074e 100644 --- a/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts +++ b/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts @@ -33,7 +33,7 @@ import {Backend} from '@app/common-model'; + + +
+ + `, + changeDetection: ChangeDetectionStrategy.OnPush, + styleUrls: ['./notification.component.scss'] +}) +export class NotificationComponent { + + constructor(@Inject(MAT_DIALOG_DATA) public data: NotificationModel) { + } + + actionBtnLabel(): string { + switch (this.data.action) { + case NotificationAction.LOGOUT: + return 'Logout'; + } + return ''; + } +} diff --git a/kouncil-frontend/apps/kouncil/src/app/rx-stomp.service.ts b/kouncil-frontend/libs/feat-notifications/src/lib/rx-stomp.service.ts similarity index 50% rename from kouncil-frontend/apps/kouncil/src/app/rx-stomp.service.ts rename to kouncil-frontend/libs/feat-notifications/src/lib/rx-stomp.service.ts index 11420dd2..603e8f02 100644 --- a/kouncil-frontend/apps/kouncil/src/app/rx-stomp.service.ts +++ b/kouncil-frontend/libs/feat-notifications/src/lib/rx-stomp.service.ts @@ -1,5 +1,5 @@ -import { Injectable } from '@angular/core'; -import { RxStomp } from '@stomp/rx-stomp'; +import {Injectable} from '@angular/core'; +import {RxStomp} from '@stomp/rx-stomp'; @Injectable({ providedIn: 'root', diff --git a/kouncil-frontend/libs/feat-notifications/src/test-setup.ts b/kouncil-frontend/libs/feat-notifications/src/test-setup.ts new file mode 100644 index 00000000..1100b3e8 --- /dev/null +++ b/kouncil-frontend/libs/feat-notifications/src/test-setup.ts @@ -0,0 +1 @@ +import 'jest-preset-angular/setup-jest'; diff --git a/kouncil-frontend/libs/feat-notifications/tsconfig.json b/kouncil-frontend/libs/feat-notifications/tsconfig.json new file mode 100644 index 00000000..1c995b83 --- /dev/null +++ b/kouncil-frontend/libs/feat-notifications/tsconfig.json @@ -0,0 +1,28 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/kouncil-frontend/libs/feat-notifications/tsconfig.lib.json b/kouncil-frontend/libs/feat-notifications/tsconfig.lib.json new file mode 100644 index 00000000..8e00439a --- /dev/null +++ b/kouncil-frontend/libs/feat-notifications/tsconfig.lib.json @@ -0,0 +1,17 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": [ + "src/test-setup.ts", + "**/*.spec.ts", + "jest.config.ts", + "**/*.test.ts" + ], + "include": ["**/*.ts"] +} diff --git a/kouncil-frontend/libs/feat-notifications/tsconfig.spec.json b/kouncil-frontend/libs/feat-notifications/tsconfig.spec.json new file mode 100644 index 00000000..c5db0277 --- /dev/null +++ b/kouncil-frontend/libs/feat-notifications/tsconfig.spec.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "files": ["src/test-setup.ts"], + "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] +} diff --git a/kouncil-frontend/libs/feat-user-groups/src/index.ts b/kouncil-frontend/libs/feat-user-groups/src/index.ts index 6dfca509..c27dbd88 100644 --- a/kouncil-frontend/libs/feat-user-groups/src/index.ts +++ b/kouncil-frontend/libs/feat-user-groups/src/index.ts @@ -1,7 +1,11 @@ export {FeatUserGroupsModule} from './lib/feat-user-groups.module'; export {FunctionsService} from './lib/user-groups-functions-matrix/functions/functions.service'; -export {FunctionsDemoService} from './lib/user-groups-functions-matrix/functions/functions.demo.service'; -export {FunctionsBackendService} from './lib/user-groups-functions-matrix/functions/functions.backend.service'; +export { + FunctionsDemoService +} from './lib/user-groups-functions-matrix/functions/functions.demo.service'; +export { + FunctionsBackendService +} from './lib/user-groups-functions-matrix/functions/functions.backend.service'; export {UserGroupsService} from './lib/user-groups/list/user-groups.service'; export {UserGroupsDemoService} from './lib/user-groups/list/user-groups.demo.service'; export {UserGroupsBackendService} from './lib/user-groups/list/user-groups.backend.service'; @@ -10,3 +14,6 @@ export {UserGroupDemoService} from './lib/user-groups/list/user-group.demo.servi export {UserGroupBackendService} from './lib/user-groups/list/user-group.backend.service'; export {UserGroupFormComponent} from './lib/user-groups/form/user-group-form.component'; export {UserGroupsComponent} from './lib/user-groups/list/user-groups.component'; +export { + UserGroupsFunctionsMatrixComponent +} from './lib/user-groups-functions-matrix/user-groups-functions-matrix.component'; diff --git a/kouncil-frontend/libs/feat-user-groups/src/lib/feat-user-groups.module.ts b/kouncil-frontend/libs/feat-user-groups/src/lib/feat-user-groups.module.ts index 874294d3..ded91979 100644 --- a/kouncil-frontend/libs/feat-user-groups/src/lib/feat-user-groups.module.ts +++ b/kouncil-frontend/libs/feat-user-groups/src/lib/feat-user-groups.module.ts @@ -13,6 +13,9 @@ import {FeatNoDataModule} from '@app/feat-no-data'; import {UserGroupFormComponent} from './user-groups/form/user-group-form.component'; import {MatDialogModule} from '@angular/material/dialog'; import {ReactiveFormsModule} from '@angular/forms'; +import { + UserGroupsFunctionsMatrixComponent +} from './user-groups-functions-matrix/user-groups-functions-matrix.component'; @NgModule({ imports: [ @@ -31,11 +34,13 @@ import {ReactiveFormsModule} from '@angular/forms'; ], declarations: [ UserGroupsComponent, - UserGroupFormComponent + UserGroupFormComponent, + UserGroupsFunctionsMatrixComponent ], exports: [ UserGroupsComponent, - UserGroupFormComponent + UserGroupFormComponent, + UserGroupsFunctionsMatrixComponent ] }) export class FeatUserGroupsModule { diff --git a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.scss b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.scss new file mode 100644 index 00000000..18252fd6 --- /dev/null +++ b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.scss @@ -0,0 +1,74 @@ +@use '../../../../../apps/kouncil/src/styles/buttons'; +@import "../../../../../apps/kouncil/src/styles/spaces"; +@import "../../../../../apps/kouncil/src/styles/palette"; + +.user-groups-header { + margin: $space-5; + display: flex; + flex-direction: row; + align-items: center; + + .user-groups-title { + font-size: 20px; + font-weight: 500; + line-height: 28px; + flex-basis: 100%; + } + + .user-groups-actions { + display: flex; + gap: 16px; + + .action-button-white { + @include buttons.button-white; + } + + .action-button-blue { + @include buttons.button-blue; + } + } +} + +.user-groups-main-container { + display: flex; + flex-direction: column; + gap: $space-5; + margin: $space-5; + + .user-group-title { + font-size: 16px; + font-weight: 500; + } + + .user-groups-table-header-row { + font-size: 12px; + } + + .user-groups-table-header-row, .user-groups-table-row { + display: flex; + flex-direction: row; + height: 32px; + padding: $space-2; + + .user-groups-label-column { + flex-basis: 15%; + display: flex; + place-items: center; + place-content: center; + font-size: 12px; + } + + .user-groups-table-header-row-columns, .user-groups-table-row-columns { + display: flex; + flex-direction: row; + justify-content: space-between; + flex-basis: 85%; + + .user-groups-table-header-row-column, .user-groups-table-row-column { + display: flex; + place-items: center; + place-content: center; + } + } + } +} diff --git a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.ts b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.ts new file mode 100644 index 00000000..98fec9f0 --- /dev/null +++ b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.ts @@ -0,0 +1,161 @@ +import {Component, OnDestroy, OnInit} from '@angular/core'; +import {UserGroupsService} from '../user-groups/list/user-groups.service'; +import {Subscription} from 'rxjs'; +import {FunctionGroup, SystemFunction, UserGroup} from './user-groups.model'; +import {FunctionsService} from './functions/functions.service'; +import {ProgressBarService, ViewMode} from '@app/common-utils'; +import {MatCheckboxChange} from '@angular/material/checkbox'; + + +@Component({ + selector: 'app-user-groups-functions-matrix', + template: ` +
+
+ Manage user groups +
+ +
+ + + +
+ +
+ + + + + + + + + + + + + {{ functionGroup.key.replace('_', " ") | titlecase }} + + + +
+ +
+ +
+ +
+ {{ systemFunction.label }} +
+
+
+
+ + +
+
+ {{ userGroup.name }} +
+
+ +
+ +
+
+
+
+
+
+
+
+ `, + styleUrls: ['./user-groups-functions-matrix.component.scss'], +}) +export class UserGroupsFunctionsMatrixComponent implements OnInit, OnDestroy { + + viewMode: ViewMode = ViewMode.VIEW; + ViewMode: typeof ViewMode = ViewMode; + + private subscription: Subscription = new Subscription(); + + userGroups: Array; + systemFunctionsGroups: Map>; + + systemFunctionsGroupsCopy: Map> = new Map>(); + + constructor(private userGroupsService: UserGroupsService, + private functionsService: FunctionsService, + private progressBarService: ProgressBarService) { + } + + ngOnInit(): void { + this.progressBarService.setProgress(true); + this.subscription.add(this.userGroupsService.getUserGroups$().subscribe(result => { + this.userGroups = result; + this.progressBarService.setProgress(false); + })); + + this.subscription.add(this.functionsService.getFunctions$().subscribe((result: Array) => { + this.systemFunctionsGroups = new Map>(); + result.forEach((fn: SystemFunction) => { + if (!this.systemFunctionsGroups.has(fn.functionGroup)) { + this.systemFunctionsGroups.set(fn.functionGroup, []); + } + this.systemFunctionsGroups.get(fn.functionGroup).push(fn); + this.progressBarService.setProgress(false); + }); + })); + } + + ngOnDestroy(): void { + this.subscription.unsubscribe(); + } + + functionHasUserGroup(userGroup: UserGroup, systemFunction: SystemFunction): boolean { + return userGroup.functions.map(sf => sf.name).includes(systemFunction.name); + } + + cancel(): void { + this.viewMode = ViewMode.VIEW; + this.systemFunctionsGroups = structuredClone(this.systemFunctionsGroupsCopy); + } + + edit(): void { + this.viewMode = ViewMode.EDIT; + this.systemFunctionsGroupsCopy = structuredClone(this.systemFunctionsGroups); + } + + change($event: MatCheckboxChange, userGroup: UserGroup, systemFunction: SystemFunction): void { + if ($event.checked) { + // check + userGroup.functions.push(systemFunction); + } else { + // uncheck + userGroup.functions.splice(userGroup.functions.map(sf => sf.name).indexOf(systemFunction.name), 1); + } + } + + save(): void { + this.viewMode = ViewMode.VIEW; + this.subscription.add(this.userGroupsService.updatePermissions$(this.userGroups).subscribe(() => { + })); + } +} diff --git a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/form/user-group-form.component.ts b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/form/user-group-form.component.ts index 9fa3d8ea..a64e7f53 100644 --- a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/form/user-group-form.component.ts +++ b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/form/user-group-form.component.ts @@ -118,7 +118,11 @@ export class UserGroupFormComponent implements OnInit, OnDestroy { this.subscriptions.add(observable$.pipe(first()) .subscribe({ next: () => { - this.dialog.closeAll(); + this.dialog.openDialogs.forEach(dialog => { + if (dialog.componentInstance === this) { + dialog.close(); + } + }); this.snackbar.openFromComponent(SnackBarComponent, { data: new SnackBarData(successMsg, 'snackbar-success', ''), panelClass: ['snackbar'], diff --git a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.backend.service.ts b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.backend.service.ts index ab79d582..11d360ca 100644 --- a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.backend.service.ts +++ b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.backend.service.ts @@ -15,4 +15,8 @@ export class UserGroupsBackendService implements UserGroupsService { getUserGroups$(): Observable> { return this.http.get>('/api/user-groups'); } + + updatePermissions$(userGroups: Array): Observable { + return this.http.post('/api/user-groups', userGroups); + } } diff --git a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.component.ts b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.component.ts index 234858f4..be35442d 100644 --- a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.component.ts +++ b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.component.ts @@ -137,7 +137,9 @@ export class UserGroupsComponent extends AbstractTableComponent implements OnIni const matDialogRef = this.dialog.open(UserGroupFormComponent, config); this.subscription.add(matDialogRef.afterClosed().subscribe(() => { - this.loadGroups(); + if (!id) { + this.loadGroups(); + } })); } diff --git a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.demo.service.ts b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.demo.service.ts index d8622e98..3a8a8440 100644 --- a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.demo.service.ts +++ b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.demo.service.ts @@ -11,4 +11,8 @@ export class UserGroupsDemoService implements UserGroupsService { getUserGroups$(): Observable> { return of(); } + + updatePermissions$(_userGroups: Array): Observable { + return of(); + } } diff --git a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.service.ts b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.service.ts index 7f89f763..8f8b3d0b 100644 --- a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.service.ts +++ b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.service.ts @@ -6,4 +6,6 @@ import {UserGroup} from '../../user-groups-functions-matrix/user-groups.model'; export abstract class UserGroupsService { abstract getUserGroups$(): Observable>; + + abstract updatePermissions$(userGroups: Array): Observable; } diff --git a/kouncil-frontend/tsconfig.base.json b/kouncil-frontend/tsconfig.base.json index 09b9ba98..50249912 100644 --- a/kouncil-frontend/tsconfig.base.json +++ b/kouncil-frontend/tsconfig.base.json @@ -34,6 +34,7 @@ "@app/feat-confirm": ["libs/feat-confirm/src/index.ts"], "@app/feat-favourites": ["libs/feat-favourites/src/index.ts"], "@app/feat-no-data": ["libs/feat-no-data/src/index.ts"], + "@app/feat-notifications": ["libs/feat-notifications/src/index.ts"], "@app/feat-send": ["libs/feat-send/src/index.ts"], "@app/feat-topic-form": ["libs/feat-topic-form/src/index.ts"], "@app/feat-topics": ["libs/feat-topics/src/index.ts"], From 21607e53505654f2b7bf92f5d33f7fbcfe8b993e Mon Sep 17 00:00:00 2001 From: Piotr Belke Date: Thu, 8 Aug 2024 17:57:52 +0200 Subject: [PATCH 2/6] IKC-394 User groups permissions --- .../com/consdata/kouncil/security/group/UserGroupService.java | 1 + .../apps/kouncil/src/app/routing/routing.module.ts | 2 +- .../src/lib/user-groups/list/user-groups.component.ts | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupService.java b/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupService.java index ae91c7c4..2d6438c5 100644 --- a/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupService.java +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/security/group/UserGroupService.java @@ -33,6 +33,7 @@ public void updateUserGroup(UserGroupDto userGroup) { public void deleteUserGroup(Long id) { userGroupRepository.deleteById(id); + userPermissionsReloader.reloadPermissions(); } public boolean isUserGroupCodeUnique(Long id, String userGroupName) { diff --git a/kouncil-frontend/apps/kouncil/src/app/routing/routing.module.ts b/kouncil-frontend/apps/kouncil/src/app/routing/routing.module.ts index 2046a628..2cd785c9 100644 --- a/kouncil-frontend/apps/kouncil/src/app/routing/routing.module.ts +++ b/kouncil-frontend/apps/kouncil/src/app/routing/routing.module.ts @@ -200,7 +200,7 @@ const routes: Routes = [ component: UserGroupsFunctionsMatrixComponent, canActivate: [AuthGuard], data: { - roles: [KouncilRole.USER_GROUPS] + roles: [SystemFunctionName.USER_GROUPS] } } ] diff --git a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.component.ts b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.component.ts index c95ba3ce..85e59f62 100644 --- a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.component.ts +++ b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups/list/user-groups.component.ts @@ -164,8 +164,7 @@ export class UserGroupsComponent extends AbstractTableComponent implements OnIni .pipe(first()) .subscribe({ next: () => { - this.loadGroups(); - + this.progressBarService.setProgress(false); this.snackbar.openFromComponent(SnackBarComponent, { data: new SnackBarData(`User group ${userGroupName} deleted`, 'snackbar-success', ''), panelClass: ['snackbar'], From 2a0d87c01964cb338cffcf63c2594438aa684e35 Mon Sep 17 00:00:00 2001 From: Piotr Belke Date: Wed, 21 Aug 2024 18:37:34 +0200 Subject: [PATCH 3/6] IKC-394 User groups permissions --- .../src/lib/feat-notifications.module.ts | 4 ++-- .../notification-button.component.scss | 0 .../notification-button/notification-button.component.ts | 8 +++----- .../user-groups-functions-matrix.component.scss | 4 ++-- .../user-groups-functions-matrix.component.ts | 6 +++--- 5 files changed, 10 insertions(+), 12 deletions(-) delete mode 100644 kouncil-frontend/libs/feat-notifications/src/lib/notification-button/notification-button.component.scss diff --git a/kouncil-frontend/libs/feat-notifications/src/lib/feat-notifications.module.ts b/kouncil-frontend/libs/feat-notifications/src/lib/feat-notifications.module.ts index 5ef000e6..cdcea8ca 100644 --- a/kouncil-frontend/libs/feat-notifications/src/lib/feat-notifications.module.ts +++ b/kouncil-frontend/libs/feat-notifications/src/lib/feat-notifications.module.ts @@ -21,11 +21,11 @@ import {MatDialogModule} from '@angular/material/dialog'; CommonComponentsModule, MatSortModule, DragDropModule, - MatDialogModule, + MatDialogModule ], declarations: [ NotificationButtonComponent, - NotificationComponent, + NotificationComponent ], exports: [ NotificationButtonComponent, diff --git a/kouncil-frontend/libs/feat-notifications/src/lib/notification-button/notification-button.component.scss b/kouncil-frontend/libs/feat-notifications/src/lib/notification-button/notification-button.component.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/kouncil-frontend/libs/feat-notifications/src/lib/notification-button/notification-button.component.ts b/kouncil-frontend/libs/feat-notifications/src/lib/notification-button/notification-button.component.ts index 6f66fd19..11dfca7e 100644 --- a/kouncil-frontend/libs/feat-notifications/src/lib/notification-button/notification-button.component.ts +++ b/kouncil-frontend/libs/feat-notifications/src/lib/notification-button/notification-button.component.ts @@ -9,10 +9,8 @@ import {NotificationAction, NotificationModel, NotificationType} from '../notifi @Component({ selector: 'app-notification-button', - template: ` - `, - changeDetection: ChangeDetectionStrategy.OnPush, - styleUrls: ['./notification-button.component.scss'] + template: ``, + changeDetection: ChangeDetectionStrategy.OnPush }) export class NotificationButtonComponent implements OnDestroy { @@ -51,7 +49,7 @@ export class NotificationButtonComponent implements OnDestroy { })); } - private logout() { + private logout(): void { this.subscription.add(this.authService.logout$().subscribe(() => { this.router.navigate(['/login']); })); diff --git a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.scss b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.scss index 18252fd6..f27fc52c 100644 --- a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.scss +++ b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.scss @@ -1,6 +1,6 @@ @use '../../../../../apps/kouncil/src/styles/buttons'; -@import "../../../../../apps/kouncil/src/styles/spaces"; -@import "../../../../../apps/kouncil/src/styles/palette"; +@import '../../../../../apps/kouncil/src/styles/spaces'; +@import '../../../../../apps/kouncil/src/styles/palette'; .user-groups-header { margin: $space-5; diff --git a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.ts b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.ts index 98fec9f0..06b805c3 100644 --- a/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.ts +++ b/kouncil-frontend/libs/feat-user-groups/src/lib/user-groups-functions-matrix/user-groups-functions-matrix.component.ts @@ -6,7 +6,6 @@ import {FunctionsService} from './functions/functions.service'; import {ProgressBarService, ViewMode} from '@app/common-utils'; import {MatCheckboxChange} from '@angular/material/checkbox'; - @Component({ selector: 'app-user-groups-functions-matrix', template: ` @@ -40,8 +39,9 @@ import {MatCheckboxChange} from '@angular/material/checkbox'; - + From 4481fb0892d04d56309051a8f46a9892e7324568 Mon Sep 17 00:00:00 2001 From: Piotr Belke Date: Thu, 22 Aug 2024 10:07:12 +0200 Subject: [PATCH 4/6] IKC-394 User groups permissions --- .../config/security/DefaultUserPermissionsReloader.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/DefaultUserPermissionsReloader.java b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/DefaultUserPermissionsReloader.java index 7fa9d1c6..56bc8e10 100644 --- a/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/DefaultUserPermissionsReloader.java +++ b/kouncil-backend/src/main/java/com/consdata/kouncil/config/security/DefaultUserPermissionsReloader.java @@ -5,7 +5,6 @@ import com.consdata.kouncil.notifications.NotificationType; import lombok.RequiredArgsConstructor; import org.springframework.messaging.simp.SimpMessagingTemplate; -import org.springframework.security.core.context.SecurityContextHolder; @RequiredArgsConstructor public class DefaultUserPermissionsReloader implements UserPermissionsReloader { @@ -14,8 +13,6 @@ public class DefaultUserPermissionsReloader implements UserPermissionsReloader { @Override public void reloadPermissions() { - SecurityContextHolder.clearContext(); - Notification notification = new Notification(); notification.setMessage("User permissions were updated. You have to re-login."); notification.setType(NotificationType.PUSH_WITH_ACTION_REQUIRED); From 01563a3dc75701a837a467b78833ccfacdab28c5 Mon Sep 17 00:00:00 2001 From: Piotr Belke Date: Sun, 8 Sep 2024 12:06:12 +0200 Subject: [PATCH 5/6] IKC-394 User groups permissions --- .../apps/kouncil/src/app/sidebar/sidebar.component.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts b/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts index bc214a7f..78cbb7a5 100644 --- a/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts +++ b/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts @@ -34,22 +34,20 @@ import {SidebarState} from './sidebar-state'; - + *ngIf="(isAuthenticated$ | async) && authService.canAccess([SystemFunctionName.USER_GROUPS_LIST])"> + *ngIf="(isAuthenticated$ | async) && authService.canAccess([SystemFunctionName.USER_GROUPS])">
From ad5bed8d254729fb42365499d9d8851a7cc54333 Mon Sep 17 00:00:00 2001 From: Piotr Belke Date: Sun, 8 Sep 2024 12:14:14 +0200 Subject: [PATCH 6/6] IKC-394 User groups permissions --- .../apps/kouncil/src/app/sidebar/sidebar.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts b/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts index 78cbb7a5..3afeb3c0 100644 --- a/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts +++ b/kouncil-frontend/apps/kouncil/src/app/sidebar/sidebar.component.ts @@ -34,7 +34,8 @@ import {SidebarState} from './sidebar-state';