Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class ResourceListController extends Controller {
@FXML private Button prevButton;
@FXML private Button nextButton;
@FXML private Button logoutButton;
@FXML private Button usersButton;

private final ObservableList<Resource> rows = FXCollections.observableArrayList();
private long offset = 0;
Expand All @@ -67,7 +68,6 @@ private void initialize() {
sortCombo.setOnAction(e -> reloadFromStart());
resourceTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN);

// Initial load on open. Guarded for FXML tooling previews where no services are wired.
if (services != null && services.getResourceService() != null) {
reloadFromStart();
}
Expand Down Expand Up @@ -126,6 +126,11 @@ private void setupRbac() {
deleteButton.setVisible(canModify);
deleteButton.setManaged(canModify);
updateDeleteButtonState();

// Кнопка «Пользователи» доступна только администраторам.
boolean isAdmin = authService != null && authService.isAdmin();
usersButton.setVisible(isAdmin);
usersButton.setManaged(isAdmin);
}

private void updateDeleteButtonState() {
Expand All @@ -134,6 +139,11 @@ private void updateDeleteButtonState() {
deleteButton.setDisable(!(canModify && hasSelection));
}

@FXML
private void onOpenUsers(ActionEvent e) {
navigator.goTo("/fxml/UserList.fxml");
}

// ===== Data loading =====

private void reloadFromStart() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.DesktopApplicationClientJava.controllers;

import com.DesktopApplicationClientJava.controllers.utils.Controller;
import com.DesktopApplicationClientJava.entities.Role;
import com.DesktopApplicationClientJava.entities.User;
import com.DesktopApplicationClientJava.services.ServiceException;
import com.DesktopApplicationClientJava.services.data.RegisterData;
import com.DesktopApplicationClientJava.validation.EmailValidator;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;

public class UserCreateFormController extends Controller {

@FXML private TextField emailField;
@FXML private PasswordField passwordField;
@FXML private Label errorLabel;
@FXML private Button submitButton;
@FXML private ChoiceBox<String> rolesChoiceBox;
@FXML private TextField firstNameField;
@FXML private TextField lastNameField;

@FXML
public void initialize() {
// Способ 1: через setItems
rolesChoiceBox.setItems(
FXCollections.observableArrayList(
Role.USER.toString(), Role.MODER.toString(), Role.ADMIN.toString()));
// Установить значение по умолчанию (опционально)
rolesChoiceBox.setValue(Role.USER.toString());

System.out.println(rolesChoiceBox.getValue());
}

@FXML
private void onSubmit(ActionEvent event) {
String email = emailField.getText() == null ? "" : emailField.getText().trim();
String password = passwordField.getText() == null ? "" : passwordField.getText();
String roleStirng = rolesChoiceBox.getValue() == null ? "" : rolesChoiceBox.getValue();
String firstName = firstNameField.getText() == null ? "" : firstNameField.getText().trim();
String lastName = lastNameField.getText() == null ? "" : lastNameField.getText().trim();

if (email.isBlank()
|| password.isBlank()
|| roleStirng.isBlank()
|| firstName.isBlank()
|| lastName.isBlank()) {
showError("Заполните все поля");
return;
}

if (!(roleStirng.equals(Role.USER.toString())
|| roleStirng.equals(Role.MODER.toString())
|| roleStirng.equals(Role.ADMIN.toString()))) {
showError("Роль не определена");
return;
}

Role role = Role.valueOf(roleStirng);

String emailError = EmailValidator.validate(email);
if (emailError != null) {
showError(emailError);
return;
}

try {
RegisterData registerData = new RegisterData(email, password, role, firstName, lastName);
User user = services.getUsersService().create(registerData);
if (user == null) {
return;
}
hideError();
navigator.goTo("/fxml/UserList.fxml");
} catch (ServiceException e) {
showError(e.getMessage());
}
}

@FXML
void onCancel(ActionEvent event) {
navigator.goTo("/fxml/UserList.fxml");
}

private void showError(String message) {
errorLabel.setText(message);
errorLabel.setVisible(true);
errorLabel.setManaged(true);
}

private void hideError() {
errorLabel.setText("");
errorLabel.setVisible(false);
errorLabel.setManaged(false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
package com.DesktopApplicationClientJava.controllers;

import com.DesktopApplicationClientJava.controllers.utils.Controller;
import com.DesktopApplicationClientJava.entities.User;
import com.DesktopApplicationClientJava.services.ServiceException;
import java.util.UUID;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;

public class UserDetailsController extends Controller {

@FXML private Label fullNameLabel;
@FXML private Label emailLabel;
@FXML private Label roleLabel;
@FXML private Label enabledLabel;
@FXML private Label uuidLabel;
@FXML private Label errorLabel;
@FXML private Label statusLabel;
@FXML private Button backButton;
@FXML private Button editButton;
@FXML private Button deleteButton;

private UUID userId;
private User current;

// ===== Lifecycle =====

@FXML
private void initialize() {
hideError();

// Кнопки редактирования и удаления доступны только администраторам.
var authService = services == null ? null : services.getAuthService();
boolean isAdmin = authService != null && authService.isAdmin();

editButton.setVisible(isAdmin);
editButton.setManaged(isAdmin);

deleteButton.setVisible(isAdmin);
deleteButton.setManaged(isAdmin);
}

/** Navigator sets the id after FXML load, so the setter triggers loading. */
public void setUserId(UUID userId) {
this.userId = userId;
if (fullNameLabel != null && userId != null && services != null) {
load();
}
}

// ===== Loading =====

private void load() {
hideError();
statusLabel.setText("Загрузка…");
setContentVisible(false);

var task =
new Task<User>() {
@Override
protected User call() {
return services.getUsersService().getById(userId);
}
};

task.setOnSucceeded(
e -> {
current = task.getValue();
statusLabel.setText("");
if (current == null) {
showError("Пользователь не найден");
return;
}
showUser(current);
setContentVisible(true);
});

task.setOnFailed(
e -> {
statusLabel.setText("");
var ex = task.getException();
String msg =
ex instanceof ServiceException se
? se.getMessage()
: "Не удалось загрузить пользователя";
showError(msg);
});

startDaemon(task, "user-details-load");
}

private void showUser(User user) {
String first = user.getFirstName() == null ? "" : user.getFirstName();
String last = user.getLastName() == null ? "" : user.getLastName();
String full = (first + " " + last).trim();
fullNameLabel.setText(full.isEmpty() ? "Без имени" : full);

emailLabel.setText(user.getEmail() == null ? "" : user.getEmail());
roleLabel.setText(user.getRole() == null ? "" : user.getRole().name());
enabledLabel.setText(Boolean.TRUE.equals(user.getEnabled()) ? "Да" : "Нет");
uuidLabel.setText(user.getUuid() == null ? "" : user.getUuid().toString());

updateDeleteButtonState(user);
}

/**
* Админ не может удалить собственную учётную запись. Кнопка видна только администраторам (см.
* initialize), но дополнительно гасится, если просматривается именно текущий пользователь.
*/
private void updateDeleteButtonState(User user) {
var authService = services == null ? null : services.getAuthService();
var me = authService == null ? null : authService.getCurrentUser();
boolean isSelf =
me != null && user != null && user.getUuid() != null && user.getUuid().equals(me.getUuid());
deleteButton.setDisable(isSelf);
}

// ===== Event handlers =====

@FXML
private void onBack(ActionEvent e) {
navigator.goTo("/fxml/UserList.fxml");
}

@FXML
private void onEdit(ActionEvent e) {
if (current == null || current.getUuid() == null) {
return;
}
navigator.goTo(
"/fxml/UserUpdateForm.fxml",
c -> ((UserUpdateFormController) c).setUserId(current.getUuid()));
}

@FXML
private void onDelete(ActionEvent e) {
if (current == null || current.getUuid() == null) {
return;
}

// Двойная защита: даже если кнопку как-то активировали, себя удалить нельзя.
var authService = services == null ? null : services.getAuthService();
var me = authService == null ? null : authService.getCurrentUser();
if (me != null && current.getUuid().equals(me.getUuid())) {
showError("Нельзя удалить собственную учётную запись");
return;
}

if (!confirmDelete(current)) {
return;
}

hideError();
setBusy(true);

var uuid = current.getUuid();
var task =
new Task<Void>() {
@Override
protected Void call() {
services.getUsersService().delete(uuid);
return null;
}
};

task.setOnSucceeded(
ev -> {
setBusy(false);
navigator.goTo("/fxml/UserList.fxml");
});

task.setOnFailed(
ev -> {
setBusy(false);
var ex = task.getException();
String msg =
ex instanceof ServiceException se
? se.getMessage()
: "Не удалось удалить пользователя";
showError(msg);
});

startDaemon(task, "user-delete");
}

// ===== Confirmation dialog =====

private boolean confirmDelete(User user) {
var alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Удаление пользователя");
alert.setHeaderText(null);
alert.setContentText(
"Удалить пользователя \""
+ (user.getEmail() == null ? user.getUuid().toString() : user.getEmail())
+ "\"? Действие необратимо.");

var ok = new ButtonType("Удалить", ButtonBar.ButtonData.OK_DONE);
var cancel = new ButtonType("Отмена", ButtonBar.ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(ok, cancel);

return alert.showAndWait().filter(ok::equals).isPresent();
}

// ===== UI helpers =====

private void setContentVisible(boolean visible) {
fullNameLabel.setVisible(visible);
emailLabel.setVisible(visible);
roleLabel.setVisible(visible);
enabledLabel.setVisible(visible);
uuidLabel.setVisible(visible);
}

private void setBusy(boolean busy) {
deleteButton.setDisable(busy);
editButton.setDisable(busy);
backButton.setDisable(busy);
statusLabel.setText(busy ? "Удаление…" : "");
}

private void showError(String message) {
errorLabel.setText(message);
errorLabel.setVisible(true);
errorLabel.setManaged(true);
}

private void hideError() {
errorLabel.setText("");
errorLabel.setVisible(false);
errorLabel.setManaged(false);
}

private static void startDaemon(Task<?> task, String name) {
var thread = new Thread(task, name);
thread.setDaemon(true);
thread.start();
}
}
Loading
Loading