remove obsolete kontor.py #61

Merged
tpeetz merged 166 commits from develop/0.1.0 into main 2025-04-30 15:31:19 +00:00
29 changed files with 567 additions and 579 deletions
Showing only changes of commit 5850b1cfb0 - Show all commits
+14 -14
View File
@@ -7,15 +7,15 @@ from sqlalchemy.orm import relationship, mapped_column, Mapped
from src.db.models.base import Base, BaseMixin from src.db.models.base import Base, BaseMixin
class User(Base, BaseMixin): class Profile(Base, BaseMixin):
__tablename__ = 'user' __tablename__ = 'profile'
first_name = Column(String(255)) first_name = Column(String(255))
last_name = Column(String(255)) last_name = Column(String(255))
user_name = Column(String(255), nullable=False) user_name = Column(String(255), nullable=False)
email = Column(String(255)) email = Column(String(255))
password = Column(String(255)) password = Column(String(255))
enabled = Column(BIT(1)) enabled = Column(BIT(1))
matrix = relationship("AuthorizationMatrix") assignments = relationship("Assignment")
tokens = relationship("Token") tokens = relationship("Token")
def get_full_name(self) -> str: def get_full_name(self) -> str:
@@ -35,22 +35,22 @@ class Token(Base, BaseMixin):
name = Column(String(255)) name = Column(String(255))
last_used_date: Mapped[datetime] = mapped_column() last_used_date: Mapped[datetime] = mapped_column()
enabled = Column(BIT(1)) enabled = Column(BIT(1))
user_id = Column(String(255), ForeignKey("user.id"), nullable=False) profile_id = Column(String(255), ForeignKey("profile.id"), nullable=False)
user = relationship("User", back_populates="tokens") profile = relationship("Profile", back_populates="tokens")
class Role(Base, BaseMixin): class Permission(Base, BaseMixin):
__tablename__ = "role" __tablename__ = "permission"
name = Column(String(255), nullable=False) name = Column(String(255), nullable=False)
matrix = relationship("AuthorizationMatrix") assignments = relationship("Assignment")
class AuthorizationMatrix(Base, BaseMixin): class Assignment(Base, BaseMixin):
__tablename__ = "authorization_matrix" __tablename__ = "assignment"
user_id = Column(String, ForeignKey("user.id"), nullable=False) profile_id = Column(String, ForeignKey("profile.id"), nullable=False)
user = relationship("User", back_populates="matrix") profile = relationship("Profile", back_populates="assignments")
role_id = Column(String, ForeignKey("role.id"), nullable=False) permission_id = Column(String, ForeignKey("permission.id"), nullable=False)
role = relationship("Role", back_populates="matrix") permission = relationship("Permission", back_populates="assignments")
class ModuleData(Base, BaseMixin): class ModuleData(Base, BaseMixin):
+1 -1
View File
@@ -1,5 +1,5 @@
""" """
copy data from SQLite to MariaDB copy data from JSON to MariaDB
""" """
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
from pathlib import Path from pathlib import Path
+14 -14
View File
@@ -7,15 +7,15 @@ from sqlalchemy.orm import relationship, mapped_column, Mapped
from .base import Base, BaseMixin from .base import Base, BaseMixin
class User(Base, BaseMixin): class Profile(Base, BaseMixin):
__tablename__ = 'user' __tablename__ = 'profile'
first_name = Column(String(255)) first_name = Column(String(255))
last_name = Column(String(255)) last_name = Column(String(255))
user_name = Column(String(255), nullable=False) user_name = Column(String(255), nullable=False)
email = Column(String(255)) email = Column(String(255))
password = Column(String(255)) password = Column(String(255))
enabled = Column(BIT(1)) enabled = Column(BIT(1))
matrix = relationship("AuthorizationMatrix") assignments = relationship("Assignment")
tokens = relationship("Token") tokens = relationship("Token")
def get_full_name(self) -> str: def get_full_name(self) -> str:
@@ -35,22 +35,22 @@ class Token(Base, BaseMixin):
name = Column(String(255)) name = Column(String(255))
last_used_date: Mapped[datetime] = mapped_column() last_used_date: Mapped[datetime] = mapped_column()
enabled = Column(BIT(1)) enabled = Column(BIT(1))
user_id = Column(String(255), ForeignKey("user.id"), nullable=False) profile_id = Column(String(255), ForeignKey("profile.id"), nullable=False)
user = relationship("User", back_populates="tokens") profile = relationship("Profile", back_populates="tokens")
class Role(Base, BaseMixin): class Permission(Base, BaseMixin):
__tablename__ = "role" __tablename__ = "permission"
name = Column(String(255), nullable=False) name = Column(String(255), nullable=False)
matrix = relationship("AuthorizationMatrix") assignments = relationship("Assignment")
class AuthorizationMatrix(Base, BaseMixin): class Assignment(Base, BaseMixin):
__tablename__ = "authorization_matrix" __tablename__ = "assignment"
user_id = Column(String, ForeignKey("user.id"), nullable=False) profile_id = Column(String, ForeignKey("profile.id"), nullable=False)
user = relationship("User", back_populates="matrix") profile = relationship("Profile", back_populates="assignments")
role_id = Column(String, ForeignKey("role.id"), nullable=False) permission_id = Column(String, ForeignKey("permission.id"), nullable=False)
role = relationship("Role", back_populates="matrix") permission = relationship("Permission", back_populates="assignments")
class ModuleData(Base, BaseMixin): class ModuleData(Base, BaseMixin):
+4 -4
View File
@@ -13,7 +13,7 @@ from sqlalchemy.orm import sessionmaker
from .tysc import Card, CardSet, Rooster, Team, FieldPosition, Player, Vendor, Sport from .tysc import Card, CardSet, Rooster, Team, FieldPosition, Player, Vendor, Sport
from .comic import Issue, TradePaperback, StoryArc, Volume, ComicWork, Artist, Comic, Publisher, WorkType from .comic import Issue, TradePaperback, StoryArc, Volume, ComicWork, Artist, Comic, Publisher, WorkType
from .bookshelf import ArticleAuthor, BookAuthor, BookshelfPublisher, Article, Book, Author 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 .metadata import MetaDataTable, MetaDataColumn
from .media import MediaVideo, MediaArticle, MediaFile, MediaActor, MediaActorFile from .media import MediaVideo, MediaArticle, MediaFile, MediaActor, MediaActorFile
@@ -81,10 +81,10 @@ class KontorDB:
self.registry[MediaVideo.__tablename__] = MediaVideo self.registry[MediaVideo.__tablename__] = MediaVideo
self.registry[MetaDataColumn.__tablename__] = MetaDataColumn self.registry[MetaDataColumn.__tablename__] = MetaDataColumn
self.registry[MetaDataTable.__tablename__] = MetaDataTable self.registry[MetaDataTable.__tablename__] = MetaDataTable
self.registry[AuthorizationMatrix.__tablename__] = AuthorizationMatrix self.registry[Assignment.__tablename__] = Assignment
self.registry[Token.__tablename__] = Token self.registry[Token.__tablename__] = Token
self.registry[User.__tablename__] = User self.registry[Profile.__tablename__] = Profile
self.registry[Role.__tablename__] = Role self.registry[Permission.__tablename__] = Permission
self.registry[ModuleData.__tablename__] = ModuleData self.registry[ModuleData.__tablename__] = ModuleData
self.registry[MailAccount.__tablename__] = MailAccount self.registry[MailAccount.__tablename__] = MailAccount
self.registry[Mail.__tablename__] = Mail self.registry[Mail.__tablename__] = Mail
@@ -18,36 +18,36 @@ public class AdminConstants {
public static final String ADMIN_TITLE = "Verwaltung"; public static final String ADMIN_TITLE = "Verwaltung";
public static final String AUTHORIZATION = "Berechtigungen"; 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 DATA = "Daten";
public static final String METADATA_ROUTE = "admin/metadata"; public static final String METADATA_ROUTE = "admin/metadata";
public static final String ROLE = "Rollen"; public static final String PERMISSION = "Berechtigungen";
public static final String ROLE_ROUTE = "/admin/role"; public static final String PERMISSION_ROUTE = "/admin/permission";
public static final String USER = "Benutzer"; public static final String PROFILE = "Benutzer";
public static final String USER_ROUTE = "/admin/user"; public static final String PROFILE_ROUTE = "/admin/profile";
public static final String ADMIN = "admin"; public static final String ADMIN = "admin";
public static final String ADMIN_ROUTE = "/admin"; public static final String ADMIN_ROUTE = "/admin";
public static RouterLink getUserNavigation() { public static RouterLink getProfileNavigation() {
return new RouterLink(USER, UserView.class); return new RouterLink(PROFILE, ProfileView.class);
} }
public static RouterLink getRoleNavigation() { public static RouterLink getPermissionNavigation() {
return new RouterLink(ROLE, RoleView.class); return new RouterLink(PERMISSION, PermissionView.class);
} }
public static RouterLink getAuthorizationNavigation() { public static RouterLink getAuthorizationNavigation() {
return new RouterLink(AUTHORIZATION, AuthorizationView.class); return new RouterLink(AUTHORIZATION, AssignmentView.class);
} }
public static SideNavItem getAdminNavigation() { public static SideNavItem getAdminNavigation() {
SideNavItem administration = new SideNavItem(ADMIN_TITLE, USER_ROUTE, VaadinIcon.GROUP.create()); SideNavItem administration = new SideNavItem(ADMIN_TITLE, PROFILE_ROUTE, VaadinIcon.GROUP.create());
administration.addItem(new SideNavItem(USER, USER_ROUTE, VaadinIcon.USERS.create())); administration.addItem(new SideNavItem(PROFILE, PROFILE_ROUTE, VaadinIcon.USERS.create()));
administration.addItem(new SideNavItem(ROLE, RoleView.class)); administration.addItem(new SideNavItem(PERMISSION, PermissionView.class));
SideNavItem data = new SideNavItem(DATA, AUTHORIZATION_ROUTE, VaadinIcon.DATABASE.create()); SideNavItem data = new SideNavItem(DATA, ASSIGNMENT_ROUTE, VaadinIcon.DATABASE.create());
data.addItem(new SideNavItem(ComicConstants.COMICWORK, ComicWorkView.class)); data.addItem(new SideNavItem(ComicConstants.COMICWORK, ComicWorkView.class));
data.addItem(new SideNavItem(MediaConstants.MEDIAACTORFILE, MediaActorFileView.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("Data Import", ModuleDataView.class));
data.addItem(new SideNavItem("Meta Data", MetaDataView.class)); data.addItem(new SideNavItem("Meta Data", MetaDataView.class));
administration.addItem(data); administration.addItem(data);
@@ -1,9 +1,7 @@
package de.thpeetz.kontor.admin; package de.thpeetz.kontor.admin;
import de.thpeetz.kontor.admin.data.*; import de.thpeetz.kontor.admin.data.*;
import de.thpeetz.kontor.admin.repository.AuthorizationMatrixRepository; import de.thpeetz.kontor.admin.repository.*;
import de.thpeetz.kontor.admin.repository.MailAccountRepository;
import de.thpeetz.kontor.admin.repository.UserRepository;
import de.thpeetz.kontor.admin.services.AdminService; import de.thpeetz.kontor.admin.services.AdminService;
import de.thpeetz.kontor.admin.services.MetaDataService; import de.thpeetz.kontor.admin.services.MetaDataService;
import de.thpeetz.kontor.mailclient.data.MailAccount; import de.thpeetz.kontor.mailclient.data.MailAccount;
@@ -23,10 +21,10 @@ public class SetupModuleAdmin implements ApplicationListener<ContextRefreshedEve
boolean alreadySetup = false; boolean alreadySetup = false;
@Autowired @Autowired
private UserRepository userRepository; private ProfileRepository profileRepository;
@Autowired @Autowired
private AuthorizationMatrixRepository authorizationMatrixRepository; private AssignmentRepository assignmentRepository;
@Autowired @Autowired
private PasswordEncoder passwordEncoder; private PasswordEncoder passwordEncoder;
@@ -50,13 +48,13 @@ public class SetupModuleAdmin implements ApplicationListener<ContextRefreshedEve
} }
// Create initial roles and users // Create initial roles and users
Role adminRole = adminService.addRole("ROLE_ADMIN"); Permission adminPermission = adminService.addPermission("ROLE_ADMIN");
Role userRole = adminService.addRole("ROLE_USER"); Permission userPermission = adminService.addPermission("ROLE_USER");
List<User> users = userRepository.findAll(); List<Profile> profiles = profileRepository.findAll();
if (users.isEmpty()) { if (profiles.isEmpty()) {
User adminUser = initAdminUser(); Profile adminProfile = initAdminUser();
initMatrix(adminRole, adminUser); initAssignments(adminPermission, adminProfile);
initMatrix(userRole, adminUser); initAssignments(userPermission, adminProfile);
} }
log.info("MailProperties: {}", mailProperties); log.info("MailProperties: {}", mailProperties);
initMail(mailProperties); initMail(mailProperties);
@@ -98,32 +96,32 @@ public class SetupModuleAdmin implements ApplicationListener<ContextRefreshedEve
} }
} }
private void initMatrix(Role role, User user) { private void initAssignments(Permission permission, Profile profile) {
log.info("initMatrix: Role {} for User {}", role.getName(), user.getUserName()); log.info("initAssignments: Permission {} for Profile {}", permission.getName(), profile.getUserName());
Collection<AuthorizationMatrix> configuredRoles = authorizationMatrixRepository.findByUser(user); Collection<Assignment> configuredRoles = assignmentRepository.findByProfile(profile);
if (configuredRoles.stream().anyMatch(matrix -> matrix.getRole().getId().equals(role.getId()))) { if (configuredRoles.stream().anyMatch(assignment -> assignment.getPermission().getId().equals(permission.getId()))) {
log.info("Role {} already defined", role.getName()); log.info("Permission {} already defined", permission.getName());
} else { } else {
log.info("add Role {} to User {}", role.getName(), user.getUserName()); log.info("add Permission {} to Profile {}", permission.getName(), profile.getUserName());
final AuthorizationMatrix adminMatrix = new AuthorizationMatrix(); final Assignment assignment = new Assignment();
adminMatrix.setUser(user); assignment.setProfile(profile);
adminMatrix.setRole(role); assignment.setPermission(permission);
authorizationMatrixRepository.save(adminMatrix); assignmentRepository.save(assignment);
} }
} }
private User initAdminUser() { private Profile initAdminUser() {
log.info("initAdminUser"); log.info("initAdminUser");
User admin = userRepository.findByUserName("admin"); Profile admin = profileRepository.findByUserName("admin");
if (admin == null) { if (admin == null) {
log.info("User admin not found, will be created."); log.info("Profile admin not found, will be created.");
admin = new User(); admin = new Profile();
admin.setFirstName("Admin"); admin.setFirstName("Admin");
admin.setLastName("Administrator"); admin.setLastName("Administrator");
admin.setUserName("admin"); admin.setUserName("admin");
admin.setEmail("admin@example.org"); admin.setEmail("admin@example.org");
admin.setPassword(passwordEncoder.encode("admin")); admin.setPassword(passwordEncoder.encode("admin"));
userRepository.save(admin); profileRepository.save(admin);
} }
return admin; return admin;
} }
@@ -348,17 +346,17 @@ public class SetupModuleAdmin implements ApplicationListener<ContextRefreshedEve
metaDataService.getColumn(cardTable, "card_set_id", "card_set_id", "TEXT", null, 7, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(cardTable, "card_set_id", "card_set_id", "TEXT", null, 7, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(cardTable, "rooster_id", "rooster_id", "TEXT", null, 8, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(cardTable, "rooster_id", "rooster_id", "TEXT", null, 8, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(cardTable, "vendor_id", "vendor_id", "TEXT", null, 9, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(cardTable, "vendor_id", "vendor_id", "TEXT", null, 9, Boolean.FALSE, "", Boolean.FALSE, null);
MetaDataTable userTable = metaDataService.getTable("user"); MetaDataTable profileTable = metaDataService.getTable("profile");
metaDataService.getColumn(userTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "", Boolean.FALSE, null); metaDataService.getColumn(profileTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "", Boolean.FALSE, null);
metaDataService.getColumn(userTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(profileTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(userTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(profileTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(userTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(profileTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(userTable, "first_name", "first_name", "TEXT", null, 5, Boolean.TRUE, "", Boolean.FALSE, null); metaDataService.getColumn(profileTable, "first_name", "first_name", "TEXT", null, 5, Boolean.TRUE, "", Boolean.FALSE, null);
metaDataService.getColumn(userTable, "last_name", "last_name", "TEXT", null, 6, Boolean.TRUE, "", Boolean.FALSE, null); metaDataService.getColumn(profileTable, "last_name", "last_name", "TEXT", null, 6, Boolean.TRUE, "", Boolean.FALSE, null);
metaDataService.getColumn(userTable, "user_name", "user_name", "TEXT", "UNIQUE", 7, Boolean.TRUE, "", Boolean.FALSE, null); metaDataService.getColumn(profileTable, "user_name", "user_name", "TEXT", "UNIQUE", 7, Boolean.TRUE, "", Boolean.FALSE, null);
metaDataService.getColumn(userTable, "email", "email", "TEXT", null, 8, Boolean.TRUE, "", Boolean.FALSE, null); metaDataService.getColumn(profileTable, "email", "email", "TEXT", null, 8, Boolean.TRUE, "", Boolean.FALSE, null);
metaDataService.getColumn(userTable, "password", "password", "TEXT", null, 9, Boolean.FALSE, "Password", Boolean.FALSE, null); metaDataService.getColumn(profileTable, "password", "password", "TEXT", null, 9, Boolean.FALSE, "Password", Boolean.FALSE, null);
metaDataService.getColumn(userTable, "enabled", "enabled", "BOOLEAN", null, 10, Boolean.TRUE, "", Boolean.TRUE, null); metaDataService.getColumn(profileTable, "enabled", "enabled", "BOOLEAN", null, 10, Boolean.TRUE, "", Boolean.TRUE, null);
MetaDataTable tokenTable = metaDataService.getTable("token"); MetaDataTable tokenTable = metaDataService.getTable("token");
metaDataService.getColumn(tokenTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "", Boolean.FALSE, null); metaDataService.getColumn(tokenTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "", Boolean.FALSE, null);
metaDataService.getColumn(tokenTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(tokenTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
@@ -368,20 +366,20 @@ public class SetupModuleAdmin implements ApplicationListener<ContextRefreshedEve
metaDataService.getColumn(tokenTable, "name", "name", "TEXT", null, 6, Boolean.TRUE, "Name", Boolean.FALSE, null); metaDataService.getColumn(tokenTable, "name", "name", "TEXT", null, 6, Boolean.TRUE, "Name", Boolean.FALSE, null);
metaDataService.getColumn(tokenTable, "last_used_date", "used", "TIMESTAMP", null, 7, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(tokenTable, "last_used_date", "used", "TIMESTAMP", null, 7, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(tokenTable, "enabled", "enabled", "BOOLEAN", null, 8, Boolean.TRUE, "", Boolean.TRUE, "Enabled"); metaDataService.getColumn(tokenTable, "enabled", "enabled", "BOOLEAN", null, 8, Boolean.TRUE, "", Boolean.TRUE, "Enabled");
metaDataService.getColumn(tokenTable, "user_id", "user_id", "TEXT", null, 9, Boolean.TRUE, "User", Boolean.FALSE, null, "user_name"); metaDataService.getColumn(tokenTable, "profile_id", "profile_id", "TEXT", null, 9, Boolean.TRUE, "Profile", Boolean.FALSE, null, "user_name");
MetaDataTable roleTable = metaDataService.getTable("role"); MetaDataTable permissionTable = metaDataService.getTable("permission");
metaDataService.getColumn(roleTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "", Boolean.FALSE, null); metaDataService.getColumn(permissionTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "", Boolean.FALSE, null);
metaDataService.getColumn(roleTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(permissionTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(roleTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(permissionTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(roleTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(permissionTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(roleTable, "name", "name", "TEXT", null, 5, Boolean.TRUE, "", Boolean.FALSE, null); metaDataService.getColumn(permissionTable, "name", "name", "TEXT", null, 5, Boolean.TRUE, "", Boolean.FALSE, null);
MetaDataTable authorizationMatrix = metaDataService.getTable("authorization_matrix"); MetaDataTable AssignmentTable = metaDataService.getTable("assignment");
metaDataService.getColumn(authorizationMatrix, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "", Boolean.FALSE, null); metaDataService.getColumn(AssignmentTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "", Boolean.FALSE, null);
metaDataService.getColumn(authorizationMatrix, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(AssignmentTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(authorizationMatrix, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(AssignmentTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(authorizationMatrix, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(AssignmentTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
metaDataService.getColumn(authorizationMatrix, "user_id", "user_id", "TEXT", null, 5, Boolean.TRUE, "User", Boolean.FALSE, null, "user_name"); metaDataService.getColumn(AssignmentTable, "profile_id", "profile_id", "TEXT", null, 5, Boolean.TRUE, "Profile", Boolean.FALSE, null, "user_name");
metaDataService.getColumn(authorizationMatrix, "role_id", "role_id", "TEXT", null, 6, Boolean.TRUE, "Role", Boolean.FALSE, null, "name"); metaDataService.getColumn(AssignmentTable, "permission_id", "permission_id", "TEXT", null, 6, Boolean.TRUE, "Permission", Boolean.FALSE, null, "name");
MetaDataTable moduleDataTable = metaDataService.getTable("module_data"); MetaDataTable moduleDataTable = metaDataService.getTable("module_data");
metaDataService.getColumn(moduleDataTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "", Boolean.FALSE, null); metaDataService.getColumn(moduleDataTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "", Boolean.FALSE, null);
metaDataService.getColumn(moduleDataTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null); metaDataService.getColumn(moduleDataTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
@@ -7,28 +7,27 @@ import jakarta.persistence.ManyToOne;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString;
@Getter @Getter
@Setter @Setter
@Entity @Entity
public class AuthorizationMatrix extends AbstractEntity { public class Assignment extends AbstractEntity {
@ManyToOne @ManyToOne
@JoinColumn(name = "user_id") @JoinColumn(name = "profile_id")
@NotNull @NotNull
private User user; private Profile profile;
@ManyToOne @ManyToOne
@JoinColumn(name = "role_id") @JoinColumn(name = "permission_id")
@NotNull @NotNull
private Role role; private Permission permission;
@Override @Override
public String toString() { public String toString() {
final StringBuffer sb = new StringBuffer("AuthorizationMatrix{"); final StringBuffer sb = new StringBuffer("Assignment{");
sb.append("user=").append(user.getUserName()); sb.append("profile=").append(profile.getUserName());
sb.append(", role=").append(role.getName()); sb.append(", permission=").append(permission.getName());
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
@@ -1,7 +1,5 @@
package de.thpeetz.kontor.admin.data; package de.thpeetz.kontor.admin.data;
import java.util.List;
import de.thpeetz.kontor.common.data.AbstractEntity; import de.thpeetz.kontor.common.data.AbstractEntity;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.FetchType; import jakarta.persistence.FetchType;
@@ -13,18 +11,19 @@ import lombok.ToString;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
@Slf4j @Slf4j
@Getter @Getter
@Setter @Setter
@ToString @ToString
@Entity @Entity
public class Role extends AbstractEntity { public class Permission extends AbstractEntity {
@NotEmpty @NotEmpty
private String name; private String name;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "role") @OneToMany(fetch = FetchType.EAGER, mappedBy = "permission")
@Nullable @Nullable
private List<AuthorizationMatrix> matrix; private List<Assignment> assignments;
} }
@@ -1,12 +1,7 @@
package de.thpeetz.kontor.admin.data; package de.thpeetz.kontor.admin.data;
import de.thpeetz.kontor.common.data.AbstractEntity; import de.thpeetz.kontor.common.data.AbstractEntity;
import jakarta.persistence.Entity; import jakarta.persistence.*;
import jakarta.persistence.FetchType;
import jakarta.persistence.Index;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -23,7 +18,7 @@ import java.util.List;
@ToString @ToString
@Entity @Entity
@Table(indexes = @Index(columnList = "userName"), uniqueConstraints = @UniqueConstraint(columnNames = {"userName"})) @Table(indexes = @Index(columnList = "userName"), uniqueConstraints = @UniqueConstraint(columnNames = {"userName"}))
public class User extends AbstractEntity { public class Profile extends AbstractEntity {
private String firstName; private String firstName;
@@ -38,25 +33,25 @@ public class User extends AbstractEntity {
private boolean enabled; private boolean enabled;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user") @OneToMany(fetch = FetchType.EAGER, mappedBy = "profile")
@Nullable @Nullable
private List<AuthorizationMatrix> matrix = new LinkedList<>(); private List<Assignment> assignments = new LinkedList<>();
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user") @OneToMany(fetch = FetchType.EAGER, mappedBy = "profile")
@Nullable @Nullable
private List<Token> tokens = new LinkedList<>(); private List<Token> tokens = new LinkedList<>();
public String getFullName() { public String getFullName() {
StringBuilder fullNamBuilder = new StringBuilder(); StringBuilder fullNameBuilder = new StringBuilder();
if (firstName != null) { if (firstName != null) {
fullNamBuilder.append(firstName); fullNameBuilder.append(firstName);
} }
if (lastName != null) { if (lastName != null) {
if (fullNamBuilder.length() > 0) { if (!fullNameBuilder.isEmpty()) {
fullNamBuilder.append(" "); fullNameBuilder.append(" ");
} }
fullNamBuilder.append(lastName); fullNameBuilder.append(lastName);
} }
return fullNamBuilder.toString(); return fullNameBuilder.toString();
} }
} }
@@ -31,7 +31,7 @@ public class Token extends AbstractEntity {
private boolean enabled; private boolean enabled;
@ManyToOne @ManyToOne
@JoinColumn(name="user_id") @JoinColumn(name="profile_id")
@NotNull @NotNull
private User user; private Profile profile;
} }
@@ -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<Assignment, String> {
List<Assignment> findByProfile(Profile profile);
List<Assignment> findByPermission(Permission permission);
}
@@ -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<AuthorizationMatrix, String> {
List<AuthorizationMatrix> findByUser(User user);
List<AuthorizationMatrix> findByRole(Role role);
}
@@ -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<Permission, String> {
@Query("select p from Permission p " +
"where lower(p.name) like lower(concat('%', :searchTerm, '%')) ")
List<Permission> search(@Param("searchTerm") String searchTerm);
@Query("select p from Permission p " +
"where lower(p.name) like lower(:name) ")
Permission findByName(@Param("name") String name);
}
@@ -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<Profile, String> {
@Query("select p from Profile p " +
"where lower(p.lastName) like lower(concat('%', :searchTerm, '%')) ")
List<Profile> search(@Param("searchTerm") String searchTerm);
Profile findByUserName(String userName);
}
@@ -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<Role, String> {
@Query("select r from Role r " +
"where lower(r.name) like lower(concat('%', :searchTerm, '%')) ")
List<Role> search(@Param("searchTerm") String searchTerm);
@Query("select r from Role r " +
"where lower(r.name) like lower(:name) ")
Role findByName(@Param("name") String name);
}
@@ -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<User, String> {
@Query("select u from User u " +
"where lower(u.lastName) like lower(concat('%', :searchTerm, '%')) ")
List<User> search(@Param("searchTerm") String searchTerm);
User findByUserName(String userName);
}
@@ -3,108 +3,105 @@ package de.thpeetz.kontor.admin.services;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import de.thpeetz.kontor.admin.data.*;
import de.thpeetz.kontor.admin.repository.*;
import org.springframework.stereotype.Service; 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; import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
@Service @Service
public class AdminService { public class AdminService {
private final UserRepository userRepository;
private final RoleRepository roleRepository;
private final AuthorizationMatrixRepository authorizationMatrixRepository;
public AdminService(UserRepository userRepository, RoleRepository roleRepository, private final ProfileRepository profileRepository;
AuthorizationMatrixRepository authorizationMatrixRepository) { private final PermissionRepository permissionRepository;
this.userRepository = userRepository; private final AssignmentRepository assignmentRepository;
this.roleRepository = roleRepository;
this.authorizationMatrixRepository = authorizationMatrixRepository; public AdminService(ProfileRepository profileRepository,
PermissionRepository permissionRepository,
AssignmentRepository assignmentRepository) {
this.profileRepository = profileRepository;
this.permissionRepository = permissionRepository;
this.assignmentRepository = assignmentRepository;
} }
public List<User> findAllUsers() { public List<Profile> findAllProfiles() { return profileRepository.findAll(); }
return userRepository.findAll();
public Profile getProfile(String userName) {
log.debug("get Profile {}", userName);
return profileRepository.findByUserName(userName);
} }
public List<Role> findAllRoles() { public List<Permission> findAllPermissions() { return permissionRepository.findAll(); }
return roleRepository.findAll();
}
public Collection<Role> findAllRoles(String stringFilter) { public Collection<Permission> findAllPermissions(String stringFilter) {
if (stringFilter == null || stringFilter.isEmpty()) { if (stringFilter == null || stringFilter.isEmpty()) {
return roleRepository.findAll(); return permissionRepository.findAll();
} else { } else {
return roleRepository.search(stringFilter); return permissionRepository.search(stringFilter);
} }
} }
public Role addRole(String roleName) { public Permission addPermission(String permissionName) {
Role role = roleRepository.findByName(roleName); Permission permission = permissionRepository.findByName(permissionName);
if (role == null) { if (permission == null) {
log.info("Role {} was not found, will create it.", roleName); log.info("Permission {} was not found, will create it.", permissionName);
role = new Role(); permission = new Permission();
role.setName(roleName); permission.setName(permissionName);
roleRepository.save(role); permissionRepository.save(permission);
} }
return role; return permission;
} }
public void saveRole(Role role) { public void savePermission(Permission permission) {
if (role == null) { if (permission == null) {
log.warn("Role is null. Can't save it."); log.warn("Permission is null. Can't save it.");
} }
log.info("saveRole: role={}", role); log.info("savePermission: permission={}", permission);
roleRepository.save(role); permissionRepository.save(permission);
} }
public void deleteRole(Role role) { public void deletePermission(Permission permission) {
if (role == null) { if (permission == null) {
log.warn("Role is null. Can't delete it."); log.warn("Permission is null. Can't delete it.");
return;
} }
log.info("deleteRole: role={}", role); log.info("deletePermission: permission={}", permission);
roleRepository.delete(role); permissionRepository.delete(permission);
} }
public List<AuthorizationMatrix> findAllAuthorizationMatrices() { public List<Assignment> findAllAssignments() {
return authorizationMatrixRepository.findAll(); return assignmentRepository.findAll();
} }
public void saveAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) { public void saveAssignment(Assignment assignment) {
if (authorizationMatrix == null) { if (assignment == null) {
log.warn("AuthorizationMatrix is null. Can't save it."); log.warn("Assignment is null. Can't save it.");
return;
} }
log.info("saveAuthorizationMatrix: authorizationMatrix={}", authorizationMatrix); log.info("saveAssignment: assignment={}", assignment);
authorizationMatrixRepository.save(authorizationMatrix); assignmentRepository.save(assignment);
} }
public void deleteAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) { public void deleteAssignment(Assignment assignment) {
if (authorizationMatrix == null) { if (assignment == null) {
log.warn("AuthorizationMatrix is null. Can't delete it."); log.warn("Assignment is null. Can't delete it.");
return;
} }
log.info("deleteAuthorizationMatrix: authorizationMatrix={}", authorizationMatrix); log.info("deleteAssignment: assignment={}", assignment);
authorizationMatrixRepository.delete(authorizationMatrix); assignmentRepository.delete(assignment);
} }
public String getUserFullName(String userName) { public String getProfileFullName(String userName) {
log.debug("get Fullname für user {}", userName); log.debug("get Fullname für Profile {}", userName);
User user = userRepository.findByUserName(userName); Profile profile = profileRepository.findByUserName(userName);
if (user == null) { if (profile == null) {
log.info("keinen Eintrag für {} gefunden", userName); log.info("keinen Eintrag für {} gefunden", userName);
return userName; return userName;
} else { } else {
log.info("Voller Name des User {}: {}", userName, user.getFullName()); log.info("Voller Name des Profile {}: {}", userName, profile.getFullName());
return user.getFullName(); return profile.getFullName();
} }
} }
public User getUser(String userName) {
log.debug("get User {}", userName);
return userRepository.findByUserName(userName);
}
} }
@@ -1,9 +1,7 @@
package de.thpeetz.kontor.admin.services; package de.thpeetz.kontor.admin.services;
import de.thpeetz.kontor.admin.data.*; import de.thpeetz.kontor.admin.data.*;
import de.thpeetz.kontor.admin.repository.AuthorizationMatrixRepository; import de.thpeetz.kontor.admin.repository.*;
import de.thpeetz.kontor.admin.repository.RoleRepository;
import de.thpeetz.kontor.admin.repository.UserRepository;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
@@ -26,83 +24,86 @@ public class KontorUserDetailsService implements UserDetailsService {
private static SecureRandom random = new SecureRandom(); private static SecureRandom random = new SecureRandom();
@Autowired @Autowired
private UserRepository userRepository; private ProfileRepository profileRepository;
@Autowired @Autowired
private RoleRepository roleRepository; private PermissionRepository permissionRepository;
@Autowired @Autowired
private AuthorizationMatrixRepository authorizationMatrixRepository; private AssignmentRepository assignmentRepository;
public Collection<User> findAllUsers(String stringFilter) { public Collection<Profile> findAllProfiles(String stringFilter) {
if (stringFilter == null || stringFilter.isEmpty()) { if (stringFilter == null || stringFilter.isEmpty()) {
return userRepository.findAll(); return profileRepository.findAll();
} else { } else {
return userRepository.search(stringFilter); return profileRepository.search(stringFilter);
} }
} }
public void saveUser(User user) { public void saveProfile(Profile profile) {
if (user == null) { if (profile == null) {
log.warn("User is null. Can't save it."); log.warn("Profile is null. Can't save it.");
return;
} }
log.info("saveUser: user={}", user); log.info("saveProfile: profile={}", profile);
userRepository.save(user); profileRepository.save(profile);
} }
public void saveUser(User user, List<Role> roles) { public void saveProfile(Profile profile, List<Permission> permissions) {
if (user == null) { if (profile == null) {
log.warn("User is null. Can't save it."); log.warn("Profile is null. Can't save it.");
return;
} }
log.info("First save user: {}", user); log.info("First save Profile: {}", profile);
user = userRepository.save(user); profile = profileRepository.save(profile);
List<Role> copy = roles.stream().collect(Collectors.toList()); List<Permission> copy = permissions.stream().collect(Collectors.toList());
List<AuthorizationMatrix> permissions = user.getMatrix(); List<Assignment> assignments = profile.getAssignments();
permissions.forEach(matrix -> { assignments.forEach(assignment -> {
if (roles.contains(matrix.getRole())) { if (permissions.contains(assignment.getPermission())) {
log.info("Role {} already assigned", matrix.getRole()); log.info("Permission {} already assigned", assignment.getPermission());
copy.remove(matrix.getRole()); copy.remove(assignment.getPermission());
} else { } else {
log.info("Role {} has to be removed", matrix.getRole()); log.info("Permission {} has to be removed", assignment.getPermission());
authorizationMatrixRepository.delete(matrix); assignmentRepository.delete(assignment);
} }
}); });
log.info("remaining roles: {}", copy); log.info("remaining roles: {}", copy);
for (Role role : copy) { for (Permission permission : copy) {
AuthorizationMatrix matrix = new AuthorizationMatrix(); Assignment assignment = new Assignment();
matrix.setUser(user); assignment.setProfile(profile);
matrix.setRole(role); assignment.setPermission(permission);
authorizationMatrixRepository.save(matrix); assignmentRepository.save(assignment);
} }
} }
public void deleteUser(User user) { public void deleteProfile(Profile profile) {
if (user == null) { if (profile == null) {
log.warn("User is null. Can't delete it."); log.warn("Profile is null. Can't delete it.");
return;
} }
log.info("deleteUser: user={}", user); log.info("deleteProfile: profile={}", profile);
userRepository.delete(user); profileRepository.delete(profile);
} }
@Override @Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
log.info("loadUserByUsername: userName={}", userName); log.info("loadUserByUsername: userName={}", userName);
User user = userRepository.findByUserName(userName); Profile profile = profileRepository.findByUserName(userName);
if (user == null) { if (profile == null) {
log.info("User not found"); log.info("User not found");
return null; return null;
} }
Collection<? extends GrantedAuthority> authorities = getAuthorities(user); Collection<? extends GrantedAuthority> authorities = getAuthorities(profile);
log.info("User {} hat Rolen: {}", userName, authorities); log.info("Profile {} hat Permissions: {}", userName, authorities);
return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getPassword(), return new org.springframework.security.core.userdetails.User(profile.getUserName(), profile.getPassword(),
authorities); authorities);
} }
private Collection<? extends GrantedAuthority> getAuthorities(User user) { private Collection<? extends GrantedAuthority> getAuthorities(Profile profile) {
return authorizationMatrixRepository.findByUser(user).stream() return assignmentRepository.findByProfile(profile).stream()
.map(matrix -> matrix.getRole().getName()) .map(assignment -> assignment.getPermission().getName())
.map(SimpleGrantedAuthority::new) .map(SimpleGrantedAuthority::new)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@@ -122,7 +123,7 @@ public class KontorUserDetailsService implements UserDetailsService {
log.info("removeRememberedUser: id={}", id); log.info("removeRememberedUser: id={}", id);
} }
public List<Role> findAllRoles() { public List<Permission> findAllPermissions() {
return roleRepository.findAll(); return permissionRepository.findAll();
} }
} }
@@ -29,7 +29,7 @@ public class AdminLayout extends AppLayout {
private HorizontalLayout getSecondaryNavigation() { private HorizontalLayout getSecondaryNavigation() {
HorizontalLayout navigation = new HorizontalLayout(); HorizontalLayout navigation = new HorizontalLayout();
navigation.addClassNames(LumoUtility.JustifyContent.CENTER, LumoUtility.Gap.SMALL, LumoUtility.Height.MEDIUM); 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()); AdminConstants.getAuthorizationNavigation());
return navigation; return navigation;
} }
@@ -13,32 +13,32 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.data.binder.BeanValidationBinder; import com.vaadin.flow.data.binder.BeanValidationBinder;
import com.vaadin.flow.data.binder.Binder; import com.vaadin.flow.data.binder.Binder;
import de.thpeetz.kontor.admin.data.AuthorizationMatrix; import de.thpeetz.kontor.admin.data.Assignment;
import de.thpeetz.kontor.admin.data.Role; import de.thpeetz.kontor.admin.data.Permission;
import de.thpeetz.kontor.admin.data.User; import de.thpeetz.kontor.admin.data.Profile;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public class AuthorizationForm extends FormLayout { public class AssignmentForm extends FormLayout {
ComboBox<User> user = new ComboBox<>("User"); ComboBox<Profile> profile = new ComboBox<>("Proile");
ComboBox<Role> role = new ComboBox<>("Role"); ComboBox<Permission> permission = new ComboBox<>("Permission");
Button save = new Button("Save"); Button save = new Button("Save");
Button delete = new Button("Delete"); Button delete = new Button("Delete");
Button close = new Button("Cancel"); Button close = new Button("Cancel");
Binder<AuthorizationMatrix> binder = new BeanValidationBinder<>(AuthorizationMatrix.class); Binder<Assignment> binder = new BeanValidationBinder<>(Assignment.class);
public AuthorizationForm(List<User> users, List<Role> roles) { public AssignmentForm(List<Profile> profiles, List<Permission> permissions) {
addClassName("authorizationmatrix-form"); addClassName("assignment-form");
binder.bindInstanceFields(this); binder.bindInstanceFields(this);
user.setItems(users); profile.setItems(profiles);
user.setItemLabelGenerator(User::getUserName); profile.setItemLabelGenerator(Profile::getUserName);
role.setItems(roles); permission.setItems(permissions);
role.setItemLabelGenerator(Role::getName); permission.setItemLabelGenerator(Permission::getName);
add(user, role, createButtonsLayout()); add(profile, permission, createButtonsLayout());
} }
private HorizontalLayout createButtonsLayout() { private HorizontalLayout createButtonsLayout() {
@@ -63,37 +63,37 @@ public class AuthorizationForm extends FormLayout {
} }
} }
public void setAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) { public void setAssignment(Assignment assignment) {
binder.setBean(authorizationMatrix); binder.setBean(assignment);
} }
public abstract static class AuthorizationFormEvent extends ComponentEvent<AuthorizationForm> { public abstract static class AssignmentFormEvent extends ComponentEvent<AssignmentForm> {
private AuthorizationMatrix authorizationMatrix; private Assignment assignment;
protected AuthorizationFormEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) { protected AssignmentFormEvent(AssignmentForm source, Assignment assignment) {
super(source, false); super(source, false);
this.authorizationMatrix = authorizationMatrix; this.assignment = assignment;
} }
public AuthorizationMatrix getAuthorizationMatrix() { public Assignment getAssignment() {
return authorizationMatrix; return assignment;
} }
} }
public static class SaveEvent extends AuthorizationFormEvent { public static class SaveEvent extends AssignmentFormEvent {
SaveEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) { SaveEvent(AssignmentForm source, Assignment assignment) {
super(source, authorizationMatrix); super(source, assignment);
} }
} }
public static class DeleteEvent extends AuthorizationFormEvent { public static class DeleteEvent extends AssignmentFormEvent {
DeleteEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) { DeleteEvent(AssignmentForm source, Assignment assignment) {
super(source, authorizationMatrix); super(source, assignment);
} }
} }
public static class CloseEvent extends AuthorizationFormEvent { public static class CloseEvent extends AssignmentFormEvent {
CloseEvent(AuthorizationForm source) { CloseEvent(AssignmentForm source) {
super(source, null); super(source, null);
} }
} }
@@ -1,5 +1,6 @@
package de.thpeetz.kontor.admin.views; package de.thpeetz.kontor.admin.views;
import de.thpeetz.kontor.admin.data.Assignment;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
@@ -13,7 +14,6 @@ import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.annotation.SpringComponent;
import de.thpeetz.kontor.admin.AdminConstants; import de.thpeetz.kontor.admin.AdminConstants;
import de.thpeetz.kontor.admin.data.AuthorizationMatrix;
import de.thpeetz.kontor.admin.services.AdminService; import de.thpeetz.kontor.admin.services.AdminService;
import de.thpeetz.kontor.common.views.MainLayout; import de.thpeetz.kontor.common.views.MainLayout;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
@@ -23,17 +23,17 @@ import lombok.extern.slf4j.Slf4j;
@SpringComponent @SpringComponent
@Scope("prototype") @Scope("prototype")
@RolesAllowed("ROLE_ADMIN") @RolesAllowed("ROLE_ADMIN")
@Route(value = AdminConstants.AUTHORIZATION_ROUTE, layout = MainLayout.class) @Route(value = AdminConstants.ASSIGNMENT_ROUTE, layout = MainLayout.class)
@PageTitle("Authorization | Admin | Kontor") @PageTitle("Authorization | Admin | Kontor")
public class AuthorizationView extends VerticalLayout { public class AssignmentView extends VerticalLayout {
Grid<AuthorizationMatrix> grid = new Grid<>(AuthorizationMatrix.class); Grid<Assignment> grid = new Grid<>(Assignment.class);
AuthorizationForm form; AssignmentForm form;
AdminService service; AdminService service;
public AuthorizationView(AdminService service) { public AssignmentView(AdminService service) {
this.service = service; this.service = service;
addClassName("authoriaztionmatrix-view"); addClassName("assignment-view");
setSizeFull(); setSizeFull();
configureGrid(); configureGrid();
configureForm(); configureForm();
@@ -43,30 +43,30 @@ public class AuthorizationView extends VerticalLayout {
} }
private void configureGrid() { private void configureGrid() {
grid.addClassName("authorizationmatrix-grid"); grid.addClassName("assignment-grid");
grid.setSizeFull(); grid.setSizeFull();
grid.setColumns("user.userName", "role.name"); grid.setColumns("profile.userName", "permission.name");
grid.getColumns().forEach(col -> col.setAutoWidth(true)); grid.getColumns().forEach(col -> col.setAutoWidth(true));
grid.asSingleSelect().addValueChangeListener(event -> editAuthorizationMatrix(event.getValue())); grid.asSingleSelect().addValueChangeListener(event -> editAssignment(event.getValue()));
} }
private void configureForm() { private void configureForm() {
form = new AuthorizationForm(service.findAllUsers(), service.findAllRoles()); form = new AssignmentForm(service.findAllProfiles(), service.findAllPermissions());
form.setWidth("25em"); form.setWidth("25em");
form.addSaveListener(this::saveAuthorizationMatrix); form.addSaveListener(this::saveAssignment);
form.addDeleteListener(this::deleteAuthorizationMatrix); form.addDeleteListener(this::deleteAssignment);
form.addCloseListener(e -> closeEditor()); form.addCloseListener(e -> closeEditor());
} }
private void saveAuthorizationMatrix(AuthorizationForm.SaveEvent event) { private void saveAssignment(AssignmentForm.SaveEvent event) {
AuthorizationMatrix authorizationMatrix = event.getAuthorizationMatrix(); Assignment assignment = event.getAssignment();
service.saveAuthorizationMatrix(authorizationMatrix); service.saveAssignment(assignment);
updateList(); updateList();
closeEditor(); closeEditor();
} }
private void deleteAuthorizationMatrix(AuthorizationForm.DeleteEvent event) { private void deleteAssignment(AssignmentForm.DeleteEvent event) {
service.deleteAuthorizationMatrix(event.getAuthorizationMatrix()); service.deleteAssignment(event.getAssignment());
updateList(); updateList();
closeEditor(); closeEditor();
} }
@@ -81,34 +81,34 @@ public class AuthorizationView extends VerticalLayout {
} }
private HorizontalLayout getToolbar() { private HorizontalLayout getToolbar() {
Button addAuthorizationMaxtrixButton = new Button("Add permssion", click -> addAuthorizationMatrix()); Button addAuthorizationMaxtrixButton = new Button("Add permission", click -> addAssignment());
HorizontalLayout toolbar = new HorizontalLayout(addAuthorizationMaxtrixButton); HorizontalLayout toolbar = new HorizontalLayout(addAuthorizationMaxtrixButton);
toolbar.addClassName("toolbar"); toolbar.addClassName("toolbar");
return toolbar; return toolbar;
} }
public void editAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) { public void editAssignment(Assignment assignment) {
if (authorizationMatrix == null) { if (assignment == null) {
closeEditor(); closeEditor();
} else { } else {
form.setAuthorizationMatrix(authorizationMatrix); form.setAssignment(assignment);
form.setVisible(true); form.setVisible(true);
addClassName("editing"); addClassName("editing");
} }
} }
public void closeEditor() { public void closeEditor() {
form.setAuthorizationMatrix(null); form.setAssignment(null);
form.setVisible(false); form.setVisible(false);
removeClassName("editing"); removeClassName("editing");
} }
private void addAuthorizationMatrix() { private void addAssignment() {
grid.asSingleSelect().clear(); grid.asSingleSelect().clear();
editAuthorizationMatrix(new AuthorizationMatrix()); editAssignment(new Assignment());
} }
private void updateList() { private void updateList() {
grid.setItems(service.findAllAuthorizationMatrices()); grid.setItems(service.findAllAssignments());
} }
} }
@@ -10,12 +10,11 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.BeanValidationBinder; import com.vaadin.flow.data.binder.BeanValidationBinder;
import com.vaadin.flow.data.binder.Binder; import com.vaadin.flow.data.binder.Binder;
import de.thpeetz.kontor.admin.data.Permission;
import de.thpeetz.kontor.admin.data.Role;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public class RoleForm extends FormLayout { public class PermissionForm extends FormLayout {
TextField name = new TextField("Role name"); TextField name = new TextField("Role name");
@@ -23,10 +22,10 @@ public class RoleForm extends FormLayout {
Button delete = new Button("Delete"); Button delete = new Button("Delete");
Button close = new Button("Cancel"); Button close = new Button("Cancel");
Binder<Role> binder = new BeanValidationBinder<>(Role.class); Binder<Permission> binder = new BeanValidationBinder<>(Permission.class);
public RoleForm() { public PermissionForm() {
addClassName("role-form"); addClassName("permission-form");
binder.bindInstanceFields(this); binder.bindInstanceFields(this);
add(name, createButtonsLayout()); add(name, createButtonsLayout());
} }
@@ -53,37 +52,37 @@ public class RoleForm extends FormLayout {
} }
} }
public void setRole(Role role) { public void setPermission(Permission permission) {
binder.setBean(role); binder.setBean(permission);
} }
public abstract static class RoleFormEvent extends ComponentEvent<RoleForm> { public abstract static class PermissionFormEvent extends ComponentEvent<PermissionForm> {
private Role role; private Permission permission;
protected RoleFormEvent(RoleForm source, Role role) { protected PermissionFormEvent(PermissionForm source, Permission permission) {
super(source, false); super(source, false);
this.role = role; this.permission = permission;
} }
public Role getRole() { public Permission getPermission() {
return role; return permission;
} }
} }
public static class SaveEvent extends RoleFormEvent { public static class SaveEvent extends PermissionFormEvent {
SaveEvent(RoleForm source, Role role) { SaveEvent(PermissionForm source, Permission permission) {
super(source, role); super(source, permission);
} }
} }
public static class DeleteEvent extends RoleFormEvent { public static class DeleteEvent extends PermissionFormEvent {
DeleteEvent(RoleForm source, Role role) { DeleteEvent(PermissionForm source, Permission permission) {
super(source, role); super(source, permission);
} }
} }
public static class CloseEvent extends RoleFormEvent { public static class CloseEvent extends PermissionFormEvent {
CloseEvent(RoleForm source) { CloseEvent(PermissionForm source) {
super(source, null); super(source, null);
} }
} }
@@ -1,5 +1,6 @@
package de.thpeetz.kontor.admin.views; package de.thpeetz.kontor.admin.views;
import de.thpeetz.kontor.admin.data.Permission;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Component;
@@ -14,7 +15,6 @@ import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.annotation.SpringComponent;
import de.thpeetz.kontor.admin.AdminConstants; import de.thpeetz.kontor.admin.AdminConstants;
import de.thpeetz.kontor.admin.data.Role;
import de.thpeetz.kontor.admin.services.AdminService; import de.thpeetz.kontor.admin.services.AdminService;
import de.thpeetz.kontor.common.views.MainLayout; import de.thpeetz.kontor.common.views.MainLayout;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
@@ -24,17 +24,18 @@ import lombok.extern.slf4j.Slf4j;
@SpringComponent @SpringComponent
@Scope("prototype") @Scope("prototype")
@RolesAllowed("ROLE_ADMIN") @RolesAllowed("ROLE_ADMIN")
@Route(value = AdminConstants.ROLE_ROUTE, layout = MainLayout.class) @Route(value = AdminConstants.PERMISSION_ROUTE, layout = MainLayout.class)
@PageTitle("Rollen | Admin | Kontor") @PageTitle("Permissions | Admin | Kontor")
public class RoleView extends VerticalLayout { public class PermissionView extends VerticalLayout {
Grid<Role> grid = new Grid<>(Role.class);
Grid<Permission> grid = new Grid<>(Permission.class);
TextField filterText = new TextField(); TextField filterText = new TextField();
RoleForm form; PermissionForm form;
AdminService service; AdminService service;
public RoleView(AdminService service) { public PermissionView(AdminService service) {
this.service = service; this.service = service;
addClassName("user-view"); addClassName("permission-view");
setSizeFull(); setSizeFull();
configureGrid(); configureGrid();
configureForm(); configureForm();
@@ -44,29 +45,29 @@ public class RoleView extends VerticalLayout {
} }
private void configureGrid() { private void configureGrid() {
grid.addClassName("user-grid"); grid.addClassName("permission-grid");
grid.setSizeFull(); grid.setSizeFull();
grid.setColumns("name"); grid.setColumns("name");
grid.getColumns().forEach(col -> col.setAutoWidth(true)); grid.getColumns().forEach(col -> col.setAutoWidth(true));
grid.asSingleSelect().addValueChangeListener(event -> editRole(event.getValue())); grid.asSingleSelect().addValueChangeListener(event -> editPermission(event.getValue()));
} }
private void configureForm() { private void configureForm() {
form = new RoleForm(); form = new PermissionForm();
form.setWidth("25em"); form.setWidth("25em");
form.addSaveListener(this::saveRole); form.addSaveListener(this::savePermission);
form.addDeleteListener(this::deleteRole); form.addDeleteListener(this::deletePermission);
form.addCloseListener(e -> closeEditor()); form.addCloseListener(e -> closeEditor());
} }
private void saveRole(RoleForm.SaveEvent event) { private void savePermission(PermissionForm.SaveEvent event) {
service.saveRole(event.getRole()); service.savePermission(event.getPermission());
updateList(); updateList();
closeEditor(); closeEditor();
} }
private void deleteRole(RoleForm.DeleteEvent event) { private void deletePermission(PermissionForm.DeleteEvent event) {
service.deleteRole(event.getRole()); service.deletePermission(event.getPermission());
updateList(); updateList();
closeEditor(); closeEditor();
} }
@@ -85,34 +86,34 @@ public class RoleView extends VerticalLayout {
filterText.setClearButtonVisible(true); filterText.setClearButtonVisible(true);
filterText.setValueChangeMode(ValueChangeMode.LAZY); filterText.setValueChangeMode(ValueChangeMode.LAZY);
filterText.addValueChangeListener(e -> updateList()); 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); HorizontalLayout toolbar = new HorizontalLayout(filterText, addUserButton);
toolbar.addClassName("toolbar"); toolbar.addClassName("toolbar");
return toolbar; return toolbar;
} }
public void editRole(Role role) { public void editPermission(Permission permission) {
if (role == null) { if (permission == null) {
closeEditor(); closeEditor();
} else { } else {
form.setRole(role); form.setPermission(permission);
form.setVisible(true); form.setVisible(true);
addClassName("editing"); addClassName("editing");
} }
} }
public void closeEditor() { public void closeEditor() {
form.setRole(null); form.setPermission(null);
form.setVisible(false); form.setVisible(false);
removeClassName("editing"); removeClassName("editing");
} }
private void addUser() { private void addPermission() {
grid.asSingleSelect().clear(); grid.asSingleSelect().clear();
editRole(new Role()); editPermission(new Permission());
} }
private void updateList() { private void updateList() {
grid.setItems(service.findAllRoles(filterText.getValue())); grid.setItems(service.findAllPermissions(filterText.getValue()));
} }
} }
@@ -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<Permission> permissionList = new CheckboxGroup<>("Permissions");
Button save = new Button("Save");
Button delete = new Button("Delete");
Button close = new Button("Cancel");
Binder<Profile> binder = new BeanValidationBinder<>(Profile.class);
public ProfileForm() {
addClassName("profile-form");
binder.bindInstanceFields(this);
add(userName, password, email, firstName, lastName, enabled, configurePermissionsGroup(), createButtonsLayout());
}
private CheckboxGroup<Permission> 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<Permission> 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<ProfileForm> {
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<ProfileForm.DeleteEvent> listener) {
addListener(ProfileForm.DeleteEvent.class, listener);
}
public void addSaveListener(ComponentEventListener<ProfileForm.SaveEvent> listener) {
addListener(ProfileForm.SaveEvent.class, listener);
}
public void addCloseListener(ComponentEventListener<ProfileForm.CloseEvent> listener) {
addListener(ProfileForm.CloseEvent.class, listener);
}
}
@@ -10,8 +10,8 @@ import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.annotation.SpringComponent;
import de.thpeetz.kontor.admin.data.Role; import de.thpeetz.kontor.admin.data.Permission;
import de.thpeetz.kontor.admin.data.User; import de.thpeetz.kontor.admin.data.Profile;
import de.thpeetz.kontor.admin.services.KontorUserDetailsService; import de.thpeetz.kontor.admin.services.KontorUserDetailsService;
import de.thpeetz.kontor.common.views.MainLayout; import de.thpeetz.kontor.common.views.MainLayout;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
@@ -27,21 +27,21 @@ import java.util.stream.Collectors;
@SpringComponent @SpringComponent
@Scope("prototype") @Scope("prototype")
@RolesAllowed("ROLE_ADMIN") @RolesAllowed("ROLE_ADMIN")
@Route(value = "admin/user", layout = MainLayout.class) @Route(value = "admin/profile", layout = MainLayout.class)
@PageTitle("User | Admin | Kontor") @PageTitle("Profile | Admin | Kontor")
public class UserView extends VerticalLayout { public class ProfileView extends VerticalLayout {
Grid<User> grid = new Grid<>(User.class); Grid<Profile> grid = new Grid<>(Profile.class);
TextField filterText = new TextField(); TextField filterText = new TextField();
UserForm form; ProfileForm form;
KontorUserDetailsService service; KontorUserDetailsService service;
@Autowired @Autowired
PasswordEncoder passwordEncoder; PasswordEncoder passwordEncoder;
public UserView(KontorUserDetailsService service) { public ProfileView(KontorUserDetailsService service) {
this.service = service; this.service = service;
addClassName("user-view"); addClassName("profile-view");
setSizeFull(); setSizeFull();
configureGrid(); configureGrid();
configureForm(); configureForm();
@@ -51,38 +51,38 @@ public class UserView extends VerticalLayout {
} }
private void configureGrid() { private void configureGrid() {
grid.addClassName("user-grid"); grid.addClassName("profile-grid");
grid.setSizeFull(); grid.setSizeFull();
grid.setColumns("userName", "email", "firstName", "lastName", "enabled"); grid.setColumns("userName", "email", "firstName", "lastName", "enabled");
grid.getColumns().forEach(col -> col.setAutoWidth(true)); grid.getColumns().forEach(col -> col.setAutoWidth(true));
grid.asSingleSelect().addValueChangeListener(event -> editUser(event.getValue())); grid.asSingleSelect().addValueChangeListener(event -> editProfile(event.getValue()));
} }
private void configureForm() { private void configureForm() {
form = new UserForm(); form = new ProfileForm();
form.setWidth("25em"); form.setWidth("25em");
form.setVisible(false); form.setVisible(false);
form.addSaveListener(this::saveUser); form.addSaveListener(this::saveProfile);
form.addDeleteListener(this::deleteUser); form.addDeleteListener(this::deleteProfile);
form.addCloseListener(e -> closeEditor()); form.addCloseListener(e -> closeEditor());
} }
private void saveUser(UserForm.SaveEvent event) { private void saveProfile(ProfileForm.SaveEvent event) {
User user = event.getUser(); Profile profile = event.getProfile();
log.debug("UserView.saveUser: {}", user); log.debug("ProfileView.saveProfile: {}", profile);
List<Role> permissions = form.permissions.getSelectedItems().stream().collect(Collectors.toList()); List<Permission> permissions = form.permissionList.getSelectedItems().stream().collect(Collectors.toList());
log.info("selected permissions: {}", permissions); log.info("selected permissions: {}", permissions);
if (form.hasPasswordChanged(user)) { if (form.hasPasswordChanged(profile)) {
user.setPassword(passwordEncoder.encode(user.getPassword())); profile.setPassword(passwordEncoder.encode(profile.getPassword()));
log.debug("password changed for user {}", user); log.debug("password changed for profile {}", profile);
} }
service.saveUser(user, permissions); service.saveProfile(profile, permissions);
updateList(); updateList();
closeEditor(); closeEditor();
} }
private void deleteUser(UserForm.DeleteEvent event) { private void deleteProfile(ProfileForm.DeleteEvent event) {
service.deleteUser(event.getUser()); service.deleteProfile(event.getProfile());
updateList(); updateList();
closeEditor(); closeEditor();
} }
@@ -101,35 +101,35 @@ public class UserView extends VerticalLayout {
filterText.setClearButtonVisible(true); filterText.setClearButtonVisible(true);
filterText.setValueChangeMode(ValueChangeMode.LAZY); filterText.setValueChangeMode(ValueChangeMode.LAZY);
filterText.addValueChangeListener(e -> updateList()); filterText.addValueChangeListener(e -> updateList());
Button addUserButton = new Button("Add user", click -> addUser()); Button addProfileButton = new Button("Add profile", click -> addProfile());
HorizontalLayout toolbar = new HorizontalLayout(filterText, addUserButton); HorizontalLayout toolbar = new HorizontalLayout(filterText, addProfileButton);
toolbar.addClassName("toolbar"); toolbar.addClassName("toolbar");
return toolbar; return toolbar;
} }
public void editUser(User user) { public void editProfile(Profile profile) {
if (user == null) { if (profile == null) {
closeEditor(); closeEditor();
} else { } else {
form.setUser(user); form.setProfile(profile);
form.setRoles(service.findAllRoles(), user); form.setPermissions(service.findAllPermissions(), profile);
form.setVisible(true); form.setVisible(true);
addClassName("editing"); addClassName("editing");
} }
} }
public void closeEditor() { public void closeEditor() {
form.setUser(null); form.setProfile(null);
form.setVisible(false); form.setVisible(false);
removeClassName("editing"); removeClassName("editing");
} }
private void addUser() { private void addProfile() {
grid.asSingleSelect().clear(); grid.asSingleSelect().clear();
editUser(new User()); editProfile(new Profile());
} }
private void updateList() { private void updateList() {
grid.setItems(service.findAllUsers(filterText.getValue())); grid.setItems(service.findAllProfiles(filterText.getValue()));
} }
} }
@@ -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<Role> permissions = new CheckboxGroup<>("Permissions");
Button save = new Button("Save");
Button delete = new Button("Delete");
Button close = new Button("Cancel");
Binder<User> binder = new BeanValidationBinder<>(User.class);
public UserForm() {
addClassName("user-form");
binder.bindInstanceFields(this);
add(userName, password, email, firstName, lastName, enabled, configurePermissionsGroup(), createButtonsLayout());
}
private CheckboxGroup<Role> 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<Role> 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<UserForm> {
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<DeleteEvent> listener) {
addListener(DeleteEvent.class, listener);
}
public void addSaveListener(ComponentEventListener<SaveEvent> listener) {
addListener(SaveEvent.class, listener);
}
public void addCloseListener(ComponentEventListener<CloseEvent> listener) {
addListener(CloseEvent.class, listener);
}
}
@@ -10,7 +10,7 @@ import com.vaadin.flow.data.binder.BeanValidationBinder;
import com.vaadin.flow.data.binder.Binder; import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; 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.admin.services.AdminService;
import de.thpeetz.kontor.common.views.MainLayout; import de.thpeetz.kontor.common.views.MainLayout;
import de.thpeetz.kontor.security.SecurityService; import de.thpeetz.kontor.security.SecurityService;
@@ -32,7 +32,7 @@ public class UserProfileView extends VerticalLayout {
Button save = new Button("Save"); Button save = new Button("Save");
Button close = new Button("Cancel"); Button close = new Button("Cancel");
Binder<User> binder = new BeanValidationBinder<>(User.class); Binder<Profile> binder = new BeanValidationBinder<>(Profile.class);
public UserProfileView(AdminService adminService, SecurityService securityService) { public UserProfileView(AdminService adminService, SecurityService securityService) {
this.adminService = adminService; this.adminService = adminService;
@@ -42,7 +42,7 @@ public class UserProfileView extends VerticalLayout {
add(firstName, lastName, createButtonsLayout()); add(firstName, lastName, createButtonsLayout());
securityService.getAuthenticatedUser().ifPresent(user -> { securityService.getAuthenticatedUser().ifPresent(user -> {
log.info("UserProfileView: {}", user.getUsername()); log.info("UserProfileView: {}", user.getUsername());
binder.setBean(adminService.getUser(user.getUsername())); binder.setBean(adminService.getProfile(user.getUsername()));
}); });
} }
@@ -32,7 +32,7 @@ public class AvatarMenuBar extends Div {
log.info("AdminService: {}", adminService); log.info("AdminService: {}", adminService);
if (user != null) { if (user != null) {
String userName = user.getUsername(); String userName = user.getUsername();
String fullName = adminService.getUserFullName(userName); String fullName = adminService.getProfileFullName(userName);
avatar.setName(fullName); avatar.setName(fullName);
} }
}); });
@@ -23,7 +23,7 @@ public class SetupModuleMedia implements ApplicationListener<ContextRefreshedEve
@Override @Override
public void onApplicationEvent(ContextRefreshedEvent event) { public void onApplicationEvent(ContextRefreshedEvent event) {
adminService.addRole(MediaConstants.MEDIA_ROLE); adminService.addPermission(MediaConstants.MEDIA_ROLE);
if (alreadySetup) { if (alreadySetup) {
log.info("SetupModuleMedia already executed, skipping"); log.info("SetupModuleMedia already executed, skipping");
return; return;