Skip to content

Instantly share code, notes, and snippets.

@arleighdickerson
Created December 12, 2024 17:45
Show Gist options
  • Save arleighdickerson/e1bf02859b9db61457e60d049955dfe8 to your computer and use it in GitHub Desktop.
Save arleighdickerson/e1bf02859b9db61457e60d049955dfe8 to your computer and use it in GitHub Desktop.
package com.teletapper.actuator;
import com.teletapper.util.SecurityUtils;
import lombok.Data;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxEndpoint;
import org.springframework.messaging.simp.user.SimpUser;
import org.springframework.messaging.simp.user.SimpUserRegistry;
import org.springframework.stereotype.Component;
import java.security.Principal;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
// ============================================================================
// scratch.sh
/**
* #!/bin/bash set -e ./gradlew services:bootJar java -javaagent:spring-instrument.jar -javaagent:aspectjweaver.jar -jar
* services/build/libs/services-0.0-SNAPSHOT.jar --spring.profiles.active=dev,local --server.port=${PORT-8081}
*/
// ============================================================================
// $ PORT=8082 ./scratch.sh
// $ PROXY_HOST=http://localhost:8082 PORT=3002 HOST=localhost yarn dev
// (invoke rest per usual w/ visualvm)
// open provider mode conn and client mode conn on webclient 3001/3002
// check the visualvm bean, we can see that the vm on 8081 knows about both users
// ■
@JmxEndpoint(id = "registry")
@Component
@Slf4j
class UserRegistryActuatorEndpoint {
// @Setter(onMethod_ = @Autowired)
// private ModelMapper modelMapper;
@Setter(onMethod_ = @Autowired)
private SimpUserRegistry userRegistry;
@ReadOperation
public Map<String, Object> getUsers() {
// locate clients for a given provider by
// userRegistry.findSubscriptions(subscription -> subscription.getDestination().equals("/provider/abc"))
//
// userRegistry.findSubscriptions(subscription -> subscription.getSession().getUser().getName().equals("provider"));
//userRegistry.findSubscriptions("provider")
val user = userRegistry.getUser("arleigh");
if (user != null) {
log.debug("{}", user.getSessions());
}
val users = userRegistry.getUsers();
return users.stream()
.map(this::convert)
.collect(Collectors.toMap(SimpUserDto::getName, Function.identity()));
}
private SimpUserDto convert(SimpUser user) {
val userDto = new SimpUserDto();
userDto.setName(user.getName());
userDto.setPrincipal(user.getPrincipal());
userDto.setPrincipalName(SecurityUtils.getPrincipalName(user.getPrincipal()));
userDto.setPrincipalDestinationName(SecurityUtils.getPrincipalDestinationName(user.getPrincipal()));
userDto.setSessions(
user.getSessions()
.stream()
.map(session -> {
val sessionDto = new SimpSessionDto();
sessionDto.setId(session.getId());
sessionDto.setSubscriptions(session.getSubscriptions().stream().map(sub -> {
val subDto = new SimpSubscriptionDto();
subDto.setId(sub.getId());
subDto.setDestination(sub.getDestination());
return subDto;
}).collect(Collectors.toSet()));
return sessionDto;
})
.collect(Collectors.toSet())
);
return userDto;
}
@Data
static class SimpUserDto {
private String name;
private Principal principal;
private String principalName;
private String principalDestinationName;
private Set<SimpSessionDto> sessions = new HashSet<>();
}
@Data
static class SimpSessionDto {
private String id;
private Set<SimpSubscriptionDto> subscriptions = new HashSet<>();
}
@Data
static class SimpSubscriptionDto {
private String id;
private String destination;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment