diff --git a/kontor-api/src/db/models/admin.py b/kontor-api/src/db/models/admin.py index 47441a5..e16b0e0 100644 --- a/kontor-api/src/db/models/admin.py +++ b/kontor-api/src/db/models/admin.py @@ -7,15 +7,15 @@ from sqlalchemy.orm import relationship, mapped_column, Mapped from src.db.models.base import Base, BaseMixin -class User(Base, BaseMixin): - __tablename__ = 'user' +class Profile(Base, BaseMixin): + __tablename__ = 'profile' first_name = Column(String(255)) last_name = Column(String(255)) user_name = Column(String(255), nullable=False) email = Column(String(255)) password = Column(String(255)) enabled = Column(BIT(1)) - matrix = relationship("AuthorizationMatrix") + assignments = relationship("Assignment") tokens = relationship("Token") def get_full_name(self) -> str: @@ -35,22 +35,22 @@ class Token(Base, BaseMixin): name = Column(String(255)) last_used_date: Mapped[datetime] = mapped_column() enabled = Column(BIT(1)) - user_id = Column(String(255), ForeignKey("user.id"), nullable=False) - user = relationship("User", back_populates="tokens") + profile_id = Column(String(255), ForeignKey("profile.id"), nullable=False) + profile = relationship("Profile", back_populates="tokens") -class Role(Base, BaseMixin): - __tablename__ = "role" +class Permission(Base, BaseMixin): + __tablename__ = "permission" name = Column(String(255), nullable=False) - matrix = relationship("AuthorizationMatrix") + assignments = relationship("Assignment") -class AuthorizationMatrix(Base, BaseMixin): - __tablename__ = "authorization_matrix" - user_id = Column(String, ForeignKey("user.id"), nullable=False) - user = relationship("User", back_populates="matrix") - role_id = Column(String, ForeignKey("role.id"), nullable=False) - role = relationship("Role", back_populates="matrix") +class Assignment(Base, BaseMixin): + __tablename__ = "assignment" + profile_id = Column(String, ForeignKey("profile.id"), nullable=False) + profile = relationship("Profile", back_populates="assignments") + permission_id = Column(String, ForeignKey("permission.id"), nullable=False) + permission = relationship("Permission", back_populates="assignments") class ModuleData(Base, BaseMixin): diff --git a/kontor-scripts/json_to_mariadb.py b/kontor-scripts/json_to_mariadb.py index e1c855f..db3916b 100644 --- a/kontor-scripts/json_to_mariadb.py +++ b/kontor-scripts/json_to_mariadb.py @@ -1,5 +1,5 @@ """ -copy data from SQLite to MariaDB +copy data from JSON to MariaDB """ from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter from pathlib import Path diff --git a/kontor-scripts/schema/admin.py b/kontor-scripts/schema/admin.py index c5b3e99..f3f6044 100644 --- a/kontor-scripts/schema/admin.py +++ b/kontor-scripts/schema/admin.py @@ -7,15 +7,15 @@ from sqlalchemy.orm import relationship, mapped_column, Mapped from .base import Base, BaseMixin -class User(Base, BaseMixin): - __tablename__ = 'user' +class Profile(Base, BaseMixin): + __tablename__ = 'profile' first_name = Column(String(255)) last_name = Column(String(255)) user_name = Column(String(255), nullable=False) email = Column(String(255)) password = Column(String(255)) enabled = Column(BIT(1)) - matrix = relationship("AuthorizationMatrix") + assignments = relationship("Assignment") tokens = relationship("Token") def get_full_name(self) -> str: @@ -35,22 +35,22 @@ class Token(Base, BaseMixin): name = Column(String(255)) last_used_date: Mapped[datetime] = mapped_column() enabled = Column(BIT(1)) - user_id = Column(String(255), ForeignKey("user.id"), nullable=False) - user = relationship("User", back_populates="tokens") + profile_id = Column(String(255), ForeignKey("profile.id"), nullable=False) + profile = relationship("Profile", back_populates="tokens") -class Role(Base, BaseMixin): - __tablename__ = "role" +class Permission(Base, BaseMixin): + __tablename__ = "permission" name = Column(String(255), nullable=False) - matrix = relationship("AuthorizationMatrix") + assignments = relationship("Assignment") -class AuthorizationMatrix(Base, BaseMixin): - __tablename__ = "authorization_matrix" - user_id = Column(String, ForeignKey("user.id"), nullable=False) - user = relationship("User", back_populates="matrix") - role_id = Column(String, ForeignKey("role.id"), nullable=False) - role = relationship("Role", back_populates="matrix") +class Assignment(Base, BaseMixin): + __tablename__ = "assignment" + profile_id = Column(String, ForeignKey("profile.id"), nullable=False) + profile = relationship("Profile", back_populates="assignments") + permission_id = Column(String, ForeignKey("permission.id"), nullable=False) + permission = relationship("Permission", back_populates="assignments") class ModuleData(Base, BaseMixin): diff --git a/kontor-scripts/schema/database.py b/kontor-scripts/schema/database.py index 87f9669..3e7db0f 100644 --- a/kontor-scripts/schema/database.py +++ b/kontor-scripts/schema/database.py @@ -13,7 +13,7 @@ from sqlalchemy.orm import sessionmaker from .tysc import Card, CardSet, Rooster, Team, FieldPosition, Player, Vendor, Sport from .comic import Issue, TradePaperback, StoryArc, Volume, ComicWork, Artist, Comic, Publisher, WorkType from .bookshelf import ArticleAuthor, BookAuthor, BookshelfPublisher, Article, Book, Author -from .admin import Mail, MailAccount, ModuleData, Role, User, Token, AuthorizationMatrix +from .admin import Mail, MailAccount, ModuleData, Permission, Profile, Token, Assignment from .metadata import MetaDataTable, MetaDataColumn from .media import MediaVideo, MediaArticle, MediaFile, MediaActor, MediaActorFile @@ -81,10 +81,10 @@ class KontorDB: self.registry[MediaVideo.__tablename__] = MediaVideo self.registry[MetaDataColumn.__tablename__] = MetaDataColumn self.registry[MetaDataTable.__tablename__] = MetaDataTable - self.registry[AuthorizationMatrix.__tablename__] = AuthorizationMatrix + self.registry[Assignment.__tablename__] = Assignment self.registry[Token.__tablename__] = Token - self.registry[User.__tablename__] = User - self.registry[Role.__tablename__] = Role + self.registry[Profile.__tablename__] = Profile + self.registry[Permission.__tablename__] = Permission self.registry[ModuleData.__tablename__] = ModuleData self.registry[MailAccount.__tablename__] = MailAccount self.registry[Mail.__tablename__] = Mail diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/AdminConstants.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/AdminConstants.java index ce0e33b..a3ef2ff 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/AdminConstants.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/AdminConstants.java @@ -18,36 +18,36 @@ public class AdminConstants { public static final String ADMIN_TITLE = "Verwaltung"; public static final String AUTHORIZATION = "Berechtigungen"; - public static final String AUTHORIZATION_ROUTE = "/admin/authorization"; + public static final String ASSIGNMENT_ROUTE = "/admin/assignment"; public static final String DATA = "Daten"; public static final String METADATA_ROUTE = "admin/metadata"; - public static final String ROLE = "Rollen"; - public static final String ROLE_ROUTE = "/admin/role"; - public static final String USER = "Benutzer"; - public static final String USER_ROUTE = "/admin/user"; + public static final String PERMISSION = "Berechtigungen"; + public static final String PERMISSION_ROUTE = "/admin/permission"; + public static final String PROFILE = "Benutzer"; + public static final String PROFILE_ROUTE = "/admin/profile"; public static final String ADMIN = "admin"; public static final String ADMIN_ROUTE = "/admin"; - public static RouterLink getUserNavigation() { - return new RouterLink(USER, UserView.class); + public static RouterLink getProfileNavigation() { + return new RouterLink(PROFILE, ProfileView.class); } - public static RouterLink getRoleNavigation() { - return new RouterLink(ROLE, RoleView.class); + public static RouterLink getPermissionNavigation() { + return new RouterLink(PERMISSION, PermissionView.class); } public static RouterLink getAuthorizationNavigation() { - return new RouterLink(AUTHORIZATION, AuthorizationView.class); + return new RouterLink(AUTHORIZATION, AssignmentView.class); } public static SideNavItem getAdminNavigation() { - SideNavItem administration = new SideNavItem(ADMIN_TITLE, USER_ROUTE, VaadinIcon.GROUP.create()); - administration.addItem(new SideNavItem(USER, USER_ROUTE, VaadinIcon.USERS.create())); - administration.addItem(new SideNavItem(ROLE, RoleView.class)); - SideNavItem data = new SideNavItem(DATA, AUTHORIZATION_ROUTE, VaadinIcon.DATABASE.create()); + SideNavItem administration = new SideNavItem(ADMIN_TITLE, PROFILE_ROUTE, VaadinIcon.GROUP.create()); + administration.addItem(new SideNavItem(PROFILE, PROFILE_ROUTE, VaadinIcon.USERS.create())); + administration.addItem(new SideNavItem(PERMISSION, PermissionView.class)); + SideNavItem data = new SideNavItem(DATA, ASSIGNMENT_ROUTE, VaadinIcon.DATABASE.create()); data.addItem(new SideNavItem(ComicConstants.COMICWORK, ComicWorkView.class)); data.addItem(new SideNavItem(MediaConstants.MEDIAACTORFILE, MediaActorFileView.class)); - data.addItem(new SideNavItem(AUTHORIZATION, AuthorizationView.class)); + data.addItem(new SideNavItem(AUTHORIZATION, AssignmentView.class)); data.addItem(new SideNavItem("Data Import", ModuleDataView.class)); data.addItem(new SideNavItem("Meta Data", MetaDataView.class)); administration.addItem(data); diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/SetupModuleAdmin.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/SetupModuleAdmin.java index 1577e7a..44e28de 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/SetupModuleAdmin.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/SetupModuleAdmin.java @@ -1,9 +1,7 @@ package de.thpeetz.kontor.admin; import de.thpeetz.kontor.admin.data.*; -import de.thpeetz.kontor.admin.repository.AuthorizationMatrixRepository; -import de.thpeetz.kontor.admin.repository.MailAccountRepository; -import de.thpeetz.kontor.admin.repository.UserRepository; +import de.thpeetz.kontor.admin.repository.*; import de.thpeetz.kontor.admin.services.AdminService; import de.thpeetz.kontor.admin.services.MetaDataService; import de.thpeetz.kontor.mailclient.data.MailAccount; @@ -23,10 +21,10 @@ public class SetupModuleAdmin implements ApplicationListener users = userRepository.findAll(); - if (users.isEmpty()) { - User adminUser = initAdminUser(); - initMatrix(adminRole, adminUser); - initMatrix(userRole, adminUser); + Permission adminPermission = adminService.addPermission("ROLE_ADMIN"); + Permission userPermission = adminService.addPermission("ROLE_USER"); + List profiles = profileRepository.findAll(); + if (profiles.isEmpty()) { + Profile adminProfile = initAdminUser(); + initAssignments(adminPermission, adminProfile); + initAssignments(userPermission, adminProfile); } log.info("MailProperties: {}", mailProperties); initMail(mailProperties); @@ -98,32 +96,32 @@ public class SetupModuleAdmin implements ApplicationListener configuredRoles = authorizationMatrixRepository.findByUser(user); - if (configuredRoles.stream().anyMatch(matrix -> matrix.getRole().getId().equals(role.getId()))) { - log.info("Role {} already defined", role.getName()); + private void initAssignments(Permission permission, Profile profile) { + log.info("initAssignments: Permission {} for Profile {}", permission.getName(), profile.getUserName()); + Collection configuredRoles = assignmentRepository.findByProfile(profile); + if (configuredRoles.stream().anyMatch(assignment -> assignment.getPermission().getId().equals(permission.getId()))) { + log.info("Permission {} already defined", permission.getName()); } else { - log.info("add Role {} to User {}", role.getName(), user.getUserName()); - final AuthorizationMatrix adminMatrix = new AuthorizationMatrix(); - adminMatrix.setUser(user); - adminMatrix.setRole(role); - authorizationMatrixRepository.save(adminMatrix); + log.info("add Permission {} to Profile {}", permission.getName(), profile.getUserName()); + final Assignment assignment = new Assignment(); + assignment.setProfile(profile); + assignment.setPermission(permission); + assignmentRepository.save(assignment); } } - private User initAdminUser() { + private Profile initAdminUser() { log.info("initAdminUser"); - User admin = userRepository.findByUserName("admin"); + Profile admin = profileRepository.findByUserName("admin"); if (admin == null) { - log.info("User admin not found, will be created."); - admin = new User(); + log.info("Profile admin not found, will be created."); + admin = new Profile(); admin.setFirstName("Admin"); admin.setLastName("Administrator"); admin.setUserName("admin"); admin.setEmail("admin@example.org"); admin.setPassword(passwordEncoder.encode("admin")); - userRepository.save(admin); + profileRepository.save(admin); } return admin; } @@ -348,17 +346,17 @@ public class SetupModuleAdmin implements ApplicationListener matrix; + private List assignments; } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/User.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/Profile.java similarity index 55% rename from kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/User.java rename to kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/Profile.java index ec16233..8773fb5 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/User.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/Profile.java @@ -1,12 +1,7 @@ package de.thpeetz.kontor.admin.data; import de.thpeetz.kontor.common.data.AbstractEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.Index; -import jakarta.persistence.OneToMany; -import jakarta.persistence.Table; -import jakarta.persistence.UniqueConstraint; +import jakarta.persistence.*; import jakarta.validation.constraints.NotEmpty; import lombok.Getter; import lombok.Setter; @@ -23,7 +18,7 @@ import java.util.List; @ToString @Entity @Table(indexes = @Index(columnList = "userName"), uniqueConstraints = @UniqueConstraint(columnNames = {"userName"})) -public class User extends AbstractEntity { +public class Profile extends AbstractEntity { private String firstName; @@ -38,25 +33,25 @@ public class User extends AbstractEntity { private boolean enabled; - @OneToMany(fetch = FetchType.EAGER, mappedBy = "user") + @OneToMany(fetch = FetchType.EAGER, mappedBy = "profile") @Nullable - private List matrix = new LinkedList<>(); + private List assignments = new LinkedList<>(); - @OneToMany(fetch = FetchType.EAGER, mappedBy = "user") + @OneToMany(fetch = FetchType.EAGER, mappedBy = "profile") @Nullable private List tokens = new LinkedList<>(); public String getFullName() { - StringBuilder fullNamBuilder = new StringBuilder(); + StringBuilder fullNameBuilder = new StringBuilder(); if (firstName != null) { - fullNamBuilder.append(firstName); + fullNameBuilder.append(firstName); } if (lastName != null) { - if (fullNamBuilder.length() > 0) { - fullNamBuilder.append(" "); + if (!fullNameBuilder.isEmpty()) { + fullNameBuilder.append(" "); } - fullNamBuilder.append(lastName); + fullNameBuilder.append(lastName); } - return fullNamBuilder.toString(); + return fullNameBuilder.toString(); } } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/Token.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/Token.java index 4e2dfed..afd4167 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/Token.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/Token.java @@ -31,7 +31,7 @@ public class Token extends AbstractEntity { private boolean enabled; @ManyToOne - @JoinColumn(name="user_id") + @JoinColumn(name="profile_id") @NotNull - private User user; + private Profile profile; } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/AssignmentRepository.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/AssignmentRepository.java new file mode 100644 index 0000000..eb20059 --- /dev/null +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/AssignmentRepository.java @@ -0,0 +1,13 @@ +package de.thpeetz.kontor.admin.repository; + +import de.thpeetz.kontor.admin.data.*; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface AssignmentRepository extends JpaRepository { + + List findByProfile(Profile profile); + + List findByPermission(Permission permission); +} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/AuthorizationMatrixRepository.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/AuthorizationMatrixRepository.java deleted file mode 100644 index 3e5c30c..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/AuthorizationMatrixRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.thpeetz.kontor.admin.repository; - -import java.util.List; - -import de.thpeetz.kontor.admin.data.AuthorizationMatrix; -import de.thpeetz.kontor.admin.data.Role; -import de.thpeetz.kontor.admin.data.User; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface AuthorizationMatrixRepository extends JpaRepository { - - List findByUser(User user); - - List findByRole(Role role); -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/PermissionRepository.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/PermissionRepository.java new file mode 100644 index 0000000..9e6e863 --- /dev/null +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/PermissionRepository.java @@ -0,0 +1,19 @@ +package de.thpeetz.kontor.admin.repository; + +import de.thpeetz.kontor.admin.data.Permission; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface PermissionRepository extends JpaRepository { + + @Query("select p from Permission p " + + "where lower(p.name) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + @Query("select p from Permission p " + + "where lower(p.name) like lower(:name) ") + Permission findByName(@Param("name") String name); +} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/ProfileRepository.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/ProfileRepository.java new file mode 100644 index 0000000..6edf48c --- /dev/null +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/ProfileRepository.java @@ -0,0 +1,18 @@ +package de.thpeetz.kontor.admin.repository; + +import de.thpeetz.kontor.admin.data.Profile; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.UUID; + +public interface ProfileRepository extends JpaRepository { + + @Query("select p from Profile p " + + "where lower(p.lastName) like lower(concat('%', :searchTerm, '%')) ") + List search(@Param("searchTerm") String searchTerm); + + Profile findByUserName(String userName); +} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/RoleRepository.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/RoleRepository.java deleted file mode 100644 index 0d1b466..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/RoleRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.thpeetz.kontor.admin.repository; - -import java.util.List; - -import de.thpeetz.kontor.admin.data.Role; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -public interface RoleRepository extends JpaRepository { - - @Query("select r from Role r " + - "where lower(r.name) like lower(concat('%', :searchTerm, '%')) ") - List search(@Param("searchTerm") String searchTerm); - - @Query("select r from Role r " + - "where lower(r.name) like lower(:name) ") - Role findByName(@Param("name") String name); -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/UserRepository.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/UserRepository.java deleted file mode 100644 index c8c20f3..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/UserRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package de.thpeetz.kontor.admin.repository; - -import java.util.List; - -import de.thpeetz.kontor.admin.data.User; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -public interface UserRepository extends JpaRepository { - - @Query("select u from User u " + - "where lower(u.lastName) like lower(concat('%', :searchTerm, '%')) ") - List search(@Param("searchTerm") String searchTerm); - - User findByUserName(String userName); -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/AdminService.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/AdminService.java index c7c854c..0bffa05 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/AdminService.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/AdminService.java @@ -3,108 +3,105 @@ package de.thpeetz.kontor.admin.services; import java.util.Collection; import java.util.List; +import de.thpeetz.kontor.admin.data.*; +import de.thpeetz.kontor.admin.repository.*; import org.springframework.stereotype.Service; -import de.thpeetz.kontor.admin.data.AuthorizationMatrix; -import de.thpeetz.kontor.admin.repository.AuthorizationMatrixRepository; -import de.thpeetz.kontor.admin.data.Role; -import de.thpeetz.kontor.admin.repository.RoleRepository; -import de.thpeetz.kontor.admin.data.User; -import de.thpeetz.kontor.admin.repository.UserRepository; import lombok.extern.slf4j.Slf4j; @Slf4j @Service public class AdminService { - private final UserRepository userRepository; - private final RoleRepository roleRepository; - private final AuthorizationMatrixRepository authorizationMatrixRepository; - public AdminService(UserRepository userRepository, RoleRepository roleRepository, - AuthorizationMatrixRepository authorizationMatrixRepository) { - this.userRepository = userRepository; - this.roleRepository = roleRepository; - this.authorizationMatrixRepository = authorizationMatrixRepository; + private final ProfileRepository profileRepository; + private final PermissionRepository permissionRepository; + private final AssignmentRepository assignmentRepository; + + public AdminService(ProfileRepository profileRepository, + PermissionRepository permissionRepository, + AssignmentRepository assignmentRepository) { + this.profileRepository = profileRepository; + this.permissionRepository = permissionRepository; + this.assignmentRepository = assignmentRepository; } - public List findAllUsers() { - return userRepository.findAll(); + public List findAllProfiles() { return profileRepository.findAll(); } + + public Profile getProfile(String userName) { + log.debug("get Profile {}", userName); + return profileRepository.findByUserName(userName); } - public List findAllRoles() { - return roleRepository.findAll(); - } + public List findAllPermissions() { return permissionRepository.findAll(); } - public Collection findAllRoles(String stringFilter) { + public Collection findAllPermissions(String stringFilter) { if (stringFilter == null || stringFilter.isEmpty()) { - return roleRepository.findAll(); + return permissionRepository.findAll(); } else { - return roleRepository.search(stringFilter); + return permissionRepository.search(stringFilter); } } - public Role addRole(String roleName) { - Role role = roleRepository.findByName(roleName); - if (role == null) { - log.info("Role {} was not found, will create it.", roleName); - role = new Role(); - role.setName(roleName); - roleRepository.save(role); + public Permission addPermission(String permissionName) { + Permission permission = permissionRepository.findByName(permissionName); + if (permission == null) { + log.info("Permission {} was not found, will create it.", permissionName); + permission = new Permission(); + permission.setName(permissionName); + permissionRepository.save(permission); } - return role; + return permission; } - public void saveRole(Role role) { - if (role == null) { - log.warn("Role is null. Can't save it."); + public void savePermission(Permission permission) { + if (permission == null) { + log.warn("Permission is null. Can't save it."); } - log.info("saveRole: role={}", role); - roleRepository.save(role); + log.info("savePermission: permission={}", permission); + permissionRepository.save(permission); } - public void deleteRole(Role role) { - if (role == null) { - log.warn("Role is null. Can't delete it."); + public void deletePermission(Permission permission) { + if (permission == null) { + log.warn("Permission is null. Can't delete it."); + return; } - log.info("deleteRole: role={}", role); - roleRepository.delete(role); + log.info("deletePermission: permission={}", permission); + permissionRepository.delete(permission); } - public List findAllAuthorizationMatrices() { - return authorizationMatrixRepository.findAll(); + public List findAllAssignments() { + return assignmentRepository.findAll(); } - public void saveAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) { - if (authorizationMatrix == null) { - log.warn("AuthorizationMatrix is null. Can't save it."); + public void saveAssignment(Assignment assignment) { + if (assignment == null) { + log.warn("Assignment is null. Can't save it."); + return; } - log.info("saveAuthorizationMatrix: authorizationMatrix={}", authorizationMatrix); - authorizationMatrixRepository.save(authorizationMatrix); + log.info("saveAssignment: assignment={}", assignment); + assignmentRepository.save(assignment); } - public void deleteAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) { - if (authorizationMatrix == null) { - log.warn("AuthorizationMatrix is null. Can't delete it."); + public void deleteAssignment(Assignment assignment) { + if (assignment == null) { + log.warn("Assignment is null. Can't delete it."); + return; } - log.info("deleteAuthorizationMatrix: authorizationMatrix={}", authorizationMatrix); - authorizationMatrixRepository.delete(authorizationMatrix); + log.info("deleteAssignment: assignment={}", assignment); + assignmentRepository.delete(assignment); } - public String getUserFullName(String userName) { - log.debug("get Fullname für user {}", userName); - User user = userRepository.findByUserName(userName); - if (user == null) { + public String getProfileFullName(String userName) { + log.debug("get Fullname für Profile {}", userName); + Profile profile = profileRepository.findByUserName(userName); + if (profile == null) { log.info("keinen Eintrag für {} gefunden", userName); return userName; } else { - log.info("Voller Name des User {}: {}", userName, user.getFullName()); - return user.getFullName(); + log.info("Voller Name des Profile {}: {}", userName, profile.getFullName()); + return profile.getFullName(); } } - - public User getUser(String userName) { - log.debug("get User {}", userName); - return userRepository.findByUserName(userName); - } } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/KontorUserDetailsService.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/KontorUserDetailsService.java index 6a1eead..52fc79a 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/KontorUserDetailsService.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/KontorUserDetailsService.java @@ -1,9 +1,7 @@ package de.thpeetz.kontor.admin.services; import de.thpeetz.kontor.admin.data.*; -import de.thpeetz.kontor.admin.repository.AuthorizationMatrixRepository; -import de.thpeetz.kontor.admin.repository.RoleRepository; -import de.thpeetz.kontor.admin.repository.UserRepository; +import de.thpeetz.kontor.admin.repository.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; @@ -26,83 +24,86 @@ public class KontorUserDetailsService implements UserDetailsService { private static SecureRandom random = new SecureRandom(); @Autowired - private UserRepository userRepository; + private ProfileRepository profileRepository; @Autowired - private RoleRepository roleRepository; + private PermissionRepository permissionRepository; @Autowired - private AuthorizationMatrixRepository authorizationMatrixRepository; + private AssignmentRepository assignmentRepository; - public Collection findAllUsers(String stringFilter) { + public Collection findAllProfiles(String stringFilter) { if (stringFilter == null || stringFilter.isEmpty()) { - return userRepository.findAll(); + return profileRepository.findAll(); } else { - return userRepository.search(stringFilter); + return profileRepository.search(stringFilter); } } - public void saveUser(User user) { - if (user == null) { - log.warn("User is null. Can't save it."); + public void saveProfile(Profile profile) { + if (profile == null) { + log.warn("Profile is null. Can't save it."); + return; } - log.info("saveUser: user={}", user); - userRepository.save(user); + log.info("saveProfile: profile={}", profile); + profileRepository.save(profile); } - public void saveUser(User user, List roles) { - if (user == null) { - log.warn("User is null. Can't save it."); + public void saveProfile(Profile profile, List permissions) { + if (profile == null) { + log.warn("Profile is null. Can't save it."); + return; } - log.info("First save user: {}", user); - user = userRepository.save(user); - List copy = roles.stream().collect(Collectors.toList()); - List permissions = user.getMatrix(); - permissions.forEach(matrix -> { - if (roles.contains(matrix.getRole())) { - log.info("Role {} already assigned", matrix.getRole()); - copy.remove(matrix.getRole()); + log.info("First save Profile: {}", profile); + profile = profileRepository.save(profile); + List copy = permissions.stream().collect(Collectors.toList()); + List assignments = profile.getAssignments(); + assignments.forEach(assignment -> { + if (permissions.contains(assignment.getPermission())) { + log.info("Permission {} already assigned", assignment.getPermission()); + copy.remove(assignment.getPermission()); } else { - log.info("Role {} has to be removed", matrix.getRole()); - authorizationMatrixRepository.delete(matrix); + log.info("Permission {} has to be removed", assignment.getPermission()); + assignmentRepository.delete(assignment); } }); log.info("remaining roles: {}", copy); - for (Role role : copy) { - AuthorizationMatrix matrix = new AuthorizationMatrix(); - matrix.setUser(user); - matrix.setRole(role); - authorizationMatrixRepository.save(matrix); + for (Permission permission : copy) { + Assignment assignment = new Assignment(); + assignment.setProfile(profile); + assignment.setPermission(permission); + assignmentRepository.save(assignment); } } - public void deleteUser(User user) { - if (user == null) { - log.warn("User is null. Can't delete it."); + public void deleteProfile(Profile profile) { + if (profile == null) { + log.warn("Profile is null. Can't delete it."); + return; } - log.info("deleteUser: user={}", user); - userRepository.delete(user); + log.info("deleteProfile: profile={}", profile); + profileRepository.delete(profile); } @Override public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { log.info("loadUserByUsername: userName={}", userName); - User user = userRepository.findByUserName(userName); - if (user == null) { + Profile profile = profileRepository.findByUserName(userName); + if (profile == null) { log.info("User not found"); return null; } - Collection authorities = getAuthorities(user); - log.info("User {} hat Rolen: {}", userName, authorities); - return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getPassword(), + Collection authorities = getAuthorities(profile); + log.info("Profile {} hat Permissions: {}", userName, authorities); + return new org.springframework.security.core.userdetails.User(profile.getUserName(), profile.getPassword(), authorities); } - private Collection getAuthorities(User user) { - return authorizationMatrixRepository.findByUser(user).stream() - .map(matrix -> matrix.getRole().getName()) + private Collection getAuthorities(Profile profile) { + return assignmentRepository.findByProfile(profile).stream() + .map(assignment -> assignment.getPermission().getName()) .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); } @@ -122,7 +123,7 @@ public class KontorUserDetailsService implements UserDetailsService { log.info("removeRememberedUser: id={}", id); } - public List findAllRoles() { - return roleRepository.findAll(); + public List findAllPermissions() { + return permissionRepository.findAll(); } } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AdminLayout.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AdminLayout.java index 5ed32c5..fa6dbe7 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AdminLayout.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AdminLayout.java @@ -29,7 +29,7 @@ public class AdminLayout extends AppLayout { private HorizontalLayout getSecondaryNavigation() { HorizontalLayout navigation = new HorizontalLayout(); navigation.addClassNames(LumoUtility.JustifyContent.CENTER, LumoUtility.Gap.SMALL, LumoUtility.Height.MEDIUM); - navigation.add(AdminConstants.getUserNavigation(), AdminConstants.getRoleNavigation(), + navigation.add(AdminConstants.getProfileNavigation(), AdminConstants.getPermissionNavigation(), AdminConstants.getAuthorizationNavigation()); return navigation; } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationForm.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AssignmentForm.java similarity index 55% rename from kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationForm.java rename to kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AssignmentForm.java index da593f8..3dcd115 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationForm.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AssignmentForm.java @@ -13,32 +13,32 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.data.binder.BeanValidationBinder; import com.vaadin.flow.data.binder.Binder; -import de.thpeetz.kontor.admin.data.AuthorizationMatrix; -import de.thpeetz.kontor.admin.data.Role; -import de.thpeetz.kontor.admin.data.User; +import de.thpeetz.kontor.admin.data.Assignment; +import de.thpeetz.kontor.admin.data.Permission; +import de.thpeetz.kontor.admin.data.Profile; import lombok.extern.slf4j.Slf4j; @Slf4j -public class AuthorizationForm extends FormLayout { +public class AssignmentForm extends FormLayout { - ComboBox user = new ComboBox<>("User"); - ComboBox role = new ComboBox<>("Role"); + ComboBox profile = new ComboBox<>("Proile"); + ComboBox permission = new ComboBox<>("Permission"); Button save = new Button("Save"); Button delete = new Button("Delete"); Button close = new Button("Cancel"); - Binder binder = new BeanValidationBinder<>(AuthorizationMatrix.class); + Binder binder = new BeanValidationBinder<>(Assignment.class); - public AuthorizationForm(List users, List roles) { - addClassName("authorizationmatrix-form"); + public AssignmentForm(List profiles, List permissions) { + addClassName("assignment-form"); binder.bindInstanceFields(this); - user.setItems(users); - user.setItemLabelGenerator(User::getUserName); - role.setItems(roles); - role.setItemLabelGenerator(Role::getName); - add(user, role, createButtonsLayout()); + profile.setItems(profiles); + profile.setItemLabelGenerator(Profile::getUserName); + permission.setItems(permissions); + permission.setItemLabelGenerator(Permission::getName); + add(profile, permission, createButtonsLayout()); } private HorizontalLayout createButtonsLayout() { @@ -63,37 +63,37 @@ public class AuthorizationForm extends FormLayout { } } - public void setAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) { - binder.setBean(authorizationMatrix); + public void setAssignment(Assignment assignment) { + binder.setBean(assignment); } - public abstract static class AuthorizationFormEvent extends ComponentEvent { - private AuthorizationMatrix authorizationMatrix; + public abstract static class AssignmentFormEvent extends ComponentEvent { + private Assignment assignment; - protected AuthorizationFormEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) { + protected AssignmentFormEvent(AssignmentForm source, Assignment assignment) { super(source, false); - this.authorizationMatrix = authorizationMatrix; + this.assignment = assignment; } - public AuthorizationMatrix getAuthorizationMatrix() { - return authorizationMatrix; + public Assignment getAssignment() { + return assignment; } } - public static class SaveEvent extends AuthorizationFormEvent { - SaveEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) { - super(source, authorizationMatrix); + public static class SaveEvent extends AssignmentFormEvent { + SaveEvent(AssignmentForm source, Assignment assignment) { + super(source, assignment); } } - public static class DeleteEvent extends AuthorizationFormEvent { - DeleteEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) { - super(source, authorizationMatrix); + public static class DeleteEvent extends AssignmentFormEvent { + DeleteEvent(AssignmentForm source, Assignment assignment) { + super(source, assignment); } } - public static class CloseEvent extends AuthorizationFormEvent { - CloseEvent(AuthorizationForm source) { + public static class CloseEvent extends AssignmentFormEvent { + CloseEvent(AssignmentForm source) { super(source, null); } } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationView.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AssignmentView.java similarity index 59% rename from kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationView.java rename to kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AssignmentView.java index 435ae8f..bc4e547 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationView.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AssignmentView.java @@ -1,5 +1,6 @@ package de.thpeetz.kontor.admin.views; +import de.thpeetz.kontor.admin.data.Assignment; import org.springframework.context.annotation.Scope; import com.vaadin.flow.component.Component; @@ -13,7 +14,6 @@ import com.vaadin.flow.router.Route; import com.vaadin.flow.spring.annotation.SpringComponent; import de.thpeetz.kontor.admin.AdminConstants; -import de.thpeetz.kontor.admin.data.AuthorizationMatrix; import de.thpeetz.kontor.admin.services.AdminService; import de.thpeetz.kontor.common.views.MainLayout; import jakarta.annotation.security.RolesAllowed; @@ -23,17 +23,17 @@ import lombok.extern.slf4j.Slf4j; @SpringComponent @Scope("prototype") @RolesAllowed("ROLE_ADMIN") -@Route(value = AdminConstants.AUTHORIZATION_ROUTE, layout = MainLayout.class) +@Route(value = AdminConstants.ASSIGNMENT_ROUTE, layout = MainLayout.class) @PageTitle("Authorization | Admin | Kontor") -public class AuthorizationView extends VerticalLayout { +public class AssignmentView extends VerticalLayout { - Grid grid = new Grid<>(AuthorizationMatrix.class); - AuthorizationForm form; + Grid grid = new Grid<>(Assignment.class); + AssignmentForm form; AdminService service; - public AuthorizationView(AdminService service) { + public AssignmentView(AdminService service) { this.service = service; - addClassName("authoriaztionmatrix-view"); + addClassName("assignment-view"); setSizeFull(); configureGrid(); configureForm(); @@ -43,30 +43,30 @@ public class AuthorizationView extends VerticalLayout { } private void configureGrid() { - grid.addClassName("authorizationmatrix-grid"); + grid.addClassName("assignment-grid"); grid.setSizeFull(); - grid.setColumns("user.userName", "role.name"); + grid.setColumns("profile.userName", "permission.name"); grid.getColumns().forEach(col -> col.setAutoWidth(true)); - grid.asSingleSelect().addValueChangeListener(event -> editAuthorizationMatrix(event.getValue())); + grid.asSingleSelect().addValueChangeListener(event -> editAssignment(event.getValue())); } private void configureForm() { - form = new AuthorizationForm(service.findAllUsers(), service.findAllRoles()); + form = new AssignmentForm(service.findAllProfiles(), service.findAllPermissions()); form.setWidth("25em"); - form.addSaveListener(this::saveAuthorizationMatrix); - form.addDeleteListener(this::deleteAuthorizationMatrix); + form.addSaveListener(this::saveAssignment); + form.addDeleteListener(this::deleteAssignment); form.addCloseListener(e -> closeEditor()); } - private void saveAuthorizationMatrix(AuthorizationForm.SaveEvent event) { - AuthorizationMatrix authorizationMatrix = event.getAuthorizationMatrix(); - service.saveAuthorizationMatrix(authorizationMatrix); + private void saveAssignment(AssignmentForm.SaveEvent event) { + Assignment assignment = event.getAssignment(); + service.saveAssignment(assignment); updateList(); closeEditor(); } - private void deleteAuthorizationMatrix(AuthorizationForm.DeleteEvent event) { - service.deleteAuthorizationMatrix(event.getAuthorizationMatrix()); + private void deleteAssignment(AssignmentForm.DeleteEvent event) { + service.deleteAssignment(event.getAssignment()); updateList(); closeEditor(); } @@ -81,34 +81,34 @@ public class AuthorizationView extends VerticalLayout { } private HorizontalLayout getToolbar() { - Button addAuthorizationMaxtrixButton = new Button("Add permssion", click -> addAuthorizationMatrix()); + Button addAuthorizationMaxtrixButton = new Button("Add permission", click -> addAssignment()); HorizontalLayout toolbar = new HorizontalLayout(addAuthorizationMaxtrixButton); toolbar.addClassName("toolbar"); return toolbar; } - public void editAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) { - if (authorizationMatrix == null) { + public void editAssignment(Assignment assignment) { + if (assignment == null) { closeEditor(); } else { - form.setAuthorizationMatrix(authorizationMatrix); + form.setAssignment(assignment); form.setVisible(true); addClassName("editing"); } } public void closeEditor() { - form.setAuthorizationMatrix(null); + form.setAssignment(null); form.setVisible(false); removeClassName("editing"); } - private void addAuthorizationMatrix() { + private void addAssignment() { grid.asSingleSelect().clear(); - editAuthorizationMatrix(new AuthorizationMatrix()); + editAssignment(new Assignment()); } private void updateList() { - grid.setItems(service.findAllAuthorizationMatrices()); + grid.setItems(service.findAllAssignments()); } } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleForm.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/PermissionForm.java similarity index 66% rename from kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleForm.java rename to kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/PermissionForm.java index 671d0f5..521c992 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleForm.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/PermissionForm.java @@ -10,12 +10,11 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.data.binder.BeanValidationBinder; import com.vaadin.flow.data.binder.Binder; - -import de.thpeetz.kontor.admin.data.Role; +import de.thpeetz.kontor.admin.data.Permission; import lombok.extern.slf4j.Slf4j; @Slf4j -public class RoleForm extends FormLayout { +public class PermissionForm extends FormLayout { TextField name = new TextField("Role name"); @@ -23,10 +22,10 @@ public class RoleForm extends FormLayout { Button delete = new Button("Delete"); Button close = new Button("Cancel"); - Binder binder = new BeanValidationBinder<>(Role.class); + Binder binder = new BeanValidationBinder<>(Permission.class); - public RoleForm() { - addClassName("role-form"); + public PermissionForm() { + addClassName("permission-form"); binder.bindInstanceFields(this); add(name, createButtonsLayout()); } @@ -53,37 +52,37 @@ public class RoleForm extends FormLayout { } } - public void setRole(Role role) { - binder.setBean(role); + public void setPermission(Permission permission) { + binder.setBean(permission); } - public abstract static class RoleFormEvent extends ComponentEvent { - private Role role; + public abstract static class PermissionFormEvent extends ComponentEvent { + private Permission permission; - protected RoleFormEvent(RoleForm source, Role role) { + protected PermissionFormEvent(PermissionForm source, Permission permission) { super(source, false); - this.role = role; + this.permission = permission; } - public Role getRole() { - return role; + public Permission getPermission() { + return permission; } } - public static class SaveEvent extends RoleFormEvent { - SaveEvent(RoleForm source, Role role) { - super(source, role); + public static class SaveEvent extends PermissionFormEvent { + SaveEvent(PermissionForm source, Permission permission) { + super(source, permission); } } - public static class DeleteEvent extends RoleFormEvent { - DeleteEvent(RoleForm source, Role role) { - super(source, role); + public static class DeleteEvent extends PermissionFormEvent { + DeleteEvent(PermissionForm source, Permission permission) { + super(source, permission); } } - public static class CloseEvent extends RoleFormEvent { - CloseEvent(RoleForm source) { + public static class CloseEvent extends PermissionFormEvent { + CloseEvent(PermissionForm source) { super(source, null); } } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleView.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/PermissionView.java similarity index 69% rename from kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleView.java rename to kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/PermissionView.java index 1f13c9a..f23881d 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleView.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/PermissionView.java @@ -1,5 +1,6 @@ package de.thpeetz.kontor.admin.views; +import de.thpeetz.kontor.admin.data.Permission; import org.springframework.context.annotation.Scope; import com.vaadin.flow.component.Component; @@ -14,7 +15,6 @@ import com.vaadin.flow.router.Route; import com.vaadin.flow.spring.annotation.SpringComponent; import de.thpeetz.kontor.admin.AdminConstants; -import de.thpeetz.kontor.admin.data.Role; import de.thpeetz.kontor.admin.services.AdminService; import de.thpeetz.kontor.common.views.MainLayout; import jakarta.annotation.security.RolesAllowed; @@ -24,17 +24,18 @@ import lombok.extern.slf4j.Slf4j; @SpringComponent @Scope("prototype") @RolesAllowed("ROLE_ADMIN") -@Route(value = AdminConstants.ROLE_ROUTE, layout = MainLayout.class) -@PageTitle("Rollen | Admin | Kontor") -public class RoleView extends VerticalLayout { - Grid grid = new Grid<>(Role.class); +@Route(value = AdminConstants.PERMISSION_ROUTE, layout = MainLayout.class) +@PageTitle("Permissions | Admin | Kontor") +public class PermissionView extends VerticalLayout { + + Grid grid = new Grid<>(Permission.class); TextField filterText = new TextField(); - RoleForm form; + PermissionForm form; AdminService service; - public RoleView(AdminService service) { + public PermissionView(AdminService service) { this.service = service; - addClassName("user-view"); + addClassName("permission-view"); setSizeFull(); configureGrid(); configureForm(); @@ -44,29 +45,29 @@ public class RoleView extends VerticalLayout { } private void configureGrid() { - grid.addClassName("user-grid"); + grid.addClassName("permission-grid"); grid.setSizeFull(); grid.setColumns("name"); grid.getColumns().forEach(col -> col.setAutoWidth(true)); - grid.asSingleSelect().addValueChangeListener(event -> editRole(event.getValue())); + grid.asSingleSelect().addValueChangeListener(event -> editPermission(event.getValue())); } private void configureForm() { - form = new RoleForm(); + form = new PermissionForm(); form.setWidth("25em"); - form.addSaveListener(this::saveRole); - form.addDeleteListener(this::deleteRole); + form.addSaveListener(this::savePermission); + form.addDeleteListener(this::deletePermission); form.addCloseListener(e -> closeEditor()); } - private void saveRole(RoleForm.SaveEvent event) { - service.saveRole(event.getRole()); + private void savePermission(PermissionForm.SaveEvent event) { + service.savePermission(event.getPermission()); updateList(); closeEditor(); } - private void deleteRole(RoleForm.DeleteEvent event) { - service.deleteRole(event.getRole()); + private void deletePermission(PermissionForm.DeleteEvent event) { + service.deletePermission(event.getPermission()); updateList(); closeEditor(); } @@ -85,34 +86,34 @@ public class RoleView extends VerticalLayout { filterText.setClearButtonVisible(true); filterText.setValueChangeMode(ValueChangeMode.LAZY); filterText.addValueChangeListener(e -> updateList()); - Button addUserButton = new Button("Add user", click -> addUser()); + Button addUserButton = new Button("Add user", click -> addPermission()); HorizontalLayout toolbar = new HorizontalLayout(filterText, addUserButton); toolbar.addClassName("toolbar"); return toolbar; } - public void editRole(Role role) { - if (role == null) { + public void editPermission(Permission permission) { + if (permission == null) { closeEditor(); } else { - form.setRole(role); + form.setPermission(permission); form.setVisible(true); addClassName("editing"); } } public void closeEditor() { - form.setRole(null); + form.setPermission(null); form.setVisible(false); removeClassName("editing"); } - private void addUser() { + private void addPermission() { grid.asSingleSelect().clear(); - editRole(new Role()); + editPermission(new Permission()); } private void updateList() { - grid.setItems(service.findAllRoles(filterText.getValue())); + grid.setItems(service.findAllPermissions(filterText.getValue())); } } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/ProfileForm.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/ProfileForm.java new file mode 100644 index 0000000..cb3166c --- /dev/null +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/ProfileForm.java @@ -0,0 +1,143 @@ +package de.thpeetz.kontor.admin.views; + +import com.vaadin.flow.component.ComponentEvent; +import com.vaadin.flow.component.ComponentEventListener; +import com.vaadin.flow.component.Key; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.checkbox.Checkbox; +import com.vaadin.flow.component.checkbox.CheckboxGroup; +import com.vaadin.flow.component.checkbox.CheckboxGroupVariant; +import com.vaadin.flow.component.formlayout.FormLayout; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.textfield.EmailField; +import com.vaadin.flow.component.textfield.PasswordField; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.data.binder.BeanValidationBinder; +import com.vaadin.flow.data.binder.Binder; +import de.thpeetz.kontor.admin.data.Permission; +import de.thpeetz.kontor.admin.data.Profile; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +@Slf4j +public class ProfileForm extends FormLayout { + + TextField userName = new TextField("User name"); + PasswordField password = new PasswordField("Password"); + EmailField email = new EmailField("Email"); + TextField firstName = new TextField("First name"); + TextField lastName = new TextField("Last name"); + Checkbox enabled = new Checkbox("Enabled"); + String originalPassword; + + CheckboxGroup permissionList = new CheckboxGroup<>("Permissions"); + + Button save = new Button("Save"); + Button delete = new Button("Delete"); + Button close = new Button("Cancel"); + + Binder binder = new BeanValidationBinder<>(Profile.class); + + public ProfileForm() { + addClassName("profile-form"); + binder.bindInstanceFields(this); + add(userName, password, email, firstName, lastName, enabled, configurePermissionsGroup(), createButtonsLayout()); + } + + private CheckboxGroup configurePermissionsGroup() { + permissionList.addThemeVariants(CheckboxGroupVariant.LUMO_VERTICAL); + permissionList.setItemLabelGenerator(Permission::getName); + permissionList.addValueChangeListener(event -> { + log.debug("permissions changed: {}", event); + }); + return permissionList; + } + + private HorizontalLayout createButtonsLayout() { + save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + delete.addThemeVariants(ButtonVariant.LUMO_ERROR); + close.addThemeVariants(ButtonVariant.LUMO_TERTIARY); + + save.addClickShortcut(Key.ENTER); + close.addClickShortcut(Key.ESCAPE); + + save.addClickListener(event -> validateAndSave()); + delete.addClickListener(event -> fireEvent(new ProfileForm.DeleteEvent(this, binder.getBean()))); + close.addClickListener(event -> fireEvent(new ProfileForm.CloseEvent(this))); + + binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); + return new HorizontalLayout(save, delete, close); + } + + private void validateAndSave() { + if (binder.isValid()) { + fireEvent(new ProfileForm.SaveEvent(this, binder.getBean())); + } + } + + public void setProfile(Profile profile) { + binder.setBean(profile); + //log.debug("UserForm.setUser: {}", user); + if (profile != null) { + this.originalPassword = profile.getPassword(); + } else { + this.originalPassword = null; + } + } + + public void setPermissions(List permissions, Profile profile) { + permissionList.setItems(permissions); + profile.getAssignments().stream().forEach(assignment -> { + permissionList.select(assignment.getPermission()); + }); + } + + public boolean hasPasswordChanged(Profile profile) { + return !originalPassword.equals(profile.getPassword()); + } + + public abstract static class ProfileFormEvent extends ComponentEvent { + private Profile profile; + + protected ProfileFormEvent(ProfileForm source, Profile profile) { + super(source, false); + this.profile = profile; + } + + public Profile getProfile() { + return profile; + } + } + + public static class SaveEvent extends ProfileForm.ProfileFormEvent { + SaveEvent(ProfileForm source, Profile profile) { + super(source, profile); + } + } + + public static class DeleteEvent extends ProfileForm.ProfileFormEvent { + DeleteEvent(ProfileForm source, Profile profile) { + super(source, profile); + } + } + + public static class CloseEvent extends ProfileForm.ProfileFormEvent { + CloseEvent(ProfileForm source) { + super(source, null); + } + } + + public void addDeleteListener(ComponentEventListener listener) { + addListener(ProfileForm.DeleteEvent.class, listener); + } + + public void addSaveListener(ComponentEventListener listener) { + addListener(ProfileForm.SaveEvent.class, listener); + } + + public void addCloseListener(ComponentEventListener listener) { + addListener(ProfileForm.CloseEvent.class, listener); + } +} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserView.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/ProfileView.java similarity index 63% rename from kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserView.java rename to kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/ProfileView.java index 9f981ec..16bc6b0 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserView.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/ProfileView.java @@ -10,8 +10,8 @@ import com.vaadin.flow.data.value.ValueChangeMode; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.spring.annotation.SpringComponent; -import de.thpeetz.kontor.admin.data.Role; -import de.thpeetz.kontor.admin.data.User; +import de.thpeetz.kontor.admin.data.Permission; +import de.thpeetz.kontor.admin.data.Profile; import de.thpeetz.kontor.admin.services.KontorUserDetailsService; import de.thpeetz.kontor.common.views.MainLayout; import jakarta.annotation.security.RolesAllowed; @@ -27,21 +27,21 @@ import java.util.stream.Collectors; @SpringComponent @Scope("prototype") @RolesAllowed("ROLE_ADMIN") -@Route(value = "admin/user", layout = MainLayout.class) -@PageTitle("User | Admin | Kontor") -public class UserView extends VerticalLayout { +@Route(value = "admin/profile", layout = MainLayout.class) +@PageTitle("Profile | Admin | Kontor") +public class ProfileView extends VerticalLayout { - Grid grid = new Grid<>(User.class); + Grid grid = new Grid<>(Profile.class); TextField filterText = new TextField(); - UserForm form; + ProfileForm form; KontorUserDetailsService service; @Autowired PasswordEncoder passwordEncoder; - public UserView(KontorUserDetailsService service) { + public ProfileView(KontorUserDetailsService service) { this.service = service; - addClassName("user-view"); + addClassName("profile-view"); setSizeFull(); configureGrid(); configureForm(); @@ -51,38 +51,38 @@ public class UserView extends VerticalLayout { } private void configureGrid() { - grid.addClassName("user-grid"); + grid.addClassName("profile-grid"); grid.setSizeFull(); grid.setColumns("userName", "email", "firstName", "lastName", "enabled"); grid.getColumns().forEach(col -> col.setAutoWidth(true)); - grid.asSingleSelect().addValueChangeListener(event -> editUser(event.getValue())); + grid.asSingleSelect().addValueChangeListener(event -> editProfile(event.getValue())); } private void configureForm() { - form = new UserForm(); + form = new ProfileForm(); form.setWidth("25em"); form.setVisible(false); - form.addSaveListener(this::saveUser); - form.addDeleteListener(this::deleteUser); + form.addSaveListener(this::saveProfile); + form.addDeleteListener(this::deleteProfile); form.addCloseListener(e -> closeEditor()); } - private void saveUser(UserForm.SaveEvent event) { - User user = event.getUser(); - log.debug("UserView.saveUser: {}", user); - List permissions = form.permissions.getSelectedItems().stream().collect(Collectors.toList()); + private void saveProfile(ProfileForm.SaveEvent event) { + Profile profile = event.getProfile(); + log.debug("ProfileView.saveProfile: {}", profile); + List permissions = form.permissionList.getSelectedItems().stream().collect(Collectors.toList()); log.info("selected permissions: {}", permissions); - if (form.hasPasswordChanged(user)) { - user.setPassword(passwordEncoder.encode(user.getPassword())); - log.debug("password changed for user {}", user); + if (form.hasPasswordChanged(profile)) { + profile.setPassword(passwordEncoder.encode(profile.getPassword())); + log.debug("password changed for profile {}", profile); } - service.saveUser(user, permissions); + service.saveProfile(profile, permissions); updateList(); closeEditor(); } - private void deleteUser(UserForm.DeleteEvent event) { - service.deleteUser(event.getUser()); + private void deleteProfile(ProfileForm.DeleteEvent event) { + service.deleteProfile(event.getProfile()); updateList(); closeEditor(); } @@ -101,35 +101,35 @@ public class UserView extends VerticalLayout { filterText.setClearButtonVisible(true); filterText.setValueChangeMode(ValueChangeMode.LAZY); filterText.addValueChangeListener(e -> updateList()); - Button addUserButton = new Button("Add user", click -> addUser()); - HorizontalLayout toolbar = new HorizontalLayout(filterText, addUserButton); + Button addProfileButton = new Button("Add profile", click -> addProfile()); + HorizontalLayout toolbar = new HorizontalLayout(filterText, addProfileButton); toolbar.addClassName("toolbar"); return toolbar; } - public void editUser(User user) { - if (user == null) { + public void editProfile(Profile profile) { + if (profile == null) { closeEditor(); } else { - form.setUser(user); - form.setRoles(service.findAllRoles(), user); + form.setProfile(profile); + form.setPermissions(service.findAllPermissions(), profile); form.setVisible(true); addClassName("editing"); } } public void closeEditor() { - form.setUser(null); + form.setProfile(null); form.setVisible(false); removeClassName("editing"); } - private void addUser() { + private void addProfile() { grid.asSingleSelect().clear(); - editUser(new User()); + editProfile(new Profile()); } private void updateList() { - grid.setItems(service.findAllUsers(filterText.getValue())); + grid.setItems(service.findAllProfiles(filterText.getValue())); } } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserForm.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserForm.java deleted file mode 100644 index 21298f3..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserForm.java +++ /dev/null @@ -1,143 +0,0 @@ -package de.thpeetz.kontor.admin.views; - -import com.vaadin.flow.component.ComponentEvent; -import com.vaadin.flow.component.ComponentEventListener; -import com.vaadin.flow.component.Key; -import com.vaadin.flow.component.button.Button; -import com.vaadin.flow.component.button.ButtonVariant; -import com.vaadin.flow.component.checkbox.Checkbox; -import com.vaadin.flow.component.checkbox.CheckboxGroup; -import com.vaadin.flow.component.checkbox.CheckboxGroupVariant; -import com.vaadin.flow.component.formlayout.FormLayout; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; -import com.vaadin.flow.component.textfield.EmailField; -import com.vaadin.flow.component.textfield.PasswordField; -import com.vaadin.flow.component.textfield.TextField; -import com.vaadin.flow.data.binder.BeanValidationBinder; -import com.vaadin.flow.data.binder.Binder; -import de.thpeetz.kontor.admin.data.Role; -import de.thpeetz.kontor.admin.data.User; -import lombok.extern.slf4j.Slf4j; - -import java.util.List; - -@Slf4j -public class UserForm extends FormLayout { - - TextField userName = new TextField("User name"); - PasswordField password = new PasswordField("Password"); - EmailField email = new EmailField("Email"); - TextField firstName = new TextField("First name"); - TextField lastName = new TextField("Last name"); - Checkbox enabled = new Checkbox("Enabled"); - String originalPassword; - - CheckboxGroup permissions = new CheckboxGroup<>("Permissions"); - - Button save = new Button("Save"); - Button delete = new Button("Delete"); - Button close = new Button("Cancel"); - - Binder binder = new BeanValidationBinder<>(User.class); - - public UserForm() { - addClassName("user-form"); - binder.bindInstanceFields(this); - add(userName, password, email, firstName, lastName, enabled, configurePermissionsGroup(), createButtonsLayout()); - } - - private CheckboxGroup configurePermissionsGroup() { - permissions.addThemeVariants(CheckboxGroupVariant.LUMO_VERTICAL); - permissions.setItemLabelGenerator(Role::getName); - permissions.addValueChangeListener(event -> { - log.debug("permissions changed: {}", event); - }); - return permissions; - } - - private HorizontalLayout createButtonsLayout() { - save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); - delete.addThemeVariants(ButtonVariant.LUMO_ERROR); - close.addThemeVariants(ButtonVariant.LUMO_TERTIARY); - - save.addClickShortcut(Key.ENTER); - close.addClickShortcut(Key.ESCAPE); - - save.addClickListener(event -> validateAndSave()); - delete.addClickListener(event -> fireEvent(new DeleteEvent(this, binder.getBean()))); - close.addClickListener(event -> fireEvent(new CloseEvent(this))); - - binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); - return new HorizontalLayout(save, delete, close); - } - - private void validateAndSave() { - if (binder.isValid()) { - fireEvent(new SaveEvent(this, binder.getBean())); - } - } - - public void setUser(User user) { - binder.setBean(user); - //log.debug("UserForm.setUser: {}", user); - if (user != null) { - this.originalPassword = user.getPassword(); - } else { - this.originalPassword = null; - } - } - - public void setRoles(List roles, User user) { - permissions.setItems(roles); - user.getMatrix().stream().forEach(authorizationMatrix -> { - permissions.select(authorizationMatrix.getRole()); - }); - } - - public boolean hasPasswordChanged(User user) { - return !originalPassword.equals(user.getPassword()); - } - - public abstract static class UserFormEvent extends ComponentEvent { - private User user; - - protected UserFormEvent(UserForm source, User user) { - super(source, false); - this.user = user; - } - - public User getUser() { - return user; - } - } - - public static class SaveEvent extends UserFormEvent { - SaveEvent(UserForm source, User user) { - super(source, user); - } - } - - public static class DeleteEvent extends UserFormEvent { - DeleteEvent(UserForm source, User user) { - super(source, user); - } - } - - public static class CloseEvent extends UserFormEvent { - CloseEvent(UserForm source) { - super(source, null); - } - } - - public void addDeleteListener(ComponentEventListener listener) { - addListener(DeleteEvent.class, listener); - } - - public void addSaveListener(ComponentEventListener listener) { - addListener(SaveEvent.class, listener); - } - - public void addCloseListener(ComponentEventListener listener) { - addListener(CloseEvent.class, listener); - } -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserProfileView.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserProfileView.java index b2a9ef8..ef00bf2 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserProfileView.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserProfileView.java @@ -10,7 +10,7 @@ import com.vaadin.flow.data.binder.BeanValidationBinder; import com.vaadin.flow.data.binder.Binder; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; -import de.thpeetz.kontor.admin.data.User; +import de.thpeetz.kontor.admin.data.Profile; import de.thpeetz.kontor.admin.services.AdminService; import de.thpeetz.kontor.common.views.MainLayout; import de.thpeetz.kontor.security.SecurityService; @@ -32,7 +32,7 @@ public class UserProfileView extends VerticalLayout { Button save = new Button("Save"); Button close = new Button("Cancel"); - Binder binder = new BeanValidationBinder<>(User.class); + Binder binder = new BeanValidationBinder<>(Profile.class); public UserProfileView(AdminService adminService, SecurityService securityService) { this.adminService = adminService; @@ -42,7 +42,7 @@ public class UserProfileView extends VerticalLayout { add(firstName, lastName, createButtonsLayout()); securityService.getAuthenticatedUser().ifPresent(user -> { log.info("UserProfileView: {}", user.getUsername()); - binder.setBean(adminService.getUser(user.getUsername())); + binder.setBean(adminService.getProfile(user.getUsername())); }); } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/common/views/AvatarMenuBar.java b/kontor-spring/src/main/java/de/thpeetz/kontor/common/views/AvatarMenuBar.java index 1678e58..39459ef 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/common/views/AvatarMenuBar.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/common/views/AvatarMenuBar.java @@ -32,7 +32,7 @@ public class AvatarMenuBar extends Div { log.info("AdminService: {}", adminService); if (user != null) { String userName = user.getUsername(); - String fullName = adminService.getUserFullName(userName); + String fullName = adminService.getProfileFullName(userName); avatar.setName(fullName); } }); diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/media/SetupModuleMedia.java b/kontor-spring/src/main/java/de/thpeetz/kontor/media/SetupModuleMedia.java index c9ce7a1..7c5671c 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/media/SetupModuleMedia.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/media/SetupModuleMedia.java @@ -23,7 +23,7 @@ public class SetupModuleMedia implements ApplicationListener