Hello,
how do I allow anonymous to register in entity Person?
Kind regards
Swara
Hello,
how do I allow anonymous to register in entity Person?
Kind regards
Swara
Hi,
You need to create a view that can be accessed anonymously, e.g. by adding @AnonymousAllowed
annotation, e.g.:
registration-view.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<view xmlns="http://jmix.io/schema/flowui/view"
title="msg://registrationView.title">
<layout justifyContent="CENTER" alignItems="CENTER" classNames="jmix-login-main-layout">
<vbox id="registrationFormWrapper"
width="22.5em"
alignItems="CENTER"
classNames="registration-form-layout">
<h2 text="msg://registrationHeader.text"/>
<formLayout>
<textField id="firstNameField" label="msg://firstNameField.title"/>
<textField id="lastNameField" label="msg://lastNameField.title"/>
<textField id="usernameField" label="msg://usernameField.title"/>
<textField id="emailField" label="msg://emailField.title"/>
<passwordField id="passwordField" label="msg://passwordField.title"/>
</formLayout>
<button id="registerBtn" text="msg://registerBtn.text" themeNames="primary" width="100%"/>
<button id="alreadyRegisteredBtn" text="msg://alreadyRegisteredBtn.text" themeNames="tertiary small"/>
</vbox>
</layout>
</view>
RegistrationView.java
import com.company.demo.app.RegistrationService;
import com.company.demo.view.login.LoginView;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.auth.AnonymousAllowed;
import io.jmix.flowui.ViewNavigators;
import io.jmix.flowui.component.textfield.JmixPasswordField;
import io.jmix.flowui.component.textfield.TypedTextField;
import io.jmix.flowui.view.*;
import org.springframework.beans.factory.annotation.Autowired;
@AnonymousAllowed
@Route(value = "registration")
@ViewController("RegistrationView")
@ViewDescriptor("registration-view.xml")
public class RegistrationView extends StandardView {
@ViewComponent
private TypedTextField<String> firstNameField;
@ViewComponent
private TypedTextField<String> lastNameField;
@ViewComponent
private TypedTextField<String> usernameField;
@ViewComponent
private TypedTextField<String> emailField;
@ViewComponent
private JmixPasswordField passwordField;
@Autowired
private ViewNavigators viewNavigators;
@Autowired
private RegistrationService registrationService;
@Subscribe("registerBtn")
public void onRegisterBtnClick(final ClickEvent<Button> event) {
// some exception handling is needed in case username
// or email are already taken or password too weak
registrationService.register(
firstNameField.getValue(),
lastNameField.getValue(),
usernameField.getValue(),
emailField.getValue(),
passwordField.getValue()
);
navigateToLoginView();
}
@Subscribe("alreadyRegisteredBtn")
public void onAlreadyRegisteredBtnClick(final ClickEvent<Button> event) {
navigateToLoginView();
}
private void navigateToLoginView() {
viewNavigators.view(LoginView.class)
.navigate();
}
}
and a service to delegate user creation:
RegistrationService
import com.company.demo.entity.User;
import io.jmix.core.UnconstrainedDataManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
public class RegistrationService {
private final UnconstrainedDataManager unconstrainedDataManager;
private final PasswordEncoder passwordEncoder;
public RegistrationService(UnconstrainedDataManager unconstrainedDataManager,
PasswordEncoder passwordEncoder) {
this.unconstrainedDataManager = unconstrainedDataManager;
this.passwordEncoder = passwordEncoder;
}
public void register(String firstName, String lastName, String username, String email, String password) {
// check of username or email are already taken or password too weak
User user = unconstrainedDataManager.create(User.class);
user.setFirstName(firstName);
user.setLastName(lastName);
user.setUsername(username);
user.setEmail(email);
user.setPassword(passwordEncoder.encode(password));
unconstrainedDataManager.save(user);
}
}
IN order to open this view, you can use the forgotPassword
button from loginForm
with custom text, e.g.:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<view xmlns="http://jmix.io/schema/flowui/view"
focusComponent="login"
title="msg://LoginView.title">
<layout justifyContent="CENTER" alignItems="CENTER" classNames="jmix-login-main-layout">
<loginForm id="login"
rememberMeVisible="true"
forgotPasswordButtonVisible="true">
<form title="msg://loginForm.headerTitle"
username="msg://loginForm.username"
password="msg://loginForm.password"
rememberMe="msg://loginForm.rememberMe"
submit="msg://loginForm.submit"
forgotPassword="msg://loginForm.register"/>
<errorMessage title="msg://loginForm.errorTitle"
message="msg://loginForm.badCredentials"/>
</loginForm>
</layout>
</view>
and handle its click
@Route(value = "login")
@ViewController("LoginView")
@ViewDescriptor("login-view.xml")
public class LoginView extends StandardView implements LocaleChangeObserver {
...
@Autowired
private ViewNavigators viewNavigators;
...
@Subscribe("login")
public void onLoginForgotPassword(final AbstractLogin.ForgotPasswordEvent event) {
viewNavigators.view(RegistrationView.class)
.navigate();
}
@Override
public void localeChange(LocaleChangeEvent event) {
...
form.setForgotPassword(messageBundle.getMessage("loginForm.register"));
...
}
}
I also added custom styles for register form:
.registration-form-layout {
padding: var(--lumo-space-l);
background: var(--lumo-base-color) linear-gradient(var(--lumo-tint-5pct), var(--lumo-tint-5pct));
}
You can find the above code in the demo project attached:
flowui-user-registration-sample.zip (399.5 KB)
Regards,
Gleb
Thank you very much for your solution.
But in order for the validations to apply, I have to define it manually within the view, because none of the validations of the Entity itself are validated and the row for the table is added empty.