usermanager

This commit is contained in:
f43nd1r 2018-11-22 03:07:23 +01:00
parent 4f050f6034
commit 04a118528a
7 changed files with 120 additions and 27 deletions

View file

@ -1,6 +1,7 @@
package com.faendir.acra.ui.base;
import com.faendir.acra.dataprovider.QueryDslDataProvider;
import com.faendir.acra.ui.component.HasSize;
import com.querydsl.core.types.Expression;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentEventListener;
@ -26,7 +27,7 @@ import java.util.function.Function;
* @author lukas
* @since 13.07.18
*/
public class MyGrid<T> extends Composite<Grid<T>> implements LocaleChangeObserver {
public class MyGrid<T> extends Composite<Grid<T>> implements LocaleChangeObserver, HasSize {
private final QueryDslDataProvider<T> dataProvider;
private final Map<Grid.Column<T>, Pair<String, Object[]>> columnCaptions;

View file

@ -17,6 +17,7 @@
package com.faendir.acra.ui.base.popup;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.HasValidation;
import com.vaadin.flow.component.HasValue;
import org.springframework.lang.NonNull;
@ -33,28 +34,34 @@ import java.util.function.Supplier;
* @author Lukas
* @since 22.06.2017
*/
public class ValidatedField<V, T extends Component & HasValue<?,V> & HasValidation> {
public class ValidatedField<V, T extends Component> {
private final T field;
private final Supplier<V> valueSupplier;
private final Consumer<String> messageSetter;
private final Map<Function<V, Boolean>, String> validators;
private final List<Listener> listeners;
private boolean valid;
private ValidatedField(T field, Supplier<V> valueSupplier, Consumer<Consumer<V>> listenerRegistration) {
private ValidatedField(T field, Supplier<V> valueSupplier, Consumer<Consumer<V>> listenerRegistration, Consumer<String> messageSetter) {
this.field = field;
this.valueSupplier = valueSupplier;
this.messageSetter = messageSetter;
this.validators = new HashMap<>();
this.listeners = new ArrayList<>();
this.valid = false;
listenerRegistration.accept(this::validate);
}
public static <V, T extends Component & HasValue<?,V> & HasValidation> ValidatedField<V, T> of(T field) {
return new ValidatedField<>(field, field::getValue, vConsumer -> field.addValueChangeListener(event -> vConsumer.accept(event.getValue())));
public static <V, T extends Component & HasValue<?, V> & HasValidation> ValidatedField<V, T> of(T field) {
return new ValidatedField<>(field, field::getValue, vConsumer -> field.addValueChangeListener(event -> vConsumer.accept(event.getValue())), field::setErrorMessage);
}
public static <V, T extends Component & HasValue<?,V> & HasValidation> ValidatedField<V, T> of(T field, Supplier<V> valueSupplier, Consumer<Consumer<V>> listenerRegistration) {
return new ValidatedField<>(field, valueSupplier, listenerRegistration);
public static <V, C extends Composite<T>, T extends Component & HasValue<?, V> & HasValidation> ValidatedField<V, C> of(C field) {
return new ValidatedField<>(field, () -> field.getContent().getValue(), vConsumer -> field.getContent().addValueChangeListener(event -> vConsumer.accept(event.getValue())), m -> field.getContent().setErrorMessage(m));
}
public static <V, T extends Component & HasValue<?, V> & HasValidation> ValidatedField<V, T> of(T field, Supplier<V> valueSupplier, Consumer<Consumer<V>> listenerRegistration) {
return new ValidatedField<>(field, valueSupplier, listenerRegistration, field::setErrorMessage);
}
public ValidatedField<V, T> addValidator(Function<V, Boolean> validator, String errorMessage) {
@ -73,10 +80,10 @@ public class ValidatedField<V, T extends Component & HasValue<?,V> & HasValidati
private boolean validate(V value) {
boolean valid = validators.entrySet().stream().allMatch(entry -> {
if (entry.getKey().apply(value)) {
field.setErrorMessage(null);
messageSetter.accept(null);
return true;
} else {
field.setErrorMessage(entry.getValue());
messageSetter.accept(entry.getValue());
return false;
}
});

View file

@ -33,7 +33,8 @@ public class FlexLayout extends com.vaadin.flow.component.orderedlayout.FlexLayo
}
public enum FlexDirection {
COLUMN("column");
COLUMN("column"),
ROW("row");
private final String value;
FlexDirection(@NonNull String value) {

View file

@ -10,7 +10,6 @@ import com.faendir.acra.ui.component.FlexLayout;
import com.faendir.acra.ui.component.Translatable;
import com.faendir.acra.ui.view.MainView;
import com.faendir.acra.ui.view.Overview;
import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.notification.Notification;
@ -69,11 +68,6 @@ public class ChangePasswordView extends Composite<FlexLayout> implements HasRout
getContent().setAlignItems(FlexComponent.Alignment.CENTER);
}
@Override
protected void onAttach(AttachEvent attachEvent) {
super.onAttach(attachEvent);
}
@NonNull
@Override
public Path.Element<?> getPathElement() {

View file

@ -1,14 +1,104 @@
package com.faendir.acra.ui.view.user;
import com.faendir.acra.i18n.Messages;
import com.faendir.acra.model.App;
import com.faendir.acra.model.Permission;
import com.faendir.acra.model.QUser;
import com.faendir.acra.model.User;
import com.faendir.acra.security.SecurityUtils;
import com.faendir.acra.service.DataService;
import com.faendir.acra.service.UserService;
import com.faendir.acra.ui.base.MyGrid;
import com.faendir.acra.ui.base.popup.Popup;
import com.faendir.acra.ui.base.popup.ValidatedField;
import com.faendir.acra.ui.component.FlexLayout;
import com.faendir.acra.ui.component.Translatable;
import com.faendir.acra.ui.view.MainView;
import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.textfield.PasswordField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent;
import com.vaadin.flow.spring.annotation.UIScope;
import org.springframework.lang.NonNull;
import java.util.Arrays;
/**
* @author lukas
* @since 15.11.18
*/
@UIScope
@SpringComponent
@Route(value = "user-manager", layout = MainView.class)
public class UserManager extends Composite<FlexLayout> {
private final UserService userService;
private final DataService dataService;
public UserManager(@NonNull UserService userService, @NonNull DataService dataService) {
this.userService = userService;
this.dataService = dataService;
getContent().setFlexDirection(FlexLayout.FlexDirection.COLUMN);
getContent().setWidthFull();
}
@Override
protected void onAttach(AttachEvent attachEvent) {
super.onAttach(attachEvent);
getContent().removeAll();
getContent().add(Translatable.createLabel(Messages.USERS));
MyGrid<User> userGrid = new MyGrid<>(userService.getUserProvider());
userGrid.setWidthFull();
userGrid.setSelectionMode(Grid.SelectionMode.NONE);
userGrid.addColumn(User::getUsername, QUser.user.username, Messages.USERNAME);
userGrid.addColumn(new ComponentRenderer<>(user -> {
Checkbox checkbox = new Checkbox(user.getRoles().contains(User.Role.ADMIN));
checkbox.addValueChangeListener(e -> {
userService.setAdmin(user, e.getValue());
userGrid.getDataProvider().refreshAll();
});
checkbox.setEnabled(!user.getUsername().equals(SecurityUtils.getUsername()));
return checkbox;
}), Messages.ADMIN);
userGrid.addColumn(new ComponentRenderer<>(user -> {
Checkbox checkbox = new Checkbox(user.getRoles().contains(User.Role.API));
checkbox.addValueChangeListener(e -> {
userService.setApiAccess(user, e.getValue());
userGrid.getDataProvider().refreshAll();
});
return checkbox;
}), Messages.API);
for (App app : dataService.findAllApps()) {
userGrid.addColumn(new ComponentRenderer<>(user -> {
Permission.Level permission = SecurityUtils.getPermission(app, user);
ComboBox<Permission.Level> levelComboBox = new ComboBox<>(null, Arrays.asList(Permission.Level.values()));
levelComboBox.setValue(permission);
levelComboBox.addValueChangeListener(e -> {
userService.setPermission(user, app, e.getValue());
userGrid.getDataProvider().refreshAll();
});
return levelComboBox;
}), Messages.ACCESS_PERMISSION, app.getName());
}
Translatable<Button> newUser = Translatable.createButton(e -> {
Translatable<TextField> name = Translatable.createTextField("", Messages.USERNAME);
Translatable<PasswordField> password = Translatable.createPasswordField(Messages.PASSWORD);
new Popup().setTitle(Messages.NEW_USER)
.addValidatedField(ValidatedField.of(name).addValidator(s -> !s.isEmpty(), Messages.USERNAME_EMPTY))
.addValidatedField(ValidatedField.of(password).addValidator(s -> !s.isEmpty(), Messages.PASSWORD_EMPTY))
.addValidatedField(ValidatedField.of(Translatable.createPasswordField(Messages.REPEAT_PASSWORD)).addValidator(s -> s.equals(password.getContent().getValue()), Messages.PASSWORDS_NOT_MATCHING))
.addCreateButton(popup -> {
userService.createUser(name.getContent().getValue().toLowerCase(), password.getContent().getValue());
userGrid.getDataProvider().refreshAll();
}, true)
.show();
}, Messages.NEW_USER);
getContent().add(userGrid, newUser);
}
}

View file

@ -24,13 +24,13 @@ host=Host
port=Port
ssl=Nutze SSL
databaseName=Datenbankname
importSuccess=Import erfolgreich für {0} von {1} Berichten.
importSuccess=Import erfolgreich für %s von %s Berichten.
acrarium=Acrarium
configurationLabel=Notiere die folgende ACRA Konfiguration. Sie kann später nicht mehr angezeigt werden:<br><code>\
@AcraCore(reportFormat = StringFormat.JSON)<br>\
@AcraHttpSender(uri = "{0}{1}",<br>\
basicAuthLogin = "{2}",<br>\
basicAuthPassword = "{3}",<br>\
@AcraHttpSender(uri = "%s%s",<br>\
basicAuthLogin = "%s",<br>\
basicAuthPassword = "%s",<br>\
httpMethod = HttpSender.Method.POST)<br></code>
create=Erzeugen
close=Schließen
@ -115,7 +115,7 @@ changePassword=Passwort ändern
success=Erfolgreich!
users=Nutzer
username=Nutzername
accessPermission=Zugriffsrechte für {0}
accessPermission=Zugriffsrechte für %s
newUser=Neuer Benutzer
password=Passwort
usernameEmpty=Nutzername darf nicht leer sein

View file

@ -24,13 +24,13 @@ host=Host
port=Port
ssl=Use SSL
databaseName=Database Name
importSuccess=Import successful for {0} of {1} reports.
importSuccess=Import successful for %s of %s reports.
acrarium=Acrarium
configurationLabel=Take note of the following ACRA configuration. It cannot be viewed later:<br><code>\
@AcraCore(reportFormat = StringFormat.JSON)<br>\
@AcraHttpSender(uri = "{0}{1}",<br>\
basicAuthLogin = "{2}",<br>\
basicAuthPassword = "{3}",<br>\
@AcraHttpSender(uri = "%s%s",<br>\
basicAuthLogin = "%s",<br>\
basicAuthPassword = "%s",<br>\
httpMethod = HttpSender.Method.POST)<br></code>
create=Create
close=Close
@ -67,7 +67,7 @@ download=Download
nothingSelected=Nothing selected
export=Export
version=Version
deleteMappingConfirm=Are you sure you want to delete the mapping for version {0}?
deleteMappingConfirm=Are you sure you want to delete the mapping for version %s?
newFile=Add File
versionCode=Version code
mappingFile=Mapping file
@ -115,7 +115,7 @@ changePassword=Change Password
success=Successful!
users=Users
username=Username
accessPermission=Access Permission for {0}
accessPermission=Access Permission for %s
newUser=New User
password=Password
usernameEmpty=Username cannot be empty