Erweiterungen
This commit is contained in:
28
pom.xml
28
pom.xml
@@ -12,6 +12,9 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>21</java.version>
|
<java.version>21</java.version>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<maven.compiler.release>21</maven.compiler.release>
|
||||||
<vaadin.version>24.7.0</vaadin.version>
|
<vaadin.version>24.7.0</vaadin.version>
|
||||||
<archunit.version>1.3.0</archunit.version>
|
<archunit.version>1.3.0</archunit.version>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -67,10 +70,16 @@
|
|||||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Security Dependencies -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>1.18.30</version>
|
<version>1.18.38</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@@ -82,6 +91,23 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.11.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>21</source>
|
||||||
|
<target>21</target>
|
||||||
|
<release>21</release>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.38</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.diffplug.spotless</groupId>
|
<groupId>com.diffplug.spotless</groupId>
|
||||||
<artifactId>spotless-maven-plugin</artifactId>
|
<artifactId>spotless-maven-plugin</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package de.assecutor.votianlt.config;
|
||||||
|
|
||||||
|
import de.assecutor.votianlt.model.User;
|
||||||
|
import de.assecutor.votianlt.repository.UserRepository;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DataInitializer implements CommandLineRunner {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(DataInitializer.class);
|
||||||
|
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
public DataInitializer(UserRepository userRepository, PasswordEncoder passwordEncoder) {
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
this.passwordEncoder = passwordEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... args) throws Exception {
|
||||||
|
initializeTestUsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeTestUsers() {
|
||||||
|
log.info("Initializing test users...");
|
||||||
|
|
||||||
|
// Admin User
|
||||||
|
if (!userRepository.existsByEmail("admin@votianlt.de")) {
|
||||||
|
User adminUser = new User();
|
||||||
|
adminUser.setEmail("admin@votianlt.de");
|
||||||
|
adminUser.setPassword(passwordEncoder.encode("admin123"));
|
||||||
|
adminUser.setName("Administrator");
|
||||||
|
adminUser.setFirstname("Admin");
|
||||||
|
adminUser.setIsActivated((byte) 1);
|
||||||
|
adminUser.setIsEmailConfirmed((byte) 1);
|
||||||
|
adminUser.setCreatedAt(LocalDateTime.now());
|
||||||
|
adminUser.setUpdatedAt(LocalDateTime.now());
|
||||||
|
adminUser.setRoles(Set.of("USER", "ADMIN"));
|
||||||
|
|
||||||
|
userRepository.save(adminUser);
|
||||||
|
log.info("Created admin user: admin@votianlt.de / admin123");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test User
|
||||||
|
if (!userRepository.existsByEmail("test@votianlt.de")) {
|
||||||
|
User testUser = new User();
|
||||||
|
testUser.setEmail("test@votianlt.de");
|
||||||
|
testUser.setPassword(passwordEncoder.encode("test123"));
|
||||||
|
testUser.setName("Testmann");
|
||||||
|
testUser.setFirstname("Test");
|
||||||
|
testUser.setIsActivated((byte) 1);
|
||||||
|
testUser.setIsEmailConfirmed((byte) 1);
|
||||||
|
testUser.setCreatedAt(LocalDateTime.now());
|
||||||
|
testUser.setUpdatedAt(LocalDateTime.now());
|
||||||
|
testUser.setRoles(Set.of("USER"));
|
||||||
|
|
||||||
|
userRepository.save(testUser);
|
||||||
|
log.info("Created test user: test@votianlt.de / test123");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Demo User
|
||||||
|
if (!userRepository.existsByEmail("demo@votianlt.de")) {
|
||||||
|
User demoUser = new User();
|
||||||
|
demoUser.setEmail("demo@votianlt.de");
|
||||||
|
demoUser.setPassword(passwordEncoder.encode("demo123"));
|
||||||
|
demoUser.setName("Demouser");
|
||||||
|
demoUser.setFirstname("Demo");
|
||||||
|
demoUser.setIsActivated((byte) 1);
|
||||||
|
demoUser.setIsEmailConfirmed((byte) 1);
|
||||||
|
demoUser.setCreatedAt(LocalDateTime.now());
|
||||||
|
demoUser.setUpdatedAt(LocalDateTime.now());
|
||||||
|
demoUser.setRoles(Set.of("USER"));
|
||||||
|
|
||||||
|
userRepository.save(demoUser);
|
||||||
|
log.info("Created demo user: demo@votianlt.de / demo123");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Test users initialization completed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,12 +6,12 @@ import org.bson.types.ObjectId;
|
|||||||
@Data
|
@Data
|
||||||
public class Company
|
public class Company
|
||||||
{
|
{
|
||||||
public ObjectId id;
|
private ObjectId id;
|
||||||
|
|
||||||
public String name;
|
private String name;
|
||||||
public String street;
|
private String street;
|
||||||
public String houseNumber;
|
private String houseNumber;
|
||||||
public String addressAddition;
|
private String addressAddition;
|
||||||
public String zip;
|
private String zip;
|
||||||
public String city;
|
private String city;
|
||||||
}
|
}
|
||||||
@@ -7,17 +7,16 @@ import org.bson.types.ObjectId;
|
|||||||
public class Customer
|
public class Customer
|
||||||
{
|
{
|
||||||
private ObjectId id;
|
private ObjectId id;
|
||||||
|
private String title;
|
||||||
public String title;
|
private String companyName;
|
||||||
public String companyName;
|
private String firstname;
|
||||||
public String firstname;
|
private String lastName;
|
||||||
public String lastName;
|
private String telephone;
|
||||||
public String telephone;
|
private String fax;
|
||||||
public String fax;
|
private String mail;
|
||||||
public String mail;
|
private String street;
|
||||||
public String street;
|
private String houseNumber;
|
||||||
public String houseNumber;
|
private String addressAddition;
|
||||||
public String addressAddition;
|
private String zip;
|
||||||
public String zip;
|
private String city;
|
||||||
public String city;
|
|
||||||
}
|
}
|
||||||
42
src/main/java/de/assecutor/votianlt/model/Job.java
Normal file
42
src/main/java/de/assecutor/votianlt/model/Job.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package de.assecutor.votianlt.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Job {
|
||||||
|
private ObjectId id;
|
||||||
|
|
||||||
|
// Auftraggeber/Rechnungsempfänger
|
||||||
|
private String customerSelection; // Kunde01 | KOTVor K01Nach
|
||||||
|
|
||||||
|
// Abholadresse
|
||||||
|
private String pickupCompany;
|
||||||
|
private String pickupSalutation;
|
||||||
|
private String pickupFirstName;
|
||||||
|
private String pickupLastName;
|
||||||
|
private String pickupPhone;
|
||||||
|
private String pickupStreet;
|
||||||
|
private String pickupHouseNumber;
|
||||||
|
private String pickupAddressAddition;
|
||||||
|
private String pickupZip;
|
||||||
|
private String pickupCity;
|
||||||
|
private boolean savePickupAddress;
|
||||||
|
|
||||||
|
// Lieferadresse
|
||||||
|
private String deliveryCompany;
|
||||||
|
private String deliverySalutation;
|
||||||
|
private String deliveryFirstName;
|
||||||
|
private String deliveryLastName;
|
||||||
|
private String deliveryPhone;
|
||||||
|
private String deliveryStreet;
|
||||||
|
private String deliveryHouseNumber;
|
||||||
|
private String deliveryAddressAddition;
|
||||||
|
private String deliveryZip;
|
||||||
|
private String deliveryCity;
|
||||||
|
private boolean saveDeliveryAddress;
|
||||||
|
|
||||||
|
// Digitale Abwicklung per App
|
||||||
|
private boolean digitalProcessing;
|
||||||
|
private String appUser;
|
||||||
|
}
|
||||||
@@ -1,28 +1,45 @@
|
|||||||
package de.assecutor.votianlt.model;
|
package de.assecutor.votianlt.model;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.springframework.data.annotation.Id;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
import org.springframework.data.mongodb.core.index.Indexed;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class User
|
@Document(collection = "users")
|
||||||
{
|
public class User {
|
||||||
public int usrId;
|
|
||||||
public int hqId;
|
@Id
|
||||||
public short type;
|
private String id;
|
||||||
public String title;
|
|
||||||
public String name;
|
private int usrId;
|
||||||
public String firstname;
|
private int hqId;
|
||||||
public java.sql.Date birthdate;
|
private short type;
|
||||||
public String email;
|
private String title;
|
||||||
public String invitationEmail;
|
private String name;
|
||||||
public String phone;
|
private String firstname;
|
||||||
public String phone2;
|
private LocalDate birthdate;
|
||||||
public String fax;
|
|
||||||
public String password;
|
@Indexed(unique = true)
|
||||||
public byte isActivated;
|
private String email;
|
||||||
public String activationCode;
|
|
||||||
public byte isEmailConfirmed;
|
private String invitationEmail;
|
||||||
public byte isPasswordLost;
|
private String phone;
|
||||||
public String passwordCode;
|
private String phone2;
|
||||||
public int passwordTimestamp;
|
private String fax;
|
||||||
public long activationDate;
|
private String password;
|
||||||
|
private byte isActivated;
|
||||||
|
private String activationCode;
|
||||||
|
private byte isEmailConfirmed;
|
||||||
|
private byte isPasswordLost;
|
||||||
|
private String passwordCode;
|
||||||
|
private LocalDateTime passwordTimestamp;
|
||||||
|
private LocalDateTime activationDate;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
private Set<String> roles;
|
||||||
}
|
}
|
||||||
@@ -16,11 +16,13 @@ import de.assecutor.votianlt.model.Company;
|
|||||||
import de.assecutor.votianlt.pages.add_company.service.AddCompanyService;
|
import de.assecutor.votianlt.pages.add_company.service.AddCompanyService;
|
||||||
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
|
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
|
||||||
|
|
||||||
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
|
|
||||||
@Route("add_company")
|
@Route(value = "add_company", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||||
@PageTitle("Neuen Firma anlegen")
|
@PageTitle("Neuen Firma anlegen")
|
||||||
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Neue Firma anlegen")
|
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Neue Firma anlegen")
|
||||||
|
@RolesAllowed("USER")
|
||||||
public class AddCompanyView extends Main {
|
public class AddCompanyView extends Main {
|
||||||
private final AddCompanyService addCompanyService;
|
private final AddCompanyService addCompanyService;
|
||||||
|
|
||||||
@@ -82,7 +84,7 @@ public class AddCompanyView extends Main {
|
|||||||
|
|
||||||
private void submit() {
|
private void submit() {
|
||||||
Company company = new Company();
|
Company company = new Company();
|
||||||
company.name = companyName.getValue();
|
company.setName(companyName.getValue());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
binder.writeBean(company);
|
binder.writeBean(company);
|
||||||
|
|||||||
@@ -16,11 +16,13 @@ import de.assecutor.votianlt.model.Customer;
|
|||||||
import de.assecutor.votianlt.pages.add_customer.service.AddCustomerService;
|
import de.assecutor.votianlt.pages.add_customer.service.AddCustomerService;
|
||||||
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
|
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
|
||||||
|
|
||||||
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
|
|
||||||
@Route("add_customer")
|
@Route(value = "add_customer", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||||
@PageTitle("Neuen Kunden anlegen")
|
@PageTitle("Neuen Kunden anlegen")
|
||||||
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Neuen Kunden anlegen")
|
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Neuen Kunden anlegen")
|
||||||
|
@RolesAllowed("USER")
|
||||||
public class AddCustomerView extends Main {
|
public class AddCustomerView extends Main {
|
||||||
private final AddCustomerService addCustomerService;
|
private final AddCustomerService addCustomerService;
|
||||||
|
|
||||||
@@ -82,7 +84,7 @@ public class AddCustomerView extends Main {
|
|||||||
|
|
||||||
private void submit() {
|
private void submit() {
|
||||||
Customer customer = new Customer();
|
Customer customer = new Customer();
|
||||||
customer.companyName = companyName.getValue();
|
customer.setCompanyName(companyName.getValue());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
binder.writeBean(customer);
|
binder.writeBean(customer);
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package de.assecutor.votianlt.pages.add_job.service;
|
||||||
|
|
||||||
|
import de.assecutor.votianlt.model.Job;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class AddJobService {
|
||||||
|
|
||||||
|
public void addJob(Job job) {
|
||||||
|
// TODO: Implement job persistence logic
|
||||||
|
System.out.println("Job would be saved: " + job.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,353 @@
|
|||||||
|
package de.assecutor.votianlt.pages.add_job.ui.view;
|
||||||
|
|
||||||
|
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.combobox.ComboBox;
|
||||||
|
import com.vaadin.flow.component.html.Div;
|
||||||
|
import com.vaadin.flow.component.html.H3;
|
||||||
|
import com.vaadin.flow.component.html.Main;
|
||||||
|
import com.vaadin.flow.component.html.Span;
|
||||||
|
import com.vaadin.flow.component.icon.Icon;
|
||||||
|
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||||
|
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.binder.Binder;
|
||||||
|
import com.vaadin.flow.data.binder.ValidationException;
|
||||||
|
import com.vaadin.flow.router.Menu;
|
||||||
|
import com.vaadin.flow.router.PageTitle;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||||
|
import de.assecutor.votianlt.model.Job;
|
||||||
|
import de.assecutor.votianlt.pages.add_job.service.AddJobService;
|
||||||
|
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
|
||||||
|
|
||||||
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
|
|
||||||
|
@Route(value = "add_job", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||||
|
@PageTitle("Neuen Auftrag anlegen")
|
||||||
|
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Neuen Auftrag anlegen")
|
||||||
|
@RolesAllowed("USER")
|
||||||
|
public class AddJobView extends Main {
|
||||||
|
|
||||||
|
private final AddJobService addJobService;
|
||||||
|
|
||||||
|
// Customer selection
|
||||||
|
private ComboBox<String> customerSelection;
|
||||||
|
private Button preloadAddressButton;
|
||||||
|
|
||||||
|
// Required fields notice
|
||||||
|
private Span requiredFieldsNotice;
|
||||||
|
|
||||||
|
// Pickup address fields
|
||||||
|
private TextField pickupCompany;
|
||||||
|
private ComboBox<String> pickupSalutation;
|
||||||
|
private TextField pickupFirstName;
|
||||||
|
private TextField pickupLastName;
|
||||||
|
private TextField pickupPhone;
|
||||||
|
private TextField pickupStreet;
|
||||||
|
private TextField pickupHouseNumber;
|
||||||
|
private TextField pickupAddressAddition;
|
||||||
|
private TextField pickupZip;
|
||||||
|
private TextField pickupCity;
|
||||||
|
private Checkbox savePickupAddress;
|
||||||
|
|
||||||
|
// Delivery address fields
|
||||||
|
private TextField deliveryCompany;
|
||||||
|
private ComboBox<String> deliverySalutation;
|
||||||
|
private TextField deliveryFirstName;
|
||||||
|
private TextField deliveryLastName;
|
||||||
|
private TextField deliveryPhone;
|
||||||
|
private TextField deliveryStreet;
|
||||||
|
private TextField deliveryHouseNumber;
|
||||||
|
private TextField deliveryAddressAddition;
|
||||||
|
private TextField deliveryZip;
|
||||||
|
private TextField deliveryCity;
|
||||||
|
private Checkbox saveDeliveryAddress;
|
||||||
|
|
||||||
|
// Digital processing
|
||||||
|
private Checkbox digitalProcessing;
|
||||||
|
private ComboBox<String> appUser;
|
||||||
|
|
||||||
|
// Submit button
|
||||||
|
private Button submitButton;
|
||||||
|
|
||||||
|
private final Binder<Job> binder = new Binder<>(Job.class);
|
||||||
|
|
||||||
|
public AddJobView(AddJobService addJobService) {
|
||||||
|
this.addJobService = addJobService;
|
||||||
|
initializeComponents();
|
||||||
|
setupLayout();
|
||||||
|
setupValidation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeComponents() {
|
||||||
|
// Customer selection
|
||||||
|
customerSelection = new ComboBox<>("Auftraggeber/Rechnungsempfänger");
|
||||||
|
customerSelection.setItems("Kunde01 | KOTVor K01Nach");
|
||||||
|
customerSelection.setValue("Kunde01 | KOTVor K01Nach");
|
||||||
|
customerSelection.setWidthFull();
|
||||||
|
|
||||||
|
preloadAddressButton = new Button("Vorbelegte Adressfelder leeren");
|
||||||
|
preloadAddressButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
preloadAddressButton.setIcon(new Icon(VaadinIcon.QUESTION_CIRCLE));
|
||||||
|
|
||||||
|
// Required fields notice
|
||||||
|
requiredFieldsNotice = new Span("Die mit (*) gekennzeichneten Felder sind Pflichtfelder.");
|
||||||
|
requiredFieldsNotice.getStyle().set("color", "red");
|
||||||
|
requiredFieldsNotice.getStyle().set("font-size", "14px");
|
||||||
|
|
||||||
|
// Pickup address
|
||||||
|
pickupCompany = new TextField("Firma");
|
||||||
|
pickupCompany.setValue("Kunde01");
|
||||||
|
pickupSalutation = new ComboBox<>("Anrede");
|
||||||
|
pickupSalutation.setItems("Herr", "Frau", "Divers");
|
||||||
|
pickupFirstName = new TextField("Vorname*");
|
||||||
|
pickupFirstName.setValue("K01Vor");
|
||||||
|
pickupFirstName.setRequiredIndicatorVisible(true);
|
||||||
|
pickupLastName = new TextField("Nachname*");
|
||||||
|
pickupLastName.setValue("K01Nach");
|
||||||
|
pickupLastName.setRequiredIndicatorVisible(true);
|
||||||
|
pickupPhone = new TextField("Telefonnummer");
|
||||||
|
pickupPhone.setValue("01");
|
||||||
|
pickupStreet = new TextField("Straße*");
|
||||||
|
pickupStreet.setValue("Ottensener Str.");
|
||||||
|
pickupStreet.setRequiredIndicatorVisible(true);
|
||||||
|
pickupHouseNumber = new TextField("Hausnr*");
|
||||||
|
pickupHouseNumber.setValue("8");
|
||||||
|
pickupHouseNumber.setRequiredIndicatorVisible(true);
|
||||||
|
pickupAddressAddition = new TextField("Adresszusatz");
|
||||||
|
pickupZip = new TextField("Postleitzahl*");
|
||||||
|
pickupZip.setValue("22525");
|
||||||
|
pickupZip.setRequiredIndicatorVisible(true);
|
||||||
|
pickupCity = new TextField("Ort*");
|
||||||
|
pickupCity.setValue("Hamburg");
|
||||||
|
pickupCity.setRequiredIndicatorVisible(true);
|
||||||
|
savePickupAddress = new Checkbox("Die Adresse für zukünftige Aufträge speichern.");
|
||||||
|
|
||||||
|
// Delivery address
|
||||||
|
deliveryCompany = new TextField("Firma");
|
||||||
|
deliverySalutation = new ComboBox<>("Anrede");
|
||||||
|
deliverySalutation.setItems("Herr", "Frau", "Divers");
|
||||||
|
deliveryFirstName = new TextField("Vorname*");
|
||||||
|
deliveryFirstName.setRequiredIndicatorVisible(true);
|
||||||
|
deliveryLastName = new TextField("Nachname*");
|
||||||
|
deliveryLastName.setRequiredIndicatorVisible(true);
|
||||||
|
deliveryPhone = new TextField("Telefonnummer");
|
||||||
|
deliveryStreet = new TextField("Straße*");
|
||||||
|
deliveryStreet.setRequiredIndicatorVisible(true);
|
||||||
|
deliveryHouseNumber = new TextField("Hausnr*");
|
||||||
|
deliveryHouseNumber.setRequiredIndicatorVisible(true);
|
||||||
|
deliveryAddressAddition = new TextField("Adresszusatz");
|
||||||
|
deliveryZip = new TextField("Postleitzahl*");
|
||||||
|
deliveryZip.setRequiredIndicatorVisible(true);
|
||||||
|
deliveryCity = new TextField("Ort*");
|
||||||
|
deliveryCity.setRequiredIndicatorVisible(true);
|
||||||
|
saveDeliveryAddress = new Checkbox("Die Adresse für zukünftige Aufträge speichern.");
|
||||||
|
saveDeliveryAddress.setValue(true);
|
||||||
|
|
||||||
|
// Digital processing
|
||||||
|
digitalProcessing = new Checkbox("Digitale Abwicklung per App");
|
||||||
|
digitalProcessing.setValue(true);
|
||||||
|
appUser = new ComboBox<>("App-Nutzer");
|
||||||
|
appUser.setItems("App-Nutzer");
|
||||||
|
|
||||||
|
// Submit button
|
||||||
|
submitButton = new Button("Auftrag anlegen", event -> submit());
|
||||||
|
submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupLayout() {
|
||||||
|
setSizeFull();
|
||||||
|
addClassNames(LumoUtility.BoxSizing.BORDER, LumoUtility.Display.FLEX,
|
||||||
|
LumoUtility.FlexDirection.COLUMN, LumoUtility.Padding.MEDIUM,
|
||||||
|
LumoUtility.Gap.SMALL);
|
||||||
|
|
||||||
|
add(new ViewToolbar("Neuen Auftrag anlegen"));
|
||||||
|
|
||||||
|
// Customer selection section
|
||||||
|
HorizontalLayout customerLayout = new HorizontalLayout();
|
||||||
|
customerLayout.setWidthFull();
|
||||||
|
customerLayout.setAlignItems(FlexComponent.Alignment.END);
|
||||||
|
customerLayout.add(customerSelection, preloadAddressButton);
|
||||||
|
customerSelection.setWidth("70%");
|
||||||
|
preloadAddressButton.setWidth("30%");
|
||||||
|
|
||||||
|
add(customerLayout);
|
||||||
|
add(requiredFieldsNotice);
|
||||||
|
|
||||||
|
// Main content layout with two equal columns (50% each)
|
||||||
|
HorizontalLayout mainLayout = new HorizontalLayout();
|
||||||
|
mainLayout.setWidthFull();
|
||||||
|
mainLayout.setSpacing(true);
|
||||||
|
mainLayout.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.START);
|
||||||
|
|
||||||
|
// Left column (50%) - Pickup address section
|
||||||
|
VerticalLayout leftColumn = createPickupSection();
|
||||||
|
leftColumn.setWidth("50%");
|
||||||
|
|
||||||
|
// Right column (50%) - Delivery address section
|
||||||
|
VerticalLayout rightColumn = createDeliverySection();
|
||||||
|
rightColumn.setWidth("50%");
|
||||||
|
|
||||||
|
// Add copy button to the right column at the top
|
||||||
|
Button copyButton = new Button("Abholadresse kopieren");
|
||||||
|
copyButton.setIcon(new Icon(VaadinIcon.ARROW_RIGHT));
|
||||||
|
copyButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
|
||||||
|
copyButton.addClickListener(e -> copyPickupToDelivery());
|
||||||
|
copyButton.getStyle().set("margin-bottom", "var(--lumo-space-m)");
|
||||||
|
|
||||||
|
// Insert copy button at the beginning of right column
|
||||||
|
rightColumn.addComponentAsFirst(copyButton);
|
||||||
|
|
||||||
|
mainLayout.add(leftColumn, rightColumn);
|
||||||
|
|
||||||
|
add(mainLayout);
|
||||||
|
|
||||||
|
// Digital processing section
|
||||||
|
VerticalLayout digitalSection = new VerticalLayout();
|
||||||
|
digitalSection.setSpacing(false);
|
||||||
|
digitalSection.add(digitalProcessing, appUser);
|
||||||
|
add(digitalSection);
|
||||||
|
|
||||||
|
// Submit button
|
||||||
|
HorizontalLayout submitLayout = new HorizontalLayout();
|
||||||
|
submitLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
|
||||||
|
submitLayout.add(submitButton);
|
||||||
|
add(submitLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private VerticalLayout createPickupSection() {
|
||||||
|
VerticalLayout section = new VerticalLayout();
|
||||||
|
section.setSpacing(true);
|
||||||
|
section.setPadding(false);
|
||||||
|
|
||||||
|
H3 title = new H3("Abholadresse");
|
||||||
|
title.getStyle().set("margin", "0");
|
||||||
|
title.getStyle().set("display", "flex");
|
||||||
|
title.getStyle().set("align-items", "center");
|
||||||
|
Icon helpIcon = new Icon(VaadinIcon.QUESTION_CIRCLE);
|
||||||
|
helpIcon.getStyle().set("margin-left", "8px");
|
||||||
|
title.add(helpIcon);
|
||||||
|
|
||||||
|
section.add(title);
|
||||||
|
section.add(pickupCompany);
|
||||||
|
section.add(pickupSalutation);
|
||||||
|
section.add(pickupFirstName);
|
||||||
|
section.add(pickupLastName);
|
||||||
|
section.add(pickupPhone);
|
||||||
|
|
||||||
|
HorizontalLayout streetLayout = new HorizontalLayout();
|
||||||
|
streetLayout.setWidthFull();
|
||||||
|
streetLayout.add(pickupStreet, pickupHouseNumber);
|
||||||
|
pickupStreet.setWidth("70%");
|
||||||
|
pickupHouseNumber.setWidth("30%");
|
||||||
|
section.add(streetLayout);
|
||||||
|
|
||||||
|
section.add(pickupAddressAddition);
|
||||||
|
|
||||||
|
HorizontalLayout zipCityLayout = new HorizontalLayout();
|
||||||
|
zipCityLayout.setWidthFull();
|
||||||
|
zipCityLayout.add(pickupZip, pickupCity);
|
||||||
|
pickupZip.setWidth("30%");
|
||||||
|
pickupCity.setWidth("70%");
|
||||||
|
section.add(zipCityLayout);
|
||||||
|
|
||||||
|
section.add(savePickupAddress);
|
||||||
|
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
private VerticalLayout createDeliverySection() {
|
||||||
|
VerticalLayout section = new VerticalLayout();
|
||||||
|
section.setSpacing(true);
|
||||||
|
section.setPadding(false);
|
||||||
|
|
||||||
|
H3 title = new H3("Lieferadresse");
|
||||||
|
title.getStyle().set("margin", "0");
|
||||||
|
|
||||||
|
section.add(title);
|
||||||
|
section.add(deliveryCompany);
|
||||||
|
section.add(deliverySalutation);
|
||||||
|
section.add(deliveryFirstName);
|
||||||
|
section.add(deliveryLastName);
|
||||||
|
section.add(deliveryPhone);
|
||||||
|
|
||||||
|
HorizontalLayout streetLayout = new HorizontalLayout();
|
||||||
|
streetLayout.setWidthFull();
|
||||||
|
streetLayout.add(deliveryStreet, deliveryHouseNumber);
|
||||||
|
deliveryStreet.setWidth("70%");
|
||||||
|
deliveryHouseNumber.setWidth("30%");
|
||||||
|
section.add(streetLayout);
|
||||||
|
|
||||||
|
section.add(deliveryAddressAddition);
|
||||||
|
|
||||||
|
HorizontalLayout zipCityLayout = new HorizontalLayout();
|
||||||
|
zipCityLayout.setWidthFull();
|
||||||
|
zipCityLayout.add(deliveryZip, deliveryCity);
|
||||||
|
deliveryZip.setWidth("30%");
|
||||||
|
deliveryCity.setWidth("70%");
|
||||||
|
section.add(zipCityLayout);
|
||||||
|
|
||||||
|
section.add(saveDeliveryAddress);
|
||||||
|
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyPickupToDelivery() {
|
||||||
|
deliveryCompany.setValue(pickupCompany.getValue());
|
||||||
|
deliverySalutation.setValue(pickupSalutation.getValue());
|
||||||
|
deliveryFirstName.setValue(pickupFirstName.getValue());
|
||||||
|
deliveryLastName.setValue(pickupLastName.getValue());
|
||||||
|
deliveryPhone.setValue(pickupPhone.getValue());
|
||||||
|
deliveryStreet.setValue(pickupStreet.getValue());
|
||||||
|
deliveryHouseNumber.setValue(pickupHouseNumber.getValue());
|
||||||
|
deliveryAddressAddition.setValue(pickupAddressAddition.getValue());
|
||||||
|
deliveryZip.setValue(pickupZip.getValue());
|
||||||
|
deliveryCity.setValue(pickupCity.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupValidation() {
|
||||||
|
// Basic validation setup - detailed validation can be added later
|
||||||
|
}
|
||||||
|
|
||||||
|
private void submit() {
|
||||||
|
Job job = new Job();
|
||||||
|
|
||||||
|
// Set pickup address
|
||||||
|
job.setPickupCompany(pickupCompany.getValue());
|
||||||
|
job.setPickupSalutation(pickupSalutation.getValue());
|
||||||
|
job.setPickupFirstName(pickupFirstName.getValue());
|
||||||
|
job.setPickupLastName(pickupLastName.getValue());
|
||||||
|
job.setPickupPhone(pickupPhone.getValue());
|
||||||
|
job.setPickupStreet(pickupStreet.getValue());
|
||||||
|
job.setPickupHouseNumber(pickupHouseNumber.getValue());
|
||||||
|
job.setPickupAddressAddition(pickupAddressAddition.getValue());
|
||||||
|
job.setPickupZip(pickupZip.getValue());
|
||||||
|
job.setPickupCity(pickupCity.getValue());
|
||||||
|
job.setSavePickupAddress(savePickupAddress.getValue());
|
||||||
|
|
||||||
|
// Set delivery address
|
||||||
|
job.setDeliveryCompany(deliveryCompany.getValue());
|
||||||
|
job.setDeliverySalutation(deliverySalutation.getValue());
|
||||||
|
job.setDeliveryFirstName(deliveryFirstName.getValue());
|
||||||
|
job.setDeliveryLastName(deliveryLastName.getValue());
|
||||||
|
job.setDeliveryPhone(deliveryPhone.getValue());
|
||||||
|
job.setDeliveryStreet(deliveryStreet.getValue());
|
||||||
|
job.setDeliveryHouseNumber(deliveryHouseNumber.getValue());
|
||||||
|
job.setDeliveryAddressAddition(deliveryAddressAddition.getValue());
|
||||||
|
job.setDeliveryZip(deliveryZip.getValue());
|
||||||
|
job.setDeliveryCity(deliveryCity.getValue());
|
||||||
|
job.setSaveDeliveryAddress(saveDeliveryAddress.getValue());
|
||||||
|
|
||||||
|
// Set digital processing
|
||||||
|
job.setDigitalProcessing(digitalProcessing.getValue());
|
||||||
|
job.setAppUser(appUser.getValue());
|
||||||
|
job.setCustomerSelection(customerSelection.getValue());
|
||||||
|
|
||||||
|
addJobService.addJob(job);
|
||||||
|
System.out.println("Job created successfully");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,13 +16,16 @@ import com.vaadin.flow.component.sidenav.SideNavItem;
|
|||||||
import com.vaadin.flow.router.Layout;
|
import com.vaadin.flow.router.Layout;
|
||||||
import com.vaadin.flow.server.menu.MenuConfiguration;
|
import com.vaadin.flow.server.menu.MenuConfiguration;
|
||||||
import com.vaadin.flow.server.menu.MenuEntry;
|
import com.vaadin.flow.server.menu.MenuEntry;
|
||||||
|
import de.assecutor.votianlt.security.SecurityService;
|
||||||
|
|
||||||
import static com.vaadin.flow.theme.lumo.LumoUtility.*;
|
import static com.vaadin.flow.theme.lumo.LumoUtility.*;
|
||||||
|
|
||||||
@Layout
|
|
||||||
public final class MainLayout extends AppLayout {
|
public final class MainLayout extends AppLayout {
|
||||||
|
|
||||||
public MainLayout() {
|
private final SecurityService securityService;
|
||||||
|
|
||||||
|
public MainLayout(SecurityService securityService) {
|
||||||
|
this.securityService = securityService;
|
||||||
setPrimarySection(Section.DRAWER);
|
setPrimarySection(Section.DRAWER);
|
||||||
addToDrawer(createHeader(), new Scroller(createSideNav()), createUserMenu());
|
addToDrawer(createHeader(), new Scroller(createSideNav()), createUserMenu());
|
||||||
|
|
||||||
@@ -58,8 +61,9 @@ public final class MainLayout extends AppLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Component createUserMenu() {
|
private Component createUserMenu() {
|
||||||
// TODO Replace with real user information and actions
|
String currentUser = securityService.getCurrentUsername();
|
||||||
var avatar = new Avatar("John Smith");
|
|
||||||
|
var avatar = new Avatar(currentUser);
|
||||||
avatar.addThemeVariants(AvatarVariant.LUMO_XSMALL);
|
avatar.addThemeVariants(AvatarVariant.LUMO_XSMALL);
|
||||||
avatar.addClassNames(Margin.Right.SMALL);
|
avatar.addClassNames(Margin.Right.SMALL);
|
||||||
avatar.setColorIndex(5);
|
avatar.setColorIndex(5);
|
||||||
@@ -69,10 +73,10 @@ public final class MainLayout extends AppLayout {
|
|||||||
userMenu.addClassNames(Margin.MEDIUM);
|
userMenu.addClassNames(Margin.MEDIUM);
|
||||||
|
|
||||||
var userMenuItem = userMenu.addItem(avatar);
|
var userMenuItem = userMenu.addItem(avatar);
|
||||||
userMenuItem.add("John Smith");
|
userMenuItem.add(currentUser);
|
||||||
userMenuItem.getSubMenu().addItem("View Profile");
|
userMenuItem.getSubMenu().addItem("Profil anzeigen");
|
||||||
userMenuItem.getSubMenu().addItem("Manage Settings");
|
userMenuItem.getSubMenu().addItem("Einstellungen");
|
||||||
userMenuItem.getSubMenu().addItem("Logout");
|
userMenuItem.getSubMenu().addItem("Abmelden", e -> securityService.logout());
|
||||||
|
|
||||||
return userMenu;
|
return userMenu;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import java.time.Clock;
|
|||||||
|
|
||||||
import static com.vaadin.flow.spring.data.VaadinSpringDataHelpers.toSpringPageRequest;
|
import static com.vaadin.flow.spring.data.VaadinSpringDataHelpers.toSpringPageRequest;
|
||||||
|
|
||||||
@Route("customer")
|
@Route(value = "customer", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||||
@PageTitle("Kunden")
|
@PageTitle("Kunden")
|
||||||
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Kunden")
|
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Kunden")
|
||||||
public class CustomersView extends Main {
|
public class CustomersView extends Main {
|
||||||
|
|||||||
@@ -12,5 +12,5 @@ public interface LoginRepository extends MongoRepository<User, String> {
|
|||||||
// If you don't need a total row count, Slice is better than Page.
|
// If you don't need a total row count, Slice is better than Page.
|
||||||
Slice<User> findAllBy(Pageable pageable);
|
Slice<User> findAllBy(Pageable pageable);
|
||||||
|
|
||||||
Optional<User> findByEmailAndPassword(String email, String password);
|
Optional<User> findByEmail(String email);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package de.assecutor.votianlt.pages.login.service;
|
|||||||
import com.vaadin.flow.component.notification.Notification;
|
import com.vaadin.flow.component.notification.Notification;
|
||||||
import de.assecutor.votianlt.model.User;
|
import de.assecutor.votianlt.model.User;
|
||||||
import de.assecutor.votianlt.pages.login.domain.LoginRepository;
|
import de.assecutor.votianlt.pages.login.domain.LoginRepository;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -15,18 +16,25 @@ import java.util.Optional;
|
|||||||
public class LoginService {
|
public class LoginService {
|
||||||
|
|
||||||
private final LoginRepository loginRepository;
|
private final LoginRepository loginRepository;
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
LoginService(LoginRepository loginRepository, Clock clock) {
|
LoginService(LoginRepository loginRepository, PasswordEncoder passwordEncoder, Clock clock) {
|
||||||
this.loginRepository = loginRepository;
|
this.loginRepository = loginRepository;
|
||||||
|
this.passwordEncoder = passwordEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<User> findUser(String mail, String password) {
|
public Optional<User> findUser(String email, String password) {
|
||||||
var user = loginRepository.findByEmailAndPassword(mail, password);
|
var userOpt = loginRepository.findByEmail(email);
|
||||||
|
|
||||||
|
if (userOpt.isPresent()) {
|
||||||
|
User user = userOpt.get();
|
||||||
|
// Prüfe das Passwort mit BCrypt
|
||||||
|
if (passwordEncoder.matches(password, user.getPassword())) {
|
||||||
|
return Optional.of(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (user.isEmpty()) {
|
|
||||||
Notification.show("Login failed", 3000, Notification.Position.BOTTOM_END);
|
Notification.show("Login failed", 3000, Notification.Position.BOTTOM_END);
|
||||||
}
|
return Optional.empty();
|
||||||
|
|
||||||
return user;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,64 +3,58 @@ package de.assecutor.votianlt.pages.login.ui.view;
|
|||||||
import com.vaadin.flow.component.UI;
|
import com.vaadin.flow.component.UI;
|
||||||
import com.vaadin.flow.component.button.Button;
|
import com.vaadin.flow.component.button.Button;
|
||||||
import com.vaadin.flow.component.button.ButtonVariant;
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
|
import com.vaadin.flow.component.html.Anchor;
|
||||||
|
import com.vaadin.flow.component.html.H1;
|
||||||
import com.vaadin.flow.component.html.Main;
|
import com.vaadin.flow.component.html.Main;
|
||||||
import com.vaadin.flow.component.notification.Notification;
|
import com.vaadin.flow.component.login.LoginForm;
|
||||||
import com.vaadin.flow.component.notification.NotificationVariant;
|
|
||||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
import com.vaadin.flow.component.textfield.TextField;
|
import com.vaadin.flow.router.BeforeEnterEvent;
|
||||||
|
import com.vaadin.flow.router.BeforeEnterObserver;
|
||||||
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.theme.lumo.LumoUtility;
|
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||||
import de.assecutor.votianlt.pages.login.service.LoginService;
|
|
||||||
import de.assecutor.votianlt.pages.register.service.RegisterService;
|
|
||||||
import de.assecutor.votianlt.util.Util;
|
|
||||||
|
|
||||||
import java.io.Console;
|
|
||||||
import java.time.Clock;
|
|
||||||
|
|
||||||
@Route("login")
|
@Route("login")
|
||||||
@PageTitle("Bei VotianLT anmelden")
|
@PageTitle("Bei VotianLT anmelden")
|
||||||
//@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Bei VotianLT registrieren")
|
@AnonymousAllowed
|
||||||
public class LoginView extends Main {
|
public class LoginView extends VerticalLayout implements BeforeEnterObserver {
|
||||||
private final LoginService loginService;
|
|
||||||
|
|
||||||
TextField usernameField = new TextField("E-Mail-Adresse");
|
private final LoginForm loginForm = new LoginForm();
|
||||||
TextField password1Field = new TextField("Passwort");
|
|
||||||
Button submitButton = new Button("Registrieren");
|
|
||||||
|
|
||||||
public LoginView(LoginService loginService, Clock clock) {
|
|
||||||
this.loginService = loginService;
|
|
||||||
|
|
||||||
// Setze den Button als primär
|
|
||||||
submitButton = new Button("Anmelden", event -> login());
|
|
||||||
submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
|
||||||
|
|
||||||
// Erstelle ein Div als Container (oder direkt ein Layout)
|
|
||||||
VerticalLayout formLayout = new VerticalLayout();
|
|
||||||
formLayout.add(usernameField, password1Field, submitButton);
|
|
||||||
|
|
||||||
// Zentriere die Inhalte vertikal und horizontal
|
|
||||||
formLayout.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
|
||||||
formLayout.setSpacing(true);
|
|
||||||
formLayout.setSizeUndefined(); // Inhalt eng setzen
|
|
||||||
|
|
||||||
|
public LoginView() {
|
||||||
|
addClassName("login-view");
|
||||||
setSizeFull();
|
setSizeFull();
|
||||||
addClassNames(LumoUtility.BoxSizing.BORDER, LumoUtility.Display.FLEX, LumoUtility.FlexDirection.COLUMN,
|
|
||||||
LumoUtility.Padding.MEDIUM, LumoUtility.Gap.SMALL);
|
|
||||||
|
|
||||||
add(formLayout);
|
setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
|
||||||
|
setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
|
||||||
|
loginForm.setAction("login");
|
||||||
|
|
||||||
|
H1 title = new H1("VotianLT");
|
||||||
|
title.getStyle().set("color", "var(--lumo-primary-color)");
|
||||||
|
|
||||||
|
Button registerButton = new Button("Noch kein Konto? Registrieren",
|
||||||
|
e -> UI.getCurrent().navigate("register"));
|
||||||
|
registerButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
|
||||||
|
|
||||||
|
VerticalLayout loginLayout = new VerticalLayout();
|
||||||
|
loginLayout.setAlignItems(FlexComponent.Alignment.CENTER);
|
||||||
|
loginLayout.add(title, loginForm, registerButton);
|
||||||
|
loginLayout.setMaxWidth("400px");
|
||||||
|
loginLayout.setPadding(true);
|
||||||
|
|
||||||
|
add(loginLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void login() {
|
@Override
|
||||||
var user = loginService.findUser(usernameField.getValue(), password1Field.getValue());
|
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
|
||||||
|
// Zeige Fehlermeldung bei fehlgeschlagener Anmeldung
|
||||||
if (user.isPresent()) {
|
if (beforeEnterEvent.getLocation()
|
||||||
UI.getCurrent().navigate("customer");
|
.getQueryParameters()
|
||||||
|
.getParameters()
|
||||||
|
.containsKey("error")) {
|
||||||
|
loginForm.setError(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void submit() {
|
|
||||||
Util.changeDrawerState(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
package de.assecutor.votianlt.pages.register.domain;
|
package de.assecutor.votianlt.pages.register.domain;
|
||||||
|
|
||||||
import de.assecutor.votianlt.model.User;
|
import de.assecutor.votianlt.repository.UserRepository;
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.data.domain.Slice;
|
|
||||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
|
||||||
|
|
||||||
public interface RegisterRepository extends MongoRepository<User, String> {
|
public interface RegisterRepository extends UserRepository {
|
||||||
|
// Erbt alle Methoden von UserRepository
|
||||||
// If you don't need a total row count, Slice is better than Page.
|
|
||||||
Slice<User> findAllBy(Pageable pageable);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package de.assecutor.votianlt.pages.register.service;
|
||||||
|
|
||||||
|
import de.assecutor.votianlt.model.User;
|
||||||
|
import de.assecutor.votianlt.repository.UserRepository;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserService {
|
||||||
|
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
|
||||||
|
public UserService(PasswordEncoder passwordEncoder, UserRepository userRepository) {
|
||||||
|
this.passwordEncoder = passwordEncoder;
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User findByEmail(String email) {
|
||||||
|
return userRepository.findByEmail(email).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public User save(User user) {
|
||||||
|
if (user.getPassword() != null && !user.getPassword().startsWith("$2a$")) {
|
||||||
|
// Passwort verschlüsseln, falls noch nicht verschlüsselt
|
||||||
|
user.setPassword(passwordEncoder.encode(user.getPassword()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timestamps setzen
|
||||||
|
if (user.getCreatedAt() == null) {
|
||||||
|
user.setCreatedAt(LocalDateTime.now());
|
||||||
|
}
|
||||||
|
user.setUpdatedAt(LocalDateTime.now());
|
||||||
|
|
||||||
|
return userRepository.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean existsByEmail(String email) {
|
||||||
|
return userRepository.existsByEmail(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
public User createUser(String email, String password, String firstName, String lastName) {
|
||||||
|
if (existsByEmail(email)) {
|
||||||
|
throw new RuntimeException("User with email " + email + " already exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = new User();
|
||||||
|
user.setEmail(email);
|
||||||
|
user.setPassword(password); // wird in save() verschlüsselt
|
||||||
|
user.setFirstname(firstName);
|
||||||
|
user.setName(lastName);
|
||||||
|
user.setIsActivated((byte) 1);
|
||||||
|
user.setIsEmailConfirmed((byte) 1);
|
||||||
|
|
||||||
|
return save(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,61 +2,162 @@ package de.assecutor.votianlt.pages.register.ui.view;
|
|||||||
|
|
||||||
import com.vaadin.flow.component.button.Button;
|
import com.vaadin.flow.component.button.Button;
|
||||||
import com.vaadin.flow.component.button.ButtonVariant;
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
import com.vaadin.flow.component.html.Main;
|
import com.vaadin.flow.component.html.H1;
|
||||||
|
import com.vaadin.flow.component.html.H2;
|
||||||
|
import com.vaadin.flow.component.notification.Notification;
|
||||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.component.textfield.PasswordField;
|
||||||
import com.vaadin.flow.component.textfield.TextField;
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
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.theme.lumo.LumoUtility;
|
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||||
import de.assecutor.votianlt.model.User;
|
|
||||||
import de.assecutor.votianlt.pages.register.service.RegisterService;
|
import de.assecutor.votianlt.pages.register.service.RegisterService;
|
||||||
import de.assecutor.votianlt.util.Util;
|
import de.assecutor.votianlt.pages.register.service.UserService;
|
||||||
|
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
|
|
||||||
@Route("register")
|
@Route("register")
|
||||||
@PageTitle("Bei VotianLT anmelden")
|
@PageTitle("Bei VotianLT registrieren")
|
||||||
//@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Bei VotianLT registrieren")
|
@AnonymousAllowed
|
||||||
public class RegisterView extends Main {
|
public class RegisterView extends VerticalLayout {
|
||||||
|
|
||||||
private final RegisterService registerService;
|
private final RegisterService registerService;
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
TextField mail = new TextField("E-Mail-Adresse");
|
private TextField emailField;
|
||||||
TextField password1Field = new TextField("Passwort");
|
private PasswordField passwordField;
|
||||||
TextField password2Field = new TextField("Passwort wiederholen");
|
private PasswordField confirmPasswordField;
|
||||||
Button submitButton = new Button("Registrieren");
|
private Button submitButton;
|
||||||
|
|
||||||
public RegisterView(RegisterService registerService, Clock clock) {
|
public RegisterView(RegisterService registerService, UserService userService, Clock clock) {
|
||||||
this.registerService = registerService;
|
this.registerService = registerService;
|
||||||
|
this.userService = userService;
|
||||||
|
|
||||||
// Setze den Button als primär
|
// Layout-Konfiguration für vollständige Zentrierung
|
||||||
submitButton = new Button("Registrieren", event -> registerUser());
|
|
||||||
submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
|
||||||
|
|
||||||
// Erstelle ein Div als Container (oder direkt ein Layout)
|
|
||||||
VerticalLayout formLayout = new VerticalLayout();
|
|
||||||
formLayout.add(mail, password1Field, password2Field, submitButton);
|
|
||||||
|
|
||||||
// Zentriere die Inhalte vertikal und horizontal
|
|
||||||
formLayout.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
|
||||||
formLayout.setSpacing(true);
|
|
||||||
formLayout.setSizeUndefined(); // Inhalt eng setzen
|
|
||||||
|
|
||||||
setSizeFull();
|
setSizeFull();
|
||||||
addClassNames(LumoUtility.BoxSizing.BORDER, LumoUtility.Display.FLEX, LumoUtility.FlexDirection.COLUMN, LumoUtility.Padding.MEDIUM, LumoUtility.Gap.SMALL);
|
setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
|
||||||
|
setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
setPadding(true);
|
||||||
|
setSpacing(false);
|
||||||
|
|
||||||
add(formLayout);
|
// Hauptcontainer für das Formular
|
||||||
|
VerticalLayout formContainer = createFormContainer();
|
||||||
|
add(formContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private VerticalLayout createFormContainer() {
|
||||||
|
VerticalLayout container = new VerticalLayout();
|
||||||
|
container.setWidth("400px");
|
||||||
|
container.setPadding(true);
|
||||||
|
container.setSpacing(true);
|
||||||
|
container.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.STRETCH);
|
||||||
|
|
||||||
|
// Styling für den Container
|
||||||
|
container.getStyle().set("background-color", "var(--lumo-base-color)");
|
||||||
|
container.getStyle().set("border", "1px solid var(--lumo-contrast-20pct)");
|
||||||
|
container.getStyle().set("border-radius", "var(--lumo-border-radius-m)");
|
||||||
|
container.getStyle().set("box-shadow", "var(--lumo-box-shadow-s)");
|
||||||
|
|
||||||
|
// Titel
|
||||||
|
H1 title = new H1("Registrierung");
|
||||||
|
title.getStyle().set("text-align", "center");
|
||||||
|
title.getStyle().set("color", "var(--lumo-primary-color)");
|
||||||
|
title.getStyle().set("margin-top", "0");
|
||||||
|
|
||||||
|
H2 subtitle = new H2("Erstellen Sie Ihr VotianLT-Konto");
|
||||||
|
subtitle.getStyle().set("text-align", "center");
|
||||||
|
subtitle.getStyle().set("color", "var(--lumo-secondary-text-color)");
|
||||||
|
subtitle.getStyle().set("font-size", "var(--lumo-font-size-l)");
|
||||||
|
subtitle.getStyle().set("font-weight", "normal");
|
||||||
|
subtitle.getStyle().set("margin-bottom", "var(--lumo-space-l)");
|
||||||
|
|
||||||
|
// Formularfelder
|
||||||
|
emailField = new TextField("E-Mail-Adresse");
|
||||||
|
emailField.setWidthFull();
|
||||||
|
emailField.setRequired(true);
|
||||||
|
emailField.setPlaceholder("ihre.email@beispiel.de");
|
||||||
|
|
||||||
|
passwordField = new PasswordField("Passwort");
|
||||||
|
passwordField.setWidthFull();
|
||||||
|
passwordField.setRequired(true);
|
||||||
|
passwordField.setPlaceholder("Mindestens 6 Zeichen");
|
||||||
|
|
||||||
|
confirmPasswordField = new PasswordField("Passwort bestätigen");
|
||||||
|
confirmPasswordField.setWidthFull();
|
||||||
|
confirmPasswordField.setRequired(true);
|
||||||
|
confirmPasswordField.setPlaceholder("Passwort wiederholen");
|
||||||
|
|
||||||
|
// Submit Button
|
||||||
|
submitButton = new Button("Registrieren", event -> registerUser());
|
||||||
|
submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_LARGE);
|
||||||
|
submitButton.setWidthFull();
|
||||||
|
|
||||||
|
// Zurück-Link
|
||||||
|
Button backButton = new Button("Zurück zur Startseite", event ->
|
||||||
|
getUI().ifPresent(ui -> ui.navigate("")));
|
||||||
|
backButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
|
||||||
|
backButton.setWidthFull();
|
||||||
|
|
||||||
|
container.add(title, subtitle, emailField, passwordField, confirmPasswordField, submitButton, backButton);
|
||||||
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerUser() {
|
private void registerUser() {
|
||||||
var mail = this.mail.getValue();
|
var email = emailField.getValue().trim();
|
||||||
var password = password1Field.getValue();
|
var password = passwordField.getValue();
|
||||||
|
var confirmPassword = confirmPasswordField.getValue();
|
||||||
|
|
||||||
User user = new User();
|
// Validierung
|
||||||
user.setEmail(mail);
|
if (email.isEmpty()) {
|
||||||
user.setPassword(password);
|
Notification.show("Bitte geben Sie eine E-Mail-Adresse ein.", 3000, Notification.Position.MIDDLE);
|
||||||
|
emailField.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
registerService.registerUser(user);
|
if (!email.contains("@") || !email.contains(".")) {
|
||||||
|
Notification.show("Bitte geben Sie eine gültige E-Mail-Adresse ein.", 3000, Notification.Position.MIDDLE);
|
||||||
|
emailField.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password.isEmpty()) {
|
||||||
|
Notification.show("Bitte geben Sie ein Passwort ein.", 3000, Notification.Position.MIDDLE);
|
||||||
|
passwordField.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password.length() < 6) {
|
||||||
|
Notification.show("Das Passwort muss mindestens 6 Zeichen lang sein.", 3000, Notification.Position.MIDDLE);
|
||||||
|
passwordField.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!password.equals(confirmPassword)) {
|
||||||
|
Notification.show("Die Passwörter stimmen nicht überein.", 3000, Notification.Position.MIDDLE);
|
||||||
|
confirmPasswordField.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Benutzer erstellen
|
||||||
|
userService.createUser(email, password, "Benutzer", "Name");
|
||||||
|
|
||||||
|
// Erfolgsmeldung und Weiterleitung
|
||||||
|
Notification.show("Registrierung erfolgreich! Sie werden zur Anmeldung weitergeleitet.",
|
||||||
|
3000, Notification.Position.MIDDLE);
|
||||||
|
|
||||||
|
getUI().ifPresent(ui -> ui.navigate("login"));
|
||||||
|
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
if (e.getMessage().contains("already exists")) {
|
||||||
|
Notification.show("Ein Benutzer mit dieser E-Mail-Adresse existiert bereits.",
|
||||||
|
5000, Notification.Position.MIDDLE);
|
||||||
|
emailField.focus();
|
||||||
|
} else {
|
||||||
|
Notification.show("Registrierung fehlgeschlagen: " + e.getMessage(),
|
||||||
|
5000, Notification.Position.MIDDLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,344 @@
|
|||||||
package de.assecutor.votianlt.pages.start.ui.view;
|
package de.assecutor.votianlt.pages.start.ui.view;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.Component;
|
||||||
import com.vaadin.flow.component.UI;
|
import com.vaadin.flow.component.UI;
|
||||||
import com.vaadin.flow.component.button.Button;
|
import com.vaadin.flow.component.button.Button;
|
||||||
import com.vaadin.flow.component.button.ButtonVariant;
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
import com.vaadin.flow.component.html.Main;
|
import com.vaadin.flow.component.combobox.ComboBox;
|
||||||
import com.vaadin.flow.router.Menu;
|
import com.vaadin.flow.component.html.*;
|
||||||
|
import com.vaadin.flow.component.icon.Icon;
|
||||||
|
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||||
|
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.PageTitle;
|
||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
import com.vaadin.flow.router.RouterLayout;
|
||||||
|
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||||
|
import de.assecutor.votianlt.security.SecurityService;
|
||||||
|
|
||||||
@Route("")
|
@Route("")
|
||||||
@PageTitle("Dummy")
|
@PageTitle("VotianLT - Willkommen")
|
||||||
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "DUMMY")
|
@AnonymousAllowed
|
||||||
public class StartView extends Main {
|
public class StartView extends VerticalLayout {
|
||||||
|
|
||||||
final Button registerBtn;
|
private final SecurityService securityService;
|
||||||
final Button loginBtn;
|
|
||||||
|
|
||||||
public StartView() {
|
|
||||||
registerBtn = new Button("Registrieren", event -> register());
|
|
||||||
registerBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
|
||||||
add(registerBtn);
|
|
||||||
|
|
||||||
loginBtn = new Button("Anmelden", event -> login());
|
|
||||||
loginBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
|
||||||
add(loginBtn);
|
|
||||||
|
|
||||||
|
public StartView(SecurityService securityService) {
|
||||||
|
this.securityService = securityService;
|
||||||
setSizeFull();
|
setSizeFull();
|
||||||
addClassNames(LumoUtility.BoxSizing.BORDER, LumoUtility.Display.FLEX, LumoUtility.FlexDirection.COLUMN,
|
setPadding(false);
|
||||||
LumoUtility.Padding.MEDIUM, LumoUtility.Gap.SMALL);
|
setSpacing(false);
|
||||||
|
setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.STRETCH);
|
||||||
|
|
||||||
|
// Header mit Navigation
|
||||||
|
add(createHeader());
|
||||||
|
|
||||||
|
// Hero Section
|
||||||
|
add(createHeroSection());
|
||||||
|
|
||||||
|
// System Section
|
||||||
|
add(createSystemSection());
|
||||||
|
|
||||||
|
// App Section
|
||||||
|
add(createAppSection());
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
add(createFooter());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component createHeader() {
|
||||||
|
HorizontalLayout header = new HorizontalLayout();
|
||||||
|
header.setWidthFull();
|
||||||
|
header.setPadding(true);
|
||||||
|
header.setSpacing(true);
|
||||||
|
header.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
header.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
|
||||||
|
header.getStyle().set("background-color", "var(--lumo-contrast-5pct)");
|
||||||
|
header.getStyle().set("border-bottom", "1px solid var(--lumo-contrast-10pct)");
|
||||||
|
|
||||||
|
// Logo
|
||||||
|
H1 logo = new H1("votian LT");
|
||||||
|
logo.getStyle().set("color", "var(--lumo-primary-color)");
|
||||||
|
logo.getStyle().set("margin", "0");
|
||||||
|
logo.getStyle().set("font-weight", "bold");
|
||||||
|
|
||||||
|
// Navigation - abhängig vom Anmeldestatus
|
||||||
|
Component navigation = securityService.isUserLoggedIn()
|
||||||
|
? createAuthenticatedNavigation()
|
||||||
|
: createAnonymousNavigation();
|
||||||
|
|
||||||
|
header.add(logo, navigation);
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component createAnonymousNavigation() {
|
||||||
|
HorizontalLayout navButtons = new HorizontalLayout();
|
||||||
|
navButtons.setSpacing(true);
|
||||||
|
navButtons.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
|
||||||
|
Button loginBtn = new Button("Anmelden", event -> login());
|
||||||
|
loginBtn.addThemeVariants(ButtonVariant.LUMO_CONTRAST);
|
||||||
|
|
||||||
|
Button registerBtn = new Button("Registrieren", event -> register());
|
||||||
|
registerBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
|
||||||
|
navButtons.add(loginBtn, registerBtn);
|
||||||
|
return navButtons;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component createAuthenticatedNavigation() {
|
||||||
|
HorizontalLayout navLayout = new HorizontalLayout();
|
||||||
|
navLayout.setSpacing(true);
|
||||||
|
navLayout.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
|
||||||
|
// Auftragserstellung Button
|
||||||
|
Button createOrderBtn = new Button("Auftragserstellung", event ->
|
||||||
|
UI.getCurrent().navigate("add_job"));
|
||||||
|
createOrderBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
|
||||||
|
// Verwaltung ComboBox
|
||||||
|
ComboBox<String> managementCombo = new ComboBox<>();
|
||||||
|
managementCombo.setPlaceholder("Verwaltung");
|
||||||
|
managementCombo.setItems("Kunden", "Aufträge", "Firmen");
|
||||||
|
managementCombo.addValueChangeListener(event -> {
|
||||||
|
String value = event.getValue();
|
||||||
|
if (value != null) {
|
||||||
|
switch (value) {
|
||||||
|
case "Kunden":
|
||||||
|
UI.getCurrent().navigate("customer");
|
||||||
|
break;
|
||||||
|
case "Aufträge":
|
||||||
|
UI.getCurrent().navigate("orders");
|
||||||
|
break;
|
||||||
|
case "Firmen":
|
||||||
|
UI.getCurrent().navigate("add_company");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
managementCombo.clear(); // Reset selection
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Benutzer ComboBox
|
||||||
|
String currentUser = securityService.getCurrentUsername();
|
||||||
|
ComboBox<String> userCombo = new ComboBox<>();
|
||||||
|
userCombo.setPlaceholder(currentUser);
|
||||||
|
userCombo.setItems("Profil anzeigen", "Einstellungen", "Abmelden");
|
||||||
|
userCombo.addValueChangeListener(event -> {
|
||||||
|
String value = event.getValue();
|
||||||
|
if (value != null) {
|
||||||
|
switch (value) {
|
||||||
|
case "Profil anzeigen":
|
||||||
|
// TODO: Navigate to profile
|
||||||
|
break;
|
||||||
|
case "Einstellungen":
|
||||||
|
// TODO: Navigate to settings
|
||||||
|
break;
|
||||||
|
case "Abmelden":
|
||||||
|
securityService.logout();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
userCombo.clear(); // Reset selection
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Benachrichtigungs-Icon
|
||||||
|
Button notificationBtn = new Button();
|
||||||
|
notificationBtn.setIcon(VaadinIcon.BELL.create());
|
||||||
|
notificationBtn.addThemeVariants(ButtonVariant.LUMO_ICON, ButtonVariant.LUMO_TERTIARY);
|
||||||
|
notificationBtn.setTooltipText("Benachrichtigungen");
|
||||||
|
notificationBtn.addClickListener(event -> {
|
||||||
|
// TODO: Show notifications
|
||||||
|
com.vaadin.flow.component.notification.Notification.show("Keine neuen Benachrichtigungen", 3000,
|
||||||
|
com.vaadin.flow.component.notification.Notification.Position.TOP_END);
|
||||||
|
});
|
||||||
|
|
||||||
|
navLayout.add(createOrderBtn, managementCombo, userCombo, notificationBtn);
|
||||||
|
return navLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component createHeroSection() {
|
||||||
|
VerticalLayout heroSection = new VerticalLayout();
|
||||||
|
heroSection.setWidthFull();
|
||||||
|
heroSection.setPadding(true);
|
||||||
|
heroSection.setSpacing(true);
|
||||||
|
heroSection.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
heroSection.getStyle().set("background", "linear-gradient(135deg, var(--lumo-primary-color-10pct), var(--lumo-primary-color-50pct))");
|
||||||
|
heroSection.getStyle().set("min-height", "400px");
|
||||||
|
heroSection.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
|
||||||
|
|
||||||
|
// Hero Image Placeholder
|
||||||
|
Icon heroIcon = VaadinIcon.TRUCK.create();
|
||||||
|
heroIcon.setSize("120px");
|
||||||
|
heroIcon.getStyle().set("color", "var(--lumo-primary-color)");
|
||||||
|
|
||||||
|
H1 heroTitle = new H1("VotianLT - Ihr digitaler Transportpartner");
|
||||||
|
heroTitle.getStyle().set("text-align", "center");
|
||||||
|
heroTitle.getStyle().set("color", "var(--lumo-primary-text-color)");
|
||||||
|
heroTitle.getStyle().set("margin-bottom", "var(--lumo-space-l)");
|
||||||
|
|
||||||
|
Paragraph heroDescription = new Paragraph(
|
||||||
|
"Für Solo-Selbstständige und Kleinunternehmer im Transportgewerbe - " +
|
||||||
|
"volldigital und aus einem Guss. Konzentrieren Sie sich auf Ihr Geschäft, " +
|
||||||
|
"wir kümmern uns um die Büroarbeit."
|
||||||
|
);
|
||||||
|
heroDescription.getStyle().set("text-align", "center");
|
||||||
|
heroDescription.getStyle().set("max-width", "600px");
|
||||||
|
heroDescription.getStyle().set("font-size", "var(--lumo-font-size-l)");
|
||||||
|
|
||||||
|
Button ctaButton = new Button("Jetzt kostenlos testen", event -> register());
|
||||||
|
ctaButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_LARGE);
|
||||||
|
|
||||||
|
heroSection.add(heroIcon, heroTitle, heroDescription, ctaButton);
|
||||||
|
return heroSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component createSystemSection() {
|
||||||
|
VerticalLayout systemSection = new VerticalLayout();
|
||||||
|
systemSection.setWidthFull();
|
||||||
|
systemSection.setPadding(true);
|
||||||
|
systemSection.setSpacing(true);
|
||||||
|
systemSection.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
systemSection.getStyle().set("background-color", "var(--lumo-base-color)");
|
||||||
|
|
||||||
|
// Section Header
|
||||||
|
H2 systemTitle = new H2("Das System");
|
||||||
|
systemTitle.getStyle().set("color", "var(--lumo-primary-color)");
|
||||||
|
systemTitle.getStyle().set("text-align", "center");
|
||||||
|
|
||||||
|
Paragraph systemIntro = new Paragraph(
|
||||||
|
"Für Solo-Selbstständige und Kleinunternehmer im Transportgewerbe ist von entscheidender Bedeutung, " +
|
||||||
|
"dass sie sich in erster Linie auf ihr eigentliches Geschäft konzentrieren können: Kunden gewinnen und Waren von A nach B liefern."
|
||||||
|
);
|
||||||
|
systemIntro.getStyle().set("text-align", "center");
|
||||||
|
systemIntro.getStyle().set("max-width", "800px");
|
||||||
|
systemIntro.getStyle().set("margin-bottom", "var(--lumo-space-xl)");
|
||||||
|
|
||||||
|
// Features Grid
|
||||||
|
HorizontalLayout featuresGrid = new HorizontalLayout();
|
||||||
|
featuresGrid.setWidthFull();
|
||||||
|
featuresGrid.setSpacing(true);
|
||||||
|
featuresGrid.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.START);
|
||||||
|
|
||||||
|
// Feature Cards
|
||||||
|
featuresGrid.add(
|
||||||
|
createFeatureCard(VaadinIcon.COG, "Einrichtungsassistent",
|
||||||
|
"Mithilfe des Einrichtungsassistenten haben Sie die Möglichkeit, Ihr Nutzerprofil zu vervollständigen."),
|
||||||
|
createFeatureCard(VaadinIcon.USERS, "Kunden- und Auftragsverwaltung",
|
||||||
|
"Mit der Kunden- und Auftragsverwaltung haben Sie alle Kontaktdaten und Auftragsdetails stets im Blick."),
|
||||||
|
createFeatureCard(VaadinIcon.CLIPBOARD_TEXT, "Auftragserstellung",
|
||||||
|
"Stellen Sie mit wenigen Mausklicks Aufträge ins System ein und legen Sie fest, welcher Mitarbeiter welchen Transportauftrag abarbeiten soll.")
|
||||||
|
);
|
||||||
|
|
||||||
|
systemSection.add(systemTitle, systemIntro, featuresGrid);
|
||||||
|
return systemSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component createFeatureCard(VaadinIcon iconType, String title, String description) {
|
||||||
|
VerticalLayout card = new VerticalLayout();
|
||||||
|
card.setSpacing(true);
|
||||||
|
card.setPadding(true);
|
||||||
|
card.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
card.getStyle().set("border", "1px solid var(--lumo-contrast-20pct)");
|
||||||
|
card.getStyle().set("border-radius", "var(--lumo-border-radius-m)");
|
||||||
|
card.getStyle().set("background-color", "var(--lumo-base-color)");
|
||||||
|
card.getStyle().set("box-shadow", "var(--lumo-box-shadow-xs)");
|
||||||
|
card.setWidth("300px");
|
||||||
|
|
||||||
|
Icon icon = iconType.create();
|
||||||
|
icon.setSize("48px");
|
||||||
|
icon.getStyle().set("color", "var(--lumo-primary-color)");
|
||||||
|
|
||||||
|
H3 cardTitle = new H3(title);
|
||||||
|
cardTitle.getStyle().set("text-align", "center");
|
||||||
|
cardTitle.getStyle().set("margin", "var(--lumo-space-s) 0");
|
||||||
|
|
||||||
|
Paragraph cardDescription = new Paragraph(description);
|
||||||
|
cardDescription.getStyle().set("text-align", "center");
|
||||||
|
cardDescription.getStyle().set("font-size", "var(--lumo-font-size-s)");
|
||||||
|
|
||||||
|
card.add(icon, cardTitle, cardDescription);
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component createAppSection() {
|
||||||
|
VerticalLayout appSection = new VerticalLayout();
|
||||||
|
appSection.setWidthFull();
|
||||||
|
appSection.setPadding(true);
|
||||||
|
appSection.setSpacing(true);
|
||||||
|
appSection.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
appSection.getStyle().set("background-color", "var(--lumo-contrast-5pct)");
|
||||||
|
|
||||||
|
H2 appTitle = new H2("Die App");
|
||||||
|
appTitle.getStyle().set("color", "var(--lumo-primary-color)");
|
||||||
|
appTitle.getStyle().set("text-align", "center");
|
||||||
|
|
||||||
|
Paragraph appDescription = new Paragraph(
|
||||||
|
"Jeder Auftrag kann optional über die votianLT-App abgearbeitet werden – ganz ohne \"Zettelwirtschaft\". " +
|
||||||
|
"So gelangen alle relevanten Auftragsinformationen direkt auf das Smartphone des Fahrers."
|
||||||
|
);
|
||||||
|
appDescription.getStyle().set("text-align", "center");
|
||||||
|
appDescription.getStyle().set("max-width", "800px");
|
||||||
|
|
||||||
|
Icon appIcon = VaadinIcon.MOBILE.create();
|
||||||
|
appIcon.setSize("80px");
|
||||||
|
appIcon.getStyle().set("color", "var(--lumo-primary-color)");
|
||||||
|
|
||||||
|
appSection.add(appTitle, appDescription, appIcon);
|
||||||
|
return appSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component createFooter() {
|
||||||
|
VerticalLayout footer = new VerticalLayout();
|
||||||
|
footer.setWidthFull();
|
||||||
|
footer.setPadding(true);
|
||||||
|
footer.setSpacing(true);
|
||||||
|
footer.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
footer.getStyle().set("background-color", "var(--lumo-contrast-10pct)");
|
||||||
|
footer.getStyle().set("border-top", "1px solid var(--lumo-contrast-20pct)");
|
||||||
|
|
||||||
|
// Company Info
|
||||||
|
H3 companyTitle = new H3("Impressum");
|
||||||
|
companyTitle.getStyle().set("color", "var(--lumo-primary-color)");
|
||||||
|
companyTitle.getStyle().set("text-align", "center");
|
||||||
|
|
||||||
|
VerticalLayout companyInfo = new VerticalLayout();
|
||||||
|
companyInfo.setSpacing(false);
|
||||||
|
companyInfo.setPadding(false);
|
||||||
|
companyInfo.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
|
||||||
|
|
||||||
|
companyInfo.add(
|
||||||
|
new Paragraph("Assecutor Data Service GmbH"),
|
||||||
|
new Paragraph("Ottensener Str. 8, 22525 Hamburg"),
|
||||||
|
new Paragraph("Telefon: +49 40 18 123 771 0"),
|
||||||
|
new Paragraph("E-Mail: ahoi@assecutor.de")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Call to Action
|
||||||
|
Paragraph ctaText = new Paragraph(
|
||||||
|
"Registrieren Sie sich noch heute und nutzen den kostenfreien Probemonat, " +
|
||||||
|
"um das System auf Herz und Nieren zu testen."
|
||||||
|
);
|
||||||
|
ctaText.getStyle().set("text-align", "center");
|
||||||
|
ctaText.getStyle().set("font-weight", "bold");
|
||||||
|
ctaText.getStyle().set("color", "var(--lumo-primary-color)");
|
||||||
|
ctaText.getStyle().set("margin-top", "var(--lumo-space-l)");
|
||||||
|
|
||||||
|
Paragraph slogan = new Paragraph("Betreiben Sie Ihr Geschäft smart … mit votianLT!");
|
||||||
|
slogan.getStyle().set("text-align", "center");
|
||||||
|
slogan.getStyle().set("font-style", "italic");
|
||||||
|
slogan.getStyle().set("color", "var(--lumo-primary-color)");
|
||||||
|
|
||||||
|
footer.add(companyTitle, companyInfo, ctaText, slogan);
|
||||||
|
return footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void register() {
|
private void register() {
|
||||||
UI.getCurrent().navigate("register");
|
UI.getCurrent().navigate("register");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void login() { UI.getCurrent().navigate("login"); }
|
private void login() {
|
||||||
|
UI.getCurrent().navigate("login");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
src/main/java/de/assecutor/votianlt/pages/test/TestView.java
Normal file
23
src/main/java/de/assecutor/votianlt/pages/test/TestView.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package de.assecutor.votianlt.pages.test;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.html.H1;
|
||||||
|
import com.vaadin.flow.component.html.Paragraph;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.router.PageTitle;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import de.assecutor.votianlt.pages.base.ui.view.MainLayout;
|
||||||
|
|
||||||
|
@Route(value = "test", layout = MainLayout.class)
|
||||||
|
@PageTitle("Test Seite")
|
||||||
|
public class TestView extends VerticalLayout {
|
||||||
|
|
||||||
|
public TestView() {
|
||||||
|
H1 title = new H1("Test Seite");
|
||||||
|
Paragraph description = new Paragraph("Diese Seite dient zum Testen der Navigation.");
|
||||||
|
|
||||||
|
add(title, description);
|
||||||
|
|
||||||
|
setPadding(true);
|
||||||
|
setSpacing(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package de.assecutor.votianlt.repository;
|
||||||
|
|
||||||
|
import de.assecutor.votianlt.model.User;
|
||||||
|
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface UserRepository extends MongoRepository<User, String> {
|
||||||
|
|
||||||
|
Optional<User> findByEmail(String email);
|
||||||
|
|
||||||
|
boolean existsByEmail(String email);
|
||||||
|
|
||||||
|
void deleteByEmail(String email);
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package de.assecutor.votianlt.security;
|
||||||
|
|
||||||
|
import com.vaadin.flow.spring.security.VaadinWebSecurity;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
|
||||||
|
import de.assecutor.votianlt.pages.login.ui.view.LoginView;
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
@Configuration
|
||||||
|
public class SecurityConfig extends VaadinWebSecurity {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
// Konfiguriere zusätzliche öffentliche Endpunkte vor der Basis-Konfiguration
|
||||||
|
http.authorizeHttpRequests(auth -> auth
|
||||||
|
// Öffentliche Endpunkte
|
||||||
|
.requestMatchers(
|
||||||
|
new AntPathRequestMatcher("/"),
|
||||||
|
new AntPathRequestMatcher("/register"),
|
||||||
|
new AntPathRequestMatcher("/login"),
|
||||||
|
new AntPathRequestMatcher("/images/**"),
|
||||||
|
new AntPathRequestMatcher("/icons/**"),
|
||||||
|
new AntPathRequestMatcher("/favicon.ico"),
|
||||||
|
new AntPathRequestMatcher("/robots.txt"),
|
||||||
|
new AntPathRequestMatcher("/manifest.webmanifest"),
|
||||||
|
new AntPathRequestMatcher("/sw.js"),
|
||||||
|
new AntPathRequestMatcher("/offline.html"),
|
||||||
|
new AntPathRequestMatcher("/frontend/**"),
|
||||||
|
new AntPathRequestMatcher("/webjars/**"),
|
||||||
|
new AntPathRequestMatcher("/h2-console/**"),
|
||||||
|
new AntPathRequestMatcher("/frontend-es5/**", "/frontend-es6/**")
|
||||||
|
).permitAll()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Delegiere die Basis-Konfiguration an VaadinWebSecurity
|
||||||
|
// Dies fügt automatisch .anyRequest().authenticated() hinzu
|
||||||
|
super.configure(http);
|
||||||
|
|
||||||
|
// Setze die Login-View
|
||||||
|
setLoginView(http, LoginView.class);
|
||||||
|
|
||||||
|
// Logout-Konfiguration
|
||||||
|
http.logout(logout -> logout
|
||||||
|
.logoutUrl("/logout")
|
||||||
|
.logoutSuccessUrl("/")
|
||||||
|
.invalidateHttpSession(true)
|
||||||
|
.deleteCookies("JSESSIONID")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package de.assecutor.votianlt.security;
|
||||||
|
|
||||||
|
import com.vaadin.flow.spring.security.AuthenticationContext;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class SecurityService {
|
||||||
|
|
||||||
|
private final AuthenticationContext authenticationContext;
|
||||||
|
|
||||||
|
public SecurityService(AuthenticationContext authenticationContext) {
|
||||||
|
this.authenticationContext = authenticationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<UserDetails> getAuthenticatedUser() {
|
||||||
|
return authenticationContext.getAuthenticatedUser(UserDetails.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUserLoggedIn() {
|
||||||
|
return authenticationContext.isAuthenticated();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCurrentUsername() {
|
||||||
|
return getAuthenticatedUser()
|
||||||
|
.map(UserDetails::getUsername)
|
||||||
|
.orElse("Anonymous");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logout() {
|
||||||
|
authenticationContext.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasRole(String role) {
|
||||||
|
return getAuthenticatedUser()
|
||||||
|
.map(user -> user.getAuthorities().stream()
|
||||||
|
.anyMatch(authority -> authority.getAuthority().equals("ROLE_" + role)))
|
||||||
|
.orElse(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package de.assecutor.votianlt.security;
|
||||||
|
|
||||||
|
import de.assecutor.votianlt.model.User;
|
||||||
|
import de.assecutor.votianlt.pages.register.service.UserService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserDetailsServiceImpl implements UserDetailsService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
|
||||||
|
User user = userService.findByEmail(email);
|
||||||
|
if (user == null) {
|
||||||
|
throw new UsernameNotFoundException("User not found with email: " + email);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new org.springframework.security.core.userdetails.User(
|
||||||
|
user.getEmail(),
|
||||||
|
user.getPassword(),
|
||||||
|
user.getIsActivated() == 1, // enabled
|
||||||
|
true, // accountNonExpired
|
||||||
|
true, // credentialsNonExpired
|
||||||
|
true, // accountNonLocked
|
||||||
|
getAuthorities(user)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<? extends GrantedAuthority> getAuthorities(User user) {
|
||||||
|
// Basis-Rolle für alle Benutzer
|
||||||
|
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,4 +12,4 @@ vaadin.allowed-packages=com.vaadin,org.vaadin,de.assecutor.votianlt
|
|||||||
spring.jpa.open-in-view=false
|
spring.jpa.open-in-view=false
|
||||||
|
|
||||||
# MongoDB
|
# MongoDB
|
||||||
spring.data.mongodb.uri=mongodb://192.168.180.28:27017/votianlt
|
spring.data.mongodb.uri=mongodb://192.168.180.25:27017/votianlt
|
||||||
Reference in New Issue
Block a user