readd secure avatar endpoints
This commit was merged in pull request #47.
This commit is contained in:
@@ -48,6 +48,31 @@ public class ApiClient {
|
||||
return handleResponse(response, responseClass);
|
||||
}
|
||||
|
||||
public byte[] getBytes(String path) throws Exception {
|
||||
HttpRequest.Builder builder = HttpRequest.newBuilder()
|
||||
.uri(URI.create(baseUrl + path))
|
||||
.GET()
|
||||
.timeout(Duration.ofSeconds(30));
|
||||
|
||||
addAuthHeader(builder);
|
||||
|
||||
HttpRequest request = builder.build();
|
||||
HttpResponse<byte[]> response = httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray());
|
||||
|
||||
int statusCode = response.statusCode();
|
||||
if (statusCode == 200 || statusCode == 201) {
|
||||
return response.body();
|
||||
} else if (statusCode == 401) {
|
||||
throw new RuntimeException("Authentication failed. Please log in again.");
|
||||
} else if (statusCode == 403) {
|
||||
throw new RuntimeException("Access restricted. You don't have permission to perform this action.");
|
||||
} else if (statusCode == 404) {
|
||||
throw new RuntimeException("Avatar not found.");
|
||||
} else {
|
||||
throw new RuntimeException("Request failed with status " + statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public String getRawResponse(String path) throws Exception {
|
||||
HttpRequest.Builder builder = HttpRequest.newBuilder()
|
||||
.uri(URI.create(baseUrl + path))
|
||||
|
||||
@@ -26,6 +26,10 @@ public class AuthApi {
|
||||
return apiClient.postMultipart("/api/v1/auth/me/avatar", "avatar", filePath, AvatarUploadResponse.class);
|
||||
}
|
||||
|
||||
public byte[] getMyAvatarFile() throws Exception {
|
||||
return apiClient.getBytes("/api/v1/auth/me/avatar/file");
|
||||
}
|
||||
|
||||
public void deleteAvatar() throws Exception {
|
||||
apiClient.delete("/api/v1/auth/me/avatar");
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import javafx.scene.paint.ImagePattern;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import org.example.petshopdesktop.api.ApiConfig;
|
||||
import org.example.petshopdesktop.api.ChatRealtimeClient;
|
||||
import org.example.petshopdesktop.api.dto.auth.AvatarUploadResponse;
|
||||
import org.example.petshopdesktop.api.dto.auth.UserInfoResponse;
|
||||
@@ -27,6 +26,8 @@ import org.example.petshopdesktop.auth.UserSession;
|
||||
import org.example.petshopdesktop.ui.SvgWebViewFactory;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
public class MainLayoutController {
|
||||
|
||||
private static final String NAV_BASE_STYLE = "-fx-background-color: transparent; " +
|
||||
@@ -218,8 +219,7 @@ public class MainLayoutController {
|
||||
try {
|
||||
AvatarUploadResponse response = AuthApi.getInstance().uploadAvatar(file.toPath());
|
||||
UserSession.getInstance().setAvatarUrl(response.getAvatarUrl());
|
||||
renderAvatar(UserSession.getInstance().getEmployeeName(), response.getAvatarUrl());
|
||||
btnRemoveAvatar.setDisable(response.getAvatarUrl() == null || response.getAvatarUrl().isBlank());
|
||||
refreshProfileHeader();
|
||||
} catch (Exception e) {
|
||||
ActivityLogger.getInstance().logException("MainLayoutController.btnChangeAvatarClicked", e, "Uploading avatar");
|
||||
showAvatarError(e.getMessage() != null ? e.getMessage() : "Could not upload profile picture.");
|
||||
@@ -263,7 +263,7 @@ public class MainLayoutController {
|
||||
@FXML
|
||||
public void initialize() {
|
||||
logoContainer.getChildren().setAll(SvgWebViewFactory.build("/org/example/petshopdesktop/images/leons-pet-store-badge-light.svg", 94));
|
||||
renderAvatar(UserSession.getInstance().getEmployeeName(), UserSession.getInstance().getAvatarUrl());
|
||||
renderAvatar(UserSession.getInstance().getEmployeeName(), null);
|
||||
btnRemoveAvatar.setDisable(UserSession.getInstance().getAvatarUrl() == null || UserSession.getInstance().getAvatarUrl().isBlank());
|
||||
refreshProfileHeader();
|
||||
applyRBAC();
|
||||
@@ -285,20 +285,35 @@ public class MainLayoutController {
|
||||
String displayName = userInfo.getFullName() == null || userInfo.getFullName().isBlank()
|
||||
? UserSession.getInstance().getUsername()
|
||||
: userInfo.getFullName();
|
||||
Image avatarImage = loadAvatarImage(userInfo.getAvatarUrl());
|
||||
Platform.runLater(() -> {
|
||||
UserSession.getInstance().setEmployeeName(displayName);
|
||||
UserSession.getInstance().setAvatarUrl(userInfo.getAvatarUrl());
|
||||
lblUsername.setText(displayName);
|
||||
renderAvatar(displayName, userInfo.getAvatarUrl());
|
||||
renderAvatar(displayName, avatarImage);
|
||||
btnRemoveAvatar.setDisable(userInfo.getAvatarUrl() == null || userInfo.getAvatarUrl().isBlank());
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Platform.runLater(() -> renderAvatar(UserSession.getInstance().getEmployeeName(), UserSession.getInstance().getAvatarUrl()));
|
||||
Platform.runLater(() -> renderAvatar(UserSession.getInstance().getEmployeeName(), null));
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void renderAvatar(String displayName, String avatarUrl) {
|
||||
private Image loadAvatarImage(String avatarUrl) {
|
||||
if (avatarUrl == null || avatarUrl.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] imageBytes = AuthApi.getInstance().getMyAvatarFile();
|
||||
Image image = new Image(new ByteArrayInputStream(imageBytes), 52, 52, true, true);
|
||||
return image.isError() ? null : image;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void renderAvatar(String displayName, Image avatarImage) {
|
||||
Circle border = new Circle(29);
|
||||
border.setFill(Color.web("#dbe4ee"));
|
||||
|
||||
@@ -306,21 +321,9 @@ public class MainLayoutController {
|
||||
Label initials = new Label(initials(displayName));
|
||||
initials.setStyle("-fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 16px;");
|
||||
|
||||
if (avatarUrl != null && !avatarUrl.isBlank()) {
|
||||
try {
|
||||
String resolvedUrl = avatarUrl.startsWith("http") ? avatarUrl : ApiConfig.getInstance().getBaseUrl() + avatarUrl;
|
||||
Image image = new Image(resolvedUrl, 52, 52, true, true, true);
|
||||
if (!image.isError()) {
|
||||
circle.setFill(new ImagePattern(image));
|
||||
initials.setVisible(false);
|
||||
} else {
|
||||
circle.setFill(Color.web("#4ECDC4"));
|
||||
initials.setVisible(true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
circle.setFill(Color.web("#4ECDC4"));
|
||||
initials.setVisible(true);
|
||||
}
|
||||
if (avatarImage != null) {
|
||||
circle.setFill(new ImagePattern(avatarImage));
|
||||
initials.setVisible(false);
|
||||
} else {
|
||||
circle.setFill(Color.web("#4ECDC4"));
|
||||
initials.setVisible(true);
|
||||
|
||||
Reference in New Issue
Block a user