implemented account details page

This commit is contained in:
Andrey Terentev 2024-05-02 17:16:14 +07:00 committed by Andrey Terentev
parent baf204bc29
commit 0bd7271ef3
4 changed files with 153 additions and 5 deletions

View File

@ -73,7 +73,9 @@ public class AccountList extends VerticalLayout implements RefreshableTable {
var button = new Button("Manage", VaadinIcon.COG_O.create()); var button = new Button("Manage", VaadinIcon.COG_O.create());
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY); button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
button.addClickListener(event -> { button.addClickListener(event -> {
getUI().ifPresent(ui -> {
ui.navigate("/admin/accounts/" + account.getUsername());
});
}); });
layout.add(button); layout.add(button);
} }
@ -171,7 +173,7 @@ public class AccountList extends VerticalLayout implements RefreshableTable {
} }
if (password.length() < 5 || password.length() > 32) { if (password.length() < 5 || password.length() > 32) {
Notifications.error("Invalid username length. Valid is 5-32"); Notifications.error("Invalid password length. Valid is 5-32");
return; return;
} }
@ -192,7 +194,7 @@ public class AccountList extends VerticalLayout implements RefreshableTable {
refresh(); refresh();
} }
private static class PermissionCheckBox extends Checkbox { public static class PermissionCheckBox extends Checkbox {
private final Permission.Enum option; private final Permission.Enum option;

View File

@ -0,0 +1,138 @@
package ru.dragonestia.picker.cp.page;
import com.vaadin.flow.component.AbstractField;
import com.vaadin.flow.component.Html;
import com.vaadin.flow.component.Unit;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.H3;
import com.vaadin.flow.component.html.Hr;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.PasswordField;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.security.RolesAllowed;
import lombok.RequiredArgsConstructor;
import ru.dragonestia.picker.api.impl.RoomPickerClient;
import ru.dragonestia.picker.api.model.account.IAccount;
import ru.dragonestia.picker.cp.component.AccountList;
import ru.dragonestia.picker.cp.component.Notifications;
import ru.dragonestia.picker.cp.model.Permission;
import ru.dragonestia.picker.cp.service.SecurityService;
import ru.dragonestia.picker.cp.util.RouteParamsExtractor;
import java.util.ArrayList;
@RequiredArgsConstructor
@RolesAllowed("ADMIN")
@PageTitle("Account details")
@Route(value = "/admin/accounts/:accountId", layout = MainLayout.class)
public class AccountDetailsPage extends VerticalLayout implements BeforeEnterObserver {
private final SecurityService securityService;
private final RouteParamsExtractor paramsExtractor;
private RoomPickerClient client;
private IAccount account;
@PostConstruct
void postConstruct() {
client = securityService.getAuthenticatedAccount().getClient();
}
@Override
public void beforeEnter(BeforeEnterEvent event) {
account = paramsExtractor.extractAccount(event);
init();
}
private void init() {
add(new H2("Account management"));
add(new Html("<span>Username: <b>%s</b></span>".formatted(account.getUsername())));
add(new Hr());
add(new H3("Change password"));
createChangePassword();
add(new Hr());
add(new H3("Update permissions"));
createEditPermissions();
add(new Hr());
add(new H3("Delete account"));
add(createDeleteAccountButton());
}
private void createChangePassword() {
var newPassword = new PasswordField("New password");
newPassword.setMinWidth(25, Unit.PERCENTAGE);
add(newPassword);
var confirmPassword = new PasswordField("Confirm new password");
confirmPassword.setMinWidth(25, Unit.PERCENTAGE);
add(confirmPassword);
var submit = new Button("Submit", event -> {
var pass = newPassword.getValue();
var confirm = confirmPassword.getValue();
if (pass.length() < 5 || pass.length() > 32) {
Notifications.error("Invalid password length. Valid is 5-32");
return;
}
if (!pass.equals(confirm)) {
Notifications.error("Passwords are not equals");
return;
}
//TODO: change password
Notifications.success("Password successfully changed!");
newPassword.setValue("");
confirmPassword.setValue("");
});
submit.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
add(submit);
}
private void createEditPermissions() {
var permissionsList = new ArrayList<AccountList.PermissionCheckBox>();
for (var permission: Permission.Enum.values()) {
var comp = new AccountList.PermissionCheckBox(permission);
comp.setValue(account.getPermissions().contains(permission.name()));
permissionsList.add(comp);
add(comp);
}
var button = new Button("Update permissions", event -> {
var permissions = permissionsList.stream()
.filter(AbstractField::getValue)
.map(AccountList.PermissionCheckBox::getOption)
.map(Enum::name)
.toList();
client.getAccountRepository().setPermissions(account, permissions);
Notifications.success("Permissions successfully changed!");
});
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
add(button);
}
private Button createDeleteAccountButton() {
var button = new Button("Delete this account", event -> {
client.getAccountRepository().removeAccount(account);
Notifications.warn("Account '%s' was deleted.".formatted(account.getUsername()));
getUI().ifPresent(ui -> {
ui.navigate("/admin/accounts");
});
});
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR);
return button;
}
}

View File

@ -6,6 +6,7 @@ import org.springframework.stereotype.Component;
import ru.dragonestia.picker.api.exception.NodeNotFoundException; import ru.dragonestia.picker.api.exception.NodeNotFoundException;
import ru.dragonestia.picker.api.exception.RoomNotFoundException; import ru.dragonestia.picker.api.exception.RoomNotFoundException;
import ru.dragonestia.picker.api.impl.RoomPickerClient; import ru.dragonestia.picker.api.impl.RoomPickerClient;
import ru.dragonestia.picker.api.model.account.IAccount;
import ru.dragonestia.picker.api.model.node.INode; import ru.dragonestia.picker.api.model.node.INode;
import ru.dragonestia.picker.api.model.room.IRoom; import ru.dragonestia.picker.api.model.room.IRoom;
import ru.dragonestia.picker.api.model.user.IUser; import ru.dragonestia.picker.api.model.user.IUser;
@ -37,4 +38,9 @@ public class RouteParamsExtractor {
var userId = UserIdentifier.of(e.getRouteParameters().get("userId").orElseThrow(RuntimeException::new)); var userId = UserIdentifier.of(e.getRouteParameters().get("userId").orElseThrow(RuntimeException::new));
return client.getUserRepository().findUserById(FindUserById.withAllDetails(userId)); return client.getUserRepository().findUserById(FindUserById.withAllDetails(userId));
} }
public IAccount extractAccount(BeforeEnterEvent e) {
var accountId = e.getRouteParameters().get("accountId").orElseThrow(RuntimeException::new);
return client.getAccountRepository().findAccountByUsername(accountId).orElseThrow(RuntimeException::new);
}
} }

View File

@ -49,11 +49,12 @@ public class AccountsController {
} }
@PostMapping @PostMapping
ResponseAccount registerAccount(@RequestParam String username, @RequestParam String password, @RequestParam String permissions) { ResponseAccount registerAccount(@RequestParam String username, @RequestParam String password, @RequestParam(defaultValue = "") String permissions) {
var account = accountService.createNewAccount(username, password); var account = accountService.createNewAccount(username, password);
var authorities = new HashSet<Permission>(); var authorities = new HashSet<Permission>();
for (var permStr : permissions.split(",")) { for (var permStr : permissions.split(",")) {
if (permStr.isBlank()) continue;
try { try {
var perm = Permission.valueOf(permStr); var perm = Permission.valueOf(permStr);
authorities.add(perm); authorities.add(perm);
@ -69,11 +70,12 @@ public class AccountsController {
} }
@PutMapping("/{accountId}") @PutMapping("/{accountId}")
ResponseEntity<?> updatePermissions(@PathVariable String accountId, @RequestParam String permissions) { ResponseEntity<?> updatePermissions(@PathVariable String accountId, @RequestParam(defaultValue = "") String permissions) {
var account = accountService.findAccount(accountId).orElseThrow(() -> new AccountDoesNotExistsException(accountId)); var account = accountService.findAccount(accountId).orElseThrow(() -> new AccountDoesNotExistsException(accountId));
var authorities = new HashSet<Permission>(); var authorities = new HashSet<Permission>();
for (var permStr : permissions.split(",")) { for (var permStr : permissions.split(",")) {
if (permStr.isBlank()) continue;
try { try {
var perm = Permission.valueOf(permStr); var perm = Permission.valueOf(permStr);
authorities.add(perm); authorities.add(perm);