Skip to content

Commit 05be6ec

Browse files
Deathehvladcheck
andauthored
User pages (#54)
Страница вывода всех пользователей Страница конкретного пользователя Страница создания пользователя Страница изменения пользователя Кнопка для админа изменения между ресурсами и пользователями Стили кнопки --------- Co-authored-by: Vladimir Valekzhanin <valdemarcheck@yandex.ru>
1 parent 5b3f1a5 commit 05be6ec

11 files changed

Lines changed: 1318 additions & 1 deletion

‎src/main/java/com/DesktopApplicationClientJava/controllers/ResourceListController.java‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public class ResourceListController extends Controller {
4747
@FXML private Button prevButton;
4848
@FXML private Button nextButton;
4949
@FXML private Button logoutButton;
50+
@FXML private Button usersButton;
5051

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

70-
// Initial load on open. Guarded for FXML tooling previews where no services are wired.
7171
if (services != null && services.getResourceService() != null) {
7272
reloadFromStart();
7373
}
@@ -126,6 +126,11 @@ private void setupRbac() {
126126
deleteButton.setVisible(canModify);
127127
deleteButton.setManaged(canModify);
128128
updateDeleteButtonState();
129+
130+
// Кнопка «Пользователи» доступна только администраторам.
131+
boolean isAdmin = authService != null && authService.isAdmin();
132+
usersButton.setVisible(isAdmin);
133+
usersButton.setManaged(isAdmin);
129134
}
130135

131136
private void updateDeleteButtonState() {
@@ -134,6 +139,11 @@ private void updateDeleteButtonState() {
134139
deleteButton.setDisable(!(canModify && hasSelection));
135140
}
136141

142+
@FXML
143+
private void onOpenUsers(ActionEvent e) {
144+
navigator.goTo("/fxml/UserList.fxml");
145+
}
146+
137147
// ===== Data loading =====
138148

139149
private void reloadFromStart() {
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package com.DesktopApplicationClientJava.controllers;
2+
3+
import com.DesktopApplicationClientJava.controllers.utils.Controller;
4+
import com.DesktopApplicationClientJava.entities.Role;
5+
import com.DesktopApplicationClientJava.entities.User;
6+
import com.DesktopApplicationClientJava.services.ServiceException;
7+
import com.DesktopApplicationClientJava.services.data.RegisterData;
8+
import com.DesktopApplicationClientJava.validation.EmailValidator;
9+
import javafx.collections.FXCollections;
10+
import javafx.event.ActionEvent;
11+
import javafx.fxml.FXML;
12+
import javafx.scene.control.*;
13+
14+
public class UserCreateFormController extends Controller {
15+
16+
@FXML private TextField emailField;
17+
@FXML private PasswordField passwordField;
18+
@FXML private Label errorLabel;
19+
@FXML private Button submitButton;
20+
@FXML private ChoiceBox<String> rolesChoiceBox;
21+
@FXML private TextField firstNameField;
22+
@FXML private TextField lastNameField;
23+
24+
@FXML
25+
public void initialize() {
26+
// Способ 1: через setItems
27+
rolesChoiceBox.setItems(
28+
FXCollections.observableArrayList(
29+
Role.USER.toString(), Role.MODER.toString(), Role.ADMIN.toString()));
30+
// Установить значение по умолчанию (опционально)
31+
rolesChoiceBox.setValue(Role.USER.toString());
32+
33+
System.out.println(rolesChoiceBox.getValue());
34+
}
35+
36+
@FXML
37+
private void onSubmit(ActionEvent event) {
38+
String email = emailField.getText() == null ? "" : emailField.getText().trim();
39+
String password = passwordField.getText() == null ? "" : passwordField.getText();
40+
String roleStirng = rolesChoiceBox.getValue() == null ? "" : rolesChoiceBox.getValue();
41+
String firstName = firstNameField.getText() == null ? "" : firstNameField.getText().trim();
42+
String lastName = lastNameField.getText() == null ? "" : lastNameField.getText().trim();
43+
44+
if (email.isBlank()
45+
|| password.isBlank()
46+
|| roleStirng.isBlank()
47+
|| firstName.isBlank()
48+
|| lastName.isBlank()) {
49+
showError("Заполните все поля");
50+
return;
51+
}
52+
53+
if (!(roleStirng.equals(Role.USER.toString())
54+
|| roleStirng.equals(Role.MODER.toString())
55+
|| roleStirng.equals(Role.ADMIN.toString()))) {
56+
showError("Роль не определена");
57+
return;
58+
}
59+
60+
Role role = Role.valueOf(roleStirng);
61+
62+
String emailError = EmailValidator.validate(email);
63+
if (emailError != null) {
64+
showError(emailError);
65+
return;
66+
}
67+
68+
try {
69+
RegisterData registerData = new RegisterData(email, password, role, firstName, lastName);
70+
User user = services.getUsersService().create(registerData);
71+
if (user == null) {
72+
return;
73+
}
74+
hideError();
75+
navigator.goTo("/fxml/UserList.fxml");
76+
} catch (ServiceException e) {
77+
showError(e.getMessage());
78+
}
79+
}
80+
81+
@FXML
82+
void onCancel(ActionEvent event) {
83+
navigator.goTo("/fxml/UserList.fxml");
84+
}
85+
86+
private void showError(String message) {
87+
errorLabel.setText(message);
88+
errorLabel.setVisible(true);
89+
errorLabel.setManaged(true);
90+
}
91+
92+
private void hideError() {
93+
errorLabel.setText("");
94+
errorLabel.setVisible(false);
95+
errorLabel.setManaged(false);
96+
}
97+
}
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
package com.DesktopApplicationClientJava.controllers;
2+
3+
import com.DesktopApplicationClientJava.controllers.utils.Controller;
4+
import com.DesktopApplicationClientJava.entities.User;
5+
import com.DesktopApplicationClientJava.services.ServiceException;
6+
import java.util.UUID;
7+
import javafx.concurrent.Task;
8+
import javafx.event.ActionEvent;
9+
import javafx.fxml.FXML;
10+
import javafx.scene.control.Alert;
11+
import javafx.scene.control.Button;
12+
import javafx.scene.control.ButtonBar;
13+
import javafx.scene.control.ButtonType;
14+
import javafx.scene.control.Label;
15+
16+
public class UserDetailsController extends Controller {
17+
18+
@FXML private Label fullNameLabel;
19+
@FXML private Label emailLabel;
20+
@FXML private Label roleLabel;
21+
@FXML private Label enabledLabel;
22+
@FXML private Label uuidLabel;
23+
@FXML private Label errorLabel;
24+
@FXML private Label statusLabel;
25+
@FXML private Button backButton;
26+
@FXML private Button editButton;
27+
@FXML private Button deleteButton;
28+
29+
private UUID userId;
30+
private User current;
31+
32+
// ===== Lifecycle =====
33+
34+
@FXML
35+
private void initialize() {
36+
hideError();
37+
38+
// Кнопки редактирования и удаления доступны только администраторам.
39+
var authService = services == null ? null : services.getAuthService();
40+
boolean isAdmin = authService != null && authService.isAdmin();
41+
42+
editButton.setVisible(isAdmin);
43+
editButton.setManaged(isAdmin);
44+
45+
deleteButton.setVisible(isAdmin);
46+
deleteButton.setManaged(isAdmin);
47+
}
48+
49+
/** Navigator sets the id after FXML load, so the setter triggers loading. */
50+
public void setUserId(UUID userId) {
51+
this.userId = userId;
52+
if (fullNameLabel != null && userId != null && services != null) {
53+
load();
54+
}
55+
}
56+
57+
// ===== Loading =====
58+
59+
private void load() {
60+
hideError();
61+
statusLabel.setText("Загрузка…");
62+
setContentVisible(false);
63+
64+
var task =
65+
new Task<User>() {
66+
@Override
67+
protected User call() {
68+
return services.getUsersService().getById(userId);
69+
}
70+
};
71+
72+
task.setOnSucceeded(
73+
e -> {
74+
current = task.getValue();
75+
statusLabel.setText("");
76+
if (current == null) {
77+
showError("Пользователь не найден");
78+
return;
79+
}
80+
showUser(current);
81+
setContentVisible(true);
82+
});
83+
84+
task.setOnFailed(
85+
e -> {
86+
statusLabel.setText("");
87+
var ex = task.getException();
88+
String msg =
89+
ex instanceof ServiceException se
90+
? se.getMessage()
91+
: "Не удалось загрузить пользователя";
92+
showError(msg);
93+
});
94+
95+
startDaemon(task, "user-details-load");
96+
}
97+
98+
private void showUser(User user) {
99+
String first = user.getFirstName() == null ? "" : user.getFirstName();
100+
String last = user.getLastName() == null ? "" : user.getLastName();
101+
String full = (first + " " + last).trim();
102+
fullNameLabel.setText(full.isEmpty() ? "Без имени" : full);
103+
104+
emailLabel.setText(user.getEmail() == null ? "" : user.getEmail());
105+
roleLabel.setText(user.getRole() == null ? "" : user.getRole().name());
106+
enabledLabel.setText(Boolean.TRUE.equals(user.getEnabled()) ? "Да" : "Нет");
107+
uuidLabel.setText(user.getUuid() == null ? "" : user.getUuid().toString());
108+
109+
updateDeleteButtonState(user);
110+
}
111+
112+
/**
113+
* Админ не может удалить собственную учётную запись. Кнопка видна только администраторам (см.
114+
* initialize), но дополнительно гасится, если просматривается именно текущий пользователь.
115+
*/
116+
private void updateDeleteButtonState(User user) {
117+
var authService = services == null ? null : services.getAuthService();
118+
var me = authService == null ? null : authService.getCurrentUser();
119+
boolean isSelf =
120+
me != null && user != null && user.getUuid() != null && user.getUuid().equals(me.getUuid());
121+
deleteButton.setDisable(isSelf);
122+
}
123+
124+
// ===== Event handlers =====
125+
126+
@FXML
127+
private void onBack(ActionEvent e) {
128+
navigator.goTo("/fxml/UserList.fxml");
129+
}
130+
131+
@FXML
132+
private void onEdit(ActionEvent e) {
133+
if (current == null || current.getUuid() == null) {
134+
return;
135+
}
136+
navigator.goTo(
137+
"/fxml/UserUpdateForm.fxml",
138+
c -> ((UserUpdateFormController) c).setUserId(current.getUuid()));
139+
}
140+
141+
@FXML
142+
private void onDelete(ActionEvent e) {
143+
if (current == null || current.getUuid() == null) {
144+
return;
145+
}
146+
147+
// Двойная защита: даже если кнопку как-то активировали, себя удалить нельзя.
148+
var authService = services == null ? null : services.getAuthService();
149+
var me = authService == null ? null : authService.getCurrentUser();
150+
if (me != null && current.getUuid().equals(me.getUuid())) {
151+
showError("Нельзя удалить собственную учётную запись");
152+
return;
153+
}
154+
155+
if (!confirmDelete(current)) {
156+
return;
157+
}
158+
159+
hideError();
160+
setBusy(true);
161+
162+
var uuid = current.getUuid();
163+
var task =
164+
new Task<Void>() {
165+
@Override
166+
protected Void call() {
167+
services.getUsersService().delete(uuid);
168+
return null;
169+
}
170+
};
171+
172+
task.setOnSucceeded(
173+
ev -> {
174+
setBusy(false);
175+
navigator.goTo("/fxml/UserList.fxml");
176+
});
177+
178+
task.setOnFailed(
179+
ev -> {
180+
setBusy(false);
181+
var ex = task.getException();
182+
String msg =
183+
ex instanceof ServiceException se
184+
? se.getMessage()
185+
: "Не удалось удалить пользователя";
186+
showError(msg);
187+
});
188+
189+
startDaemon(task, "user-delete");
190+
}
191+
192+
// ===== Confirmation dialog =====
193+
194+
private boolean confirmDelete(User user) {
195+
var alert = new Alert(Alert.AlertType.CONFIRMATION);
196+
alert.setTitle("Удаление пользователя");
197+
alert.setHeaderText(null);
198+
alert.setContentText(
199+
"Удалить пользователя \""
200+
+ (user.getEmail() == null ? user.getUuid().toString() : user.getEmail())
201+
+ "\"? Действие необратимо.");
202+
203+
var ok = new ButtonType("Удалить", ButtonBar.ButtonData.OK_DONE);
204+
var cancel = new ButtonType("Отмена", ButtonBar.ButtonData.CANCEL_CLOSE);
205+
alert.getButtonTypes().setAll(ok, cancel);
206+
207+
return alert.showAndWait().filter(ok::equals).isPresent();
208+
}
209+
210+
// ===== UI helpers =====
211+
212+
private void setContentVisible(boolean visible) {
213+
fullNameLabel.setVisible(visible);
214+
emailLabel.setVisible(visible);
215+
roleLabel.setVisible(visible);
216+
enabledLabel.setVisible(visible);
217+
uuidLabel.setVisible(visible);
218+
}
219+
220+
private void setBusy(boolean busy) {
221+
deleteButton.setDisable(busy);
222+
editButton.setDisable(busy);
223+
backButton.setDisable(busy);
224+
statusLabel.setText(busy ? "Удаление…" : "");
225+
}
226+
227+
private void showError(String message) {
228+
errorLabel.setText(message);
229+
errorLabel.setVisible(true);
230+
errorLabel.setManaged(true);
231+
}
232+
233+
private void hideError() {
234+
errorLabel.setText("");
235+
errorLabel.setVisible(false);
236+
errorLabel.setManaged(false);
237+
}
238+
239+
private static void startDaemon(Task<?> task, String name) {
240+
var thread = new Thread(task, name);
241+
thread.setDaemon(true);
242+
thread.start();
243+
}
244+
}

0 commit comments

Comments
 (0)