feat: add password verify and role management methods to LogtoManagementClient

Adds verifyUserPassword (for current-password check before password change) and
four global role methods (listRoleUsers, getRoleByName, assignGlobalRole,
revokeGlobalRole) needed by the upcoming AccountService and VendorAdminService.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-27 14:36:59 +02:00
parent 316e5ef6c1
commit 19428b4e27

View File

@@ -526,6 +526,26 @@ public class LogtoManagementClient {
.toBodilessEntity();
}
/** Verify a user's current password. Returns true if correct, false if wrong. */
public boolean verifyUserPassword(String userId, String password) {
try {
var token = getAccessToken();
restClient.post()
.uri(config.getLogtoEndpoint() + "/api/users/" + userId + "/password/verify")
.header("Authorization", "Bearer " + token)
.contentType(MediaType.APPLICATION_JSON)
.body(Map.of("password", password))
.retrieve()
.toBodilessEntity();
return true;
} catch (org.springframework.web.client.HttpClientErrorException e) {
if (e.getStatusCode().value() == 422 || e.getStatusCode().value() == 400) {
return false;
}
throw e;
}
}
// --- MFA Verification Management ---
/** List all MFA verifications for a user. Returns a list of MFA factor objects. */
@@ -673,6 +693,60 @@ public class LogtoManagementClient {
}
}
// --- Global Role Management ---
/** List all users assigned to a global role. */
@SuppressWarnings("unchecked")
public List<Map<String, Object>> listRoleUsers(String roleId) {
var token = getAccessToken();
var response = restClient.get()
.uri(config.getLogtoEndpoint() + "/api/roles/" + roleId + "/users?page=1&page_size=200")
.header("Authorization", "Bearer " + token)
.retrieve()
.body(List.class);
return response != null ? response : List.of();
}
/** Find a global role by exact name. Returns null if not found. */
@SuppressWarnings("unchecked")
public Map<String, Object> getRoleByName(String roleName) {
var token = getAccessToken();
var response = restClient.get()
.uri(config.getLogtoEndpoint() + "/api/roles?search=" +
java.net.URLEncoder.encode(roleName, java.nio.charset.StandardCharsets.UTF_8) +
"&page=1&page_size=20")
.header("Authorization", "Bearer " + token)
.retrieve()
.body(List.class);
if (response == null) return null;
return ((List<Map<String, Object>>) response).stream()
.filter(r -> roleName.equals(r.get("name")))
.findFirst()
.orElse(null);
}
/** Assign a global role to a user. */
public void assignGlobalRole(String userId, String roleId) {
var token = getAccessToken();
restClient.post()
.uri(config.getLogtoEndpoint() + "/api/roles/" + roleId + "/users")
.header("Authorization", "Bearer " + token)
.contentType(MediaType.APPLICATION_JSON)
.body(Map.of("userIds", List.of(userId)))
.retrieve()
.toBodilessEntity();
}
/** Revoke a global role from a user. */
public void revokeGlobalRole(String userId, String roleId) {
var token = getAccessToken();
restClient.delete()
.uri(config.getLogtoEndpoint() + "/api/roles/" + roleId + "/users/" + userId)
.header("Authorization", "Bearer " + token)
.retrieve()
.toBodilessEntity();
}
private static final String MGMT_API_RESOURCE = "https://default.logto.app/api";
private synchronized String getAccessToken() {