use PostgreSQL for kontor-spring and kontor-api
This commit is contained in:
@@ -13,7 +13,7 @@ from sqlalchemy.orm import sessionmaker
|
|||||||
from src.db.models.tysc import Card, CardSet, Rooster, Team, FieldPosition, Player, Vendor, Sport
|
from src.db.models.tysc import Card, CardSet, Rooster, Team, FieldPosition, Player, Vendor, Sport
|
||||||
from src.db.models.comic import Issue, TradePaperback, StoryArc, Volume, ComicWork, Artist, Comic, Publisher, WorkType
|
from src.db.models.comic import Issue, TradePaperback, StoryArc, Volume, ComicWork, Artist, Comic, Publisher, WorkType
|
||||||
from src.db.models.bookshelf import ArticleAuthor, BookAuthor, BookshelfPublisher, Article, Book, Author
|
from src.db.models.bookshelf import ArticleAuthor, BookAuthor, BookshelfPublisher, Article, Book, Author
|
||||||
from src.db.models.admin import Mail, MailAccount, ModuleData, Role, User, Token, AuthorizationMatrix
|
from src.db.models.admin import Mail, MailAccount, ModuleData, Token, Assignment, Permission, Profile
|
||||||
from src.db.models.metadata import MetaDataTable, MetaDataColumn
|
from src.db.models.metadata import MetaDataTable, MetaDataColumn
|
||||||
from src.db.models.media import MediaVideo, MediaArticle, MediaFile, MediaActor, MediaActorFile
|
from src.db.models.media import MediaVideo, MediaArticle, MediaFile, MediaActor, MediaActorFile
|
||||||
|
|
||||||
@@ -79,10 +79,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
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
from sqlalchemy import Column, String, ForeignKey, Integer
|
from sqlalchemy import Column, String, ForeignKey, Integer, Boolean
|
||||||
from sqlalchemy.dialects.mysql import BIT
|
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
from src.db.models.base import Base, BaseMixin
|
from src.db.models.base import Base, BaseMixin
|
||||||
@@ -28,8 +27,8 @@ class MetaDataColumn(Base, BaseMixin):
|
|||||||
table = relationship("MetaDataTable", back_populates="table_columns")
|
table = relationship("MetaDataTable", back_populates="table_columns")
|
||||||
column_label = Column(String(255))
|
column_label = Column(String(255))
|
||||||
filter_label = Column(String(255))
|
filter_label = Column(String(255))
|
||||||
is_shown = Column(BIT(1))
|
is_shown = Column(Boolean)
|
||||||
show_filter = Column(BIT(1))
|
show_filter = Column(Boolean)
|
||||||
ref_column = Column(String, nullable=True)
|
ref_column = Column(String, nullable=True)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
"""
|
||||||
|
copy data from JSON to Postgres
|
||||||
|
"""
|
||||||
|
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
|
||||||
|
from pathlib import Path
|
||||||
|
from config import get_logger, get_database_cursors
|
||||||
|
import json
|
||||||
|
import psycopg2
|
||||||
|
from psycopg2.sql import SQL
|
||||||
|
|
||||||
|
parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
|
||||||
|
parser.add_argument('--verbose', '-v', action='count', default=0)
|
||||||
|
parser.add_argument('--config', '-c', default='kontor-docker')
|
||||||
|
parser.add_argument('--file', '-f', default='~/.sync/media/data.json')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
def copy_data(postgres_conn, data_file: Path, log):
|
||||||
|
postgres_cursor = postgres_conn.cursor()
|
||||||
|
import_file = Path(data_file)
|
||||||
|
if not import_file.exists():
|
||||||
|
log.info(f"File {data_file} does not exist. Do nothing.")
|
||||||
|
return
|
||||||
|
log.info("read json file")
|
||||||
|
with open(data_file, 'r') as json_file:
|
||||||
|
json_load = json.load(json_file)
|
||||||
|
for table in json_load:
|
||||||
|
log.info(f"{table}: {len(json_load[table])}")
|
||||||
|
# result[table] = import_table(table, json_load[table])
|
||||||
|
truncate_statement = 'TRUNCATE {}'.format(table)
|
||||||
|
#log.info(f"truncate: {truncate_statement}")
|
||||||
|
postgres_cursor.execute("SET FOREIGN_KEY_CHECKS = 0")
|
||||||
|
postgres_cursor.execute(truncate_statement)
|
||||||
|
items = json_load[table]
|
||||||
|
for item in items:
|
||||||
|
#log.info(f"item: {item}")
|
||||||
|
values = []
|
||||||
|
columns = []
|
||||||
|
for (key, value) in item.items():
|
||||||
|
columns.append(key)
|
||||||
|
values.append(value)
|
||||||
|
row = tuple(values)
|
||||||
|
log.info(f"values: {row}")
|
||||||
|
insert_statement = 'INSERT INTO {}({}) VALUES({})'.format(table, ', '.join(columns), ', '.join(['%s']*len(columns)))
|
||||||
|
#log.info(f"statement: {insert_statement}")
|
||||||
|
postgres_cursor.execute(SQL(insert_statement), row)
|
||||||
|
try:
|
||||||
|
postgres_conn.commit()
|
||||||
|
except psycopg2.Error as error:
|
||||||
|
log.info('insert failed with %s', error)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
logger = get_logger(args.verbose, args.config)
|
||||||
|
logger.info('kontor.json_to_postgres started')
|
||||||
|
_, _, p_conn = get_database_cursors(logger, args.config)
|
||||||
|
copy_data(p_conn, args.file, logger)
|
||||||
|
p_conn.close()
|
||||||
|
logger.info('kontor.json_to_postgres finished')
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
FROM alpine/java:21-jdk
|
FROM alpine/java:21-jdk
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
ADD build/libs/kontor-spring-0.1.0-SNAPSHOT.jar app.jar
|
ADD build/libs/kontor-spring-0.2.0-SNAPSHOT.jar app.jar
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
CMD ["java", "-jar", "-Dspring.profiles.active=prod", "-Dvaadin.productionMode=true", "app.jar"]
|
CMD ["java", "-jar", "-Dspring.profiles.active=prod", "-Dvaadin.productionMode=true", "app.jar"]
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
package de.thpeetz.kontor.admin.data;
|
|
||||||
|
|
||||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Entity
|
|
||||||
public class AuthorizationMatrix extends AbstractEntity {
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "user_id")
|
|
||||||
@NotNull
|
|
||||||
private User user;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "role_id")
|
|
||||||
@NotNull
|
|
||||||
private Role role;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
final StringBuffer sb = new StringBuffer("AuthorizationMatrix{");
|
|
||||||
sb.append("user=").append(user.getUserName());
|
|
||||||
sb.append(", role=").append(role.getName());
|
|
||||||
sb.append('}');
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package de.thpeetz.kontor.admin.data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.OneToMany;
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
@Entity
|
|
||||||
public class Role extends AbstractEntity {
|
|
||||||
|
|
||||||
@NotEmpty
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "role")
|
|
||||||
@Nullable
|
|
||||||
private List<AuthorizationMatrix> matrix;
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
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.validation.constraints.NotEmpty;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
@Entity
|
|
||||||
@Table(indexes = @Index(columnList = "userName"), uniqueConstraints = @UniqueConstraint(columnNames = {"userName"}))
|
|
||||||
public class User extends AbstractEntity {
|
|
||||||
|
|
||||||
private String firstName;
|
|
||||||
|
|
||||||
private String lastName;
|
|
||||||
|
|
||||||
@NotEmpty
|
|
||||||
private String userName;
|
|
||||||
|
|
||||||
private String email;
|
|
||||||
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
private boolean enabled;
|
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
|
|
||||||
@Nullable
|
|
||||||
private List<AuthorizationMatrix> matrix = new LinkedList<>();
|
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
|
|
||||||
@Nullable
|
|
||||||
private List<Token> tokens = new LinkedList<>();
|
|
||||||
|
|
||||||
public String getFullName() {
|
|
||||||
StringBuilder fullNamBuilder = new StringBuilder();
|
|
||||||
if (firstName != null) {
|
|
||||||
fullNamBuilder.append(firstName);
|
|
||||||
}
|
|
||||||
if (lastName != null) {
|
|
||||||
if (fullNamBuilder.length() > 0) {
|
|
||||||
fullNamBuilder.append(" ");
|
|
||||||
}
|
|
||||||
fullNamBuilder.append(lastName);
|
|
||||||
}
|
|
||||||
return fullNamBuilder.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-15
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
package de.thpeetz.kontor.admin.views;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
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.combobox.ComboBox;
|
|
||||||
import com.vaadin.flow.component.formlayout.FormLayout;
|
|
||||||
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 lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class AuthorizationForm extends FormLayout {
|
|
||||||
|
|
||||||
ComboBox<User> user = new ComboBox<>("User");
|
|
||||||
ComboBox<Role> role = new ComboBox<>("Role");
|
|
||||||
|
|
||||||
Button save = new Button("Save");
|
|
||||||
Button delete = new Button("Delete");
|
|
||||||
Button close = new Button("Cancel");
|
|
||||||
|
|
||||||
Binder<AuthorizationMatrix> binder = new BeanValidationBinder<>(AuthorizationMatrix.class);
|
|
||||||
|
|
||||||
public AuthorizationForm(List<User> users, List<Role> roles) {
|
|
||||||
addClassName("authorizationmatrix-form");
|
|
||||||
binder.bindInstanceFields(this);
|
|
||||||
|
|
||||||
user.setItems(users);
|
|
||||||
user.setItemLabelGenerator(User::getUserName);
|
|
||||||
role.setItems(roles);
|
|
||||||
role.setItemLabelGenerator(Role::getName);
|
|
||||||
add(user, role, createButtonsLayout());
|
|
||||||
}
|
|
||||||
|
|
||||||
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 setAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) {
|
|
||||||
binder.setBean(authorizationMatrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract static class AuthorizationFormEvent extends ComponentEvent<AuthorizationForm> {
|
|
||||||
private AuthorizationMatrix authorizationMatrix;
|
|
||||||
|
|
||||||
protected AuthorizationFormEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) {
|
|
||||||
super(source, false);
|
|
||||||
this.authorizationMatrix = authorizationMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthorizationMatrix getAuthorizationMatrix() {
|
|
||||||
return authorizationMatrix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SaveEvent extends AuthorizationFormEvent {
|
|
||||||
SaveEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) {
|
|
||||||
super(source, authorizationMatrix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DeleteEvent extends AuthorizationFormEvent {
|
|
||||||
DeleteEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) {
|
|
||||||
super(source, authorizationMatrix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class CloseEvent extends AuthorizationFormEvent {
|
|
||||||
CloseEvent(AuthorizationForm 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
package de.thpeetz.kontor.admin.views;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Scope;
|
|
||||||
|
|
||||||
import com.vaadin.flow.component.Component;
|
|
||||||
import com.vaadin.flow.component.button.Button;
|
|
||||||
import com.vaadin.flow.component.grid.Grid;
|
|
||||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
|
||||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
|
||||||
|
|
||||||
import com.vaadin.flow.router.PageTitle;
|
|
||||||
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;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@SpringComponent
|
|
||||||
@Scope("prototype")
|
|
||||||
@RolesAllowed("ROLE_ADMIN")
|
|
||||||
@Route(value = AdminConstants.AUTHORIZATION_ROUTE, layout = MainLayout.class)
|
|
||||||
@PageTitle("Authorization | Admin | Kontor")
|
|
||||||
public class AuthorizationView extends VerticalLayout {
|
|
||||||
|
|
||||||
Grid<AuthorizationMatrix> grid = new Grid<>(AuthorizationMatrix.class);
|
|
||||||
AuthorizationForm form;
|
|
||||||
AdminService service;
|
|
||||||
|
|
||||||
public AuthorizationView(AdminService service) {
|
|
||||||
this.service = service;
|
|
||||||
addClassName("authoriaztionmatrix-view");
|
|
||||||
setSizeFull();
|
|
||||||
configureGrid();
|
|
||||||
configureForm();
|
|
||||||
|
|
||||||
add(getToolbar(), getContent());
|
|
||||||
updateList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureGrid() {
|
|
||||||
grid.addClassName("authorizationmatrix-grid");
|
|
||||||
grid.setSizeFull();
|
|
||||||
grid.setColumns("user.userName", "role.name");
|
|
||||||
grid.getColumns().forEach(col -> col.setAutoWidth(true));
|
|
||||||
grid.asSingleSelect().addValueChangeListener(event -> editAuthorizationMatrix(event.getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureForm() {
|
|
||||||
form = new AuthorizationForm(service.findAllUsers(), service.findAllRoles());
|
|
||||||
form.setWidth("25em");
|
|
||||||
form.addSaveListener(this::saveAuthorizationMatrix);
|
|
||||||
form.addDeleteListener(this::deleteAuthorizationMatrix);
|
|
||||||
form.addCloseListener(e -> closeEditor());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveAuthorizationMatrix(AuthorizationForm.SaveEvent event) {
|
|
||||||
AuthorizationMatrix authorizationMatrix = event.getAuthorizationMatrix();
|
|
||||||
service.saveAuthorizationMatrix(authorizationMatrix);
|
|
||||||
updateList();
|
|
||||||
closeEditor();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteAuthorizationMatrix(AuthorizationForm.DeleteEvent event) {
|
|
||||||
service.deleteAuthorizationMatrix(event.getAuthorizationMatrix());
|
|
||||||
updateList();
|
|
||||||
closeEditor();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Component getContent() {
|
|
||||||
HorizontalLayout content = new HorizontalLayout(grid, form);
|
|
||||||
content.setFlexGrow(2, grid);
|
|
||||||
content.setFlexGrow(1, form);
|
|
||||||
content.addClassName("content");
|
|
||||||
content.setSizeFull();
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HorizontalLayout getToolbar() {
|
|
||||||
Button addAuthorizationMaxtrixButton = new Button("Add permssion", click -> addAuthorizationMatrix());
|
|
||||||
HorizontalLayout toolbar = new HorizontalLayout(addAuthorizationMaxtrixButton);
|
|
||||||
toolbar.addClassName("toolbar");
|
|
||||||
return toolbar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void editAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) {
|
|
||||||
if (authorizationMatrix == null) {
|
|
||||||
closeEditor();
|
|
||||||
} else {
|
|
||||||
form.setAuthorizationMatrix(authorizationMatrix);
|
|
||||||
form.setVisible(true);
|
|
||||||
addClassName("editing");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closeEditor() {
|
|
||||||
form.setAuthorizationMatrix(null);
|
|
||||||
form.setVisible(false);
|
|
||||||
removeClassName("editing");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addAuthorizationMatrix() {
|
|
||||||
grid.asSingleSelect().clear();
|
|
||||||
editAuthorizationMatrix(new AuthorizationMatrix());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateList() {
|
|
||||||
grid.setItems(service.findAllAuthorizationMatrices());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +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.formlayout.FormLayout;
|
|
||||||
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 lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class RoleForm extends FormLayout {
|
|
||||||
|
|
||||||
TextField name = new TextField("Role name");
|
|
||||||
|
|
||||||
Button save = new Button("Save");
|
|
||||||
Button delete = new Button("Delete");
|
|
||||||
Button close = new Button("Cancel");
|
|
||||||
|
|
||||||
Binder<Role> binder = new BeanValidationBinder<>(Role.class);
|
|
||||||
|
|
||||||
public RoleForm() {
|
|
||||||
addClassName("role-form");
|
|
||||||
binder.bindInstanceFields(this);
|
|
||||||
add(name, createButtonsLayout());
|
|
||||||
}
|
|
||||||
|
|
||||||
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 setRole(Role role) {
|
|
||||||
binder.setBean(role);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract static class RoleFormEvent extends ComponentEvent<RoleForm> {
|
|
||||||
private Role role;
|
|
||||||
|
|
||||||
protected RoleFormEvent(RoleForm source, Role role) {
|
|
||||||
super(source, false);
|
|
||||||
this.role = role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Role getRole() {
|
|
||||||
return role;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SaveEvent extends RoleFormEvent {
|
|
||||||
SaveEvent(RoleForm source, Role role) {
|
|
||||||
super(source, role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DeleteEvent extends RoleFormEvent {
|
|
||||||
DeleteEvent(RoleForm source, Role role) {
|
|
||||||
super(source, role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class CloseEvent extends RoleFormEvent {
|
|
||||||
CloseEvent(RoleForm 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
package de.thpeetz.kontor.admin.views;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Scope;
|
|
||||||
|
|
||||||
import com.vaadin.flow.component.Component;
|
|
||||||
import com.vaadin.flow.component.button.Button;
|
|
||||||
import com.vaadin.flow.component.grid.Grid;
|
|
||||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
|
||||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
|
||||||
import com.vaadin.flow.component.textfield.TextField;
|
|
||||||
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.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;
|
|
||||||
import lombok.extern.slf4j.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<Role> grid = new Grid<>(Role.class);
|
|
||||||
TextField filterText = new TextField();
|
|
||||||
RoleForm form;
|
|
||||||
AdminService service;
|
|
||||||
|
|
||||||
public RoleView(AdminService service) {
|
|
||||||
this.service = service;
|
|
||||||
addClassName("user-view");
|
|
||||||
setSizeFull();
|
|
||||||
configureGrid();
|
|
||||||
configureForm();
|
|
||||||
|
|
||||||
add(getToolbar(), getContent());
|
|
||||||
updateList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureGrid() {
|
|
||||||
grid.addClassName("user-grid");
|
|
||||||
grid.setSizeFull();
|
|
||||||
grid.setColumns("name");
|
|
||||||
grid.getColumns().forEach(col -> col.setAutoWidth(true));
|
|
||||||
grid.asSingleSelect().addValueChangeListener(event -> editRole(event.getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureForm() {
|
|
||||||
form = new RoleForm();
|
|
||||||
form.setWidth("25em");
|
|
||||||
form.addSaveListener(this::saveRole);
|
|
||||||
form.addDeleteListener(this::deleteRole);
|
|
||||||
form.addCloseListener(e -> closeEditor());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveRole(RoleForm.SaveEvent event) {
|
|
||||||
service.saveRole(event.getRole());
|
|
||||||
updateList();
|
|
||||||
closeEditor();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteRole(RoleForm.DeleteEvent event) {
|
|
||||||
service.deleteRole(event.getRole());
|
|
||||||
updateList();
|
|
||||||
closeEditor();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Component getContent() {
|
|
||||||
HorizontalLayout content = new HorizontalLayout(grid, form);
|
|
||||||
content.setFlexGrow(2, grid);
|
|
||||||
content.setFlexGrow(1, form);
|
|
||||||
content.addClassName("content");
|
|
||||||
content.setSizeFull();
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HorizontalLayout getToolbar() {
|
|
||||||
filterText.setPlaceholder("Filter by user name...");
|
|
||||||
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);
|
|
||||||
toolbar.addClassName("toolbar");
|
|
||||||
return toolbar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void editRole(Role role) {
|
|
||||||
if (role == null) {
|
|
||||||
closeEditor();
|
|
||||||
} else {
|
|
||||||
form.setRole(role);
|
|
||||||
form.setVisible(true);
|
|
||||||
addClassName("editing");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closeEditor() {
|
|
||||||
form.setRole(null);
|
|
||||||
form.setVisible(false);
|
|
||||||
removeClassName("editing");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addUser() {
|
|
||||||
grid.asSingleSelect().clear();
|
|
||||||
editRole(new Role());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateList() {
|
|
||||||
grid.setItems(service.findAllRoles(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
package de.thpeetz.kontor.admin.views;
|
|
||||||
|
|
||||||
import com.vaadin.flow.component.Component;
|
|
||||||
import com.vaadin.flow.component.button.Button;
|
|
||||||
import com.vaadin.flow.component.grid.Grid;
|
|
||||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
|
||||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
|
||||||
import com.vaadin.flow.component.textfield.TextField;
|
|
||||||
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.services.KontorUserDetailsService;
|
|
||||||
import de.thpeetz.kontor.common.views.MainLayout;
|
|
||||||
import jakarta.annotation.security.RolesAllowed;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Scope;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@SpringComponent
|
|
||||||
@Scope("prototype")
|
|
||||||
@RolesAllowed("ROLE_ADMIN")
|
|
||||||
@Route(value = "admin/user", layout = MainLayout.class)
|
|
||||||
@PageTitle("User | Admin | Kontor")
|
|
||||||
public class UserView extends VerticalLayout {
|
|
||||||
|
|
||||||
Grid<User> grid = new Grid<>(User.class);
|
|
||||||
TextField filterText = new TextField();
|
|
||||||
UserForm form;
|
|
||||||
KontorUserDetailsService service;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
PasswordEncoder passwordEncoder;
|
|
||||||
|
|
||||||
public UserView(KontorUserDetailsService service) {
|
|
||||||
this.service = service;
|
|
||||||
addClassName("user-view");
|
|
||||||
setSizeFull();
|
|
||||||
configureGrid();
|
|
||||||
configureForm();
|
|
||||||
|
|
||||||
add(getToolbar(), getContent());
|
|
||||||
updateList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureGrid() {
|
|
||||||
grid.addClassName("user-grid");
|
|
||||||
grid.setSizeFull();
|
|
||||||
grid.setColumns("userName", "email", "firstName", "lastName", "enabled");
|
|
||||||
grid.getColumns().forEach(col -> col.setAutoWidth(true));
|
|
||||||
grid.asSingleSelect().addValueChangeListener(event -> editUser(event.getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureForm() {
|
|
||||||
form = new UserForm();
|
|
||||||
form.setWidth("25em");
|
|
||||||
form.setVisible(false);
|
|
||||||
form.addSaveListener(this::saveUser);
|
|
||||||
form.addDeleteListener(this::deleteUser);
|
|
||||||
form.addCloseListener(e -> closeEditor());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveUser(UserForm.SaveEvent event) {
|
|
||||||
User user = event.getUser();
|
|
||||||
log.debug("UserView.saveUser: {}", user);
|
|
||||||
List<Role> permissions = form.permissions.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);
|
|
||||||
}
|
|
||||||
service.saveUser(user, permissions);
|
|
||||||
updateList();
|
|
||||||
closeEditor();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteUser(UserForm.DeleteEvent event) {
|
|
||||||
service.deleteUser(event.getUser());
|
|
||||||
updateList();
|
|
||||||
closeEditor();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Component getContent() {
|
|
||||||
HorizontalLayout content = new HorizontalLayout(grid, form);
|
|
||||||
content.setFlexGrow(2, grid);
|
|
||||||
content.setFlexGrow(1, form);
|
|
||||||
content.addClassName("content");
|
|
||||||
content.setSizeFull();
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HorizontalLayout getToolbar() {
|
|
||||||
filterText.setPlaceholder("Filter by user name...");
|
|
||||||
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);
|
|
||||||
toolbar.addClassName("toolbar");
|
|
||||||
return toolbar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void editUser(User user) {
|
|
||||||
if (user == null) {
|
|
||||||
closeEditor();
|
|
||||||
} else {
|
|
||||||
form.setUser(user);
|
|
||||||
form.setRoles(service.findAllRoles(), user);
|
|
||||||
form.setVisible(true);
|
|
||||||
addClassName("editing");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closeEditor() {
|
|
||||||
form.setUser(null);
|
|
||||||
form.setVisible(false);
|
|
||||||
removeClassName("editing");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addUser() {
|
|
||||||
grid.asSingleSelect().clear();
|
|
||||||
editUser(new User());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateList() {
|
|
||||||
grid.setItems(service.findAllUsers(filterText.getValue()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user