Skip to content

Commit

Permalink
refactor: use spring session 3.3 to adapt
Browse files Browse the repository at this point in the history
  • Loading branch information
guqing committed Apr 22, 2024
1 parent 3f0ca78 commit d380c6b
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class InMemoryReactiveIndexedSessionRepository extends ReactiveMapSession
implements ReactiveIndexedSessionRepository<MapSession>, DisposableBean {

final IndexResolver<MapSession> indexResolver =
new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>(PRINCIPAL_NAME_INDEX_NAME));

private final ConcurrentMap<String, Set<IndexKey>> sessionIdIndexMap =
new ConcurrentHashMap<>();
Expand All @@ -35,14 +35,49 @@ public Mono<Void> save(MapSession session) {
.then(updateIndex(session));
}

Mono<Void> updateIndex(MapSession session) {
return getIndexes(session.getId())
.doOnNext(originalIndex -> indexSessionIdMap.computeIfPresent(originalIndex,
@Override
public Mono<Void> deleteById(String id) {
return super.deleteById(id)
.then(removeIndex(id));
}

@Override
public Mono<Map<String, MapSession>> findByIndexNameAndIndexValue(String indexName,
String indexValue) {
var indexKey = new IndexKey(indexName, indexValue);
return Flux.fromIterable(indexSessionIdMap.getOrDefault(indexKey, Set.of()))
.flatMap(this::findById)
.collectMap(Session::getId);
}

@Override
public Mono<Map<String, MapSession>> findByPrincipalName(String principalName) {
return this.findByIndexNameAndIndexValue(PRINCIPAL_NAME_INDEX_NAME, principalName);
}

@Override
public void destroy() {
sessionIdIndexMap.clear();
indexSessionIdMap.clear();
}

Mono<Void> removeIndex(String sessionId) {
return getIndexes(sessionId)
.doOnNext(indexKey -> indexSessionIdMap.computeIfPresent(indexKey,
(key, sessionIdSet) -> {
sessionIdSet.remove(session.getId());
sessionIdSet.remove(sessionId);
return sessionIdSet.isEmpty() ? null : sessionIdSet;
})
)
.then(Mono.defer(() -> {
sessionIdIndexMap.remove(sessionId);
return Mono.empty();
}))
.then();
}

Mono<Void> updateIndex(MapSession session) {
return removeIndex(session.getId())
.then(Mono.defer(() -> {
indexResolver.resolveIndexesFor(session)
.forEach((name, value) -> {
Expand All @@ -64,19 +99,18 @@ Flux<IndexKey> getIndexes(String sessionId) {
return Flux.fromIterable(sessionIdIndexMap.getOrDefault(sessionId, Set.of()));
}

@Override
public Mono<Map<String, MapSession>> findByIndexNameAndIndexValue(String indexName,
String indexValue) {
var indexKey = new IndexKey(indexName, indexValue);
return Flux.fromIterable(indexSessionIdMap.getOrDefault(indexKey, Set.of()))
.flatMap(this::findById)
.collectMap(Session::getId);
/**
* For testing purpose.
*/
ConcurrentMap<String, Set<IndexKey>> getSessionIdIndexMap() {
return sessionIdIndexMap;
}

@Override
public void destroy() {
sessionIdIndexMap.clear();
indexSessionIdMap.clear();
/**
* For testing purpose.
*/
ConcurrentMap<IndexKey, Set<String>> getIndexSessionIdMap() {
return indexSessionIdMap;
}

record IndexKey(String attributeName, String attributeValue) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package run.halo.app.security.session;

import org.springframework.session.ReactiveFindByIndexNameSessionRepository;
import org.springframework.session.ReactiveSessionRepository;
import org.springframework.session.Session;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.session.ReactiveFindByIndexNameSessionRepository;
import org.springframework.session.ReactiveSessionRepository;
import org.springframework.session.Session;
import org.springframework.stereotype.Component;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package run.halo.app.security.session;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.session.ReactiveFindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import reactor.test.StepVerifier;

/**
* Tests for {@link InMemoryReactiveIndexedSessionRepository}.
*
* @author guqing
* @since 2.15.0
*/
class InMemoryReactiveIndexedSessionRepositoryTest {
private InMemoryReactiveIndexedSessionRepository sessionRepository;

Expand All @@ -19,15 +27,81 @@ void setUp() {
void principalNameIndexTest() {
sessionRepository.createSession()
.doOnNext(session -> {
session.setAttribute(ReactiveIndexedSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
session.setAttribute(PRINCIPAL_NAME_INDEX_NAME,
"test");
})
.map(session -> sessionRepository.indexResolver.resolveIndexesFor(session))
.as(StepVerifier::create)
.consumeNextWith(map -> {
assertThat(map).containsEntry(
ReactiveIndexedSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
PRINCIPAL_NAME_INDEX_NAME,
"test");
});

sessionRepository.findByPrincipalName("test")
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();

sessionRepository.findByIndexNameAndIndexValue(
PRINCIPAL_NAME_INDEX_NAME, "test")
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}

@Test
void saveTest() {
var indexKey = createSession("fake-session-1", "test");

assertThat(sessionRepository.getSessionIdIndexMap()).hasSize(1);
assertThat(
sessionRepository.getSessionIdIndexMap().containsValue(Set.of(indexKey))).isTrue();

assertThat(sessionRepository.getIndexSessionIdMap()).hasSize(1);
assertThat(sessionRepository.getIndexSessionIdMap().containsKey(indexKey)).isTrue();
assertThat(sessionRepository.getIndexSessionIdMap().get(indexKey)).isEqualTo(
Set.of("fake-session-1"));
}

@Test
void saveToUpdateTest() {
// same session id will update the index
createSession("fake-session-1", "test");
var indexKey2 = createSession("fake-session-1", "test2");

assertThat(sessionRepository.getSessionIdIndexMap()).hasSize(1);
assertThat(
sessionRepository.getSessionIdIndexMap().containsValue(Set.of(indexKey2))).isTrue();

assertThat(sessionRepository.getIndexSessionIdMap()).hasSize(1);
assertThat(sessionRepository.getIndexSessionIdMap().containsKey(indexKey2)).isTrue();
assertThat(sessionRepository.getIndexSessionIdMap().get(indexKey2)).isEqualTo(
Set.of("fake-session-1"));
}

@Test
void deleteByIdTest() {
createSession("fake-session-2", "test1");
sessionRepository.deleteById("fake-session-2")
.as(StepVerifier::create)
.verifyComplete();
assertThat(sessionRepository.getSessionIdIndexMap()).isEmpty();
assertThat(sessionRepository.getIndexSessionIdMap()).isEmpty();
}

InMemoryReactiveIndexedSessionRepository.IndexKey createSession(String sessionId,
String principalName) {
var indexKey = new InMemoryReactiveIndexedSessionRepository.IndexKey(
PRINCIPAL_NAME_INDEX_NAME, principalName);
sessionRepository.createSession()
.doOnNext(session -> {
session.setAttribute(indexKey.attributeName(), indexKey.attributeValue());
session.setId(sessionId);
})
.flatMap(sessionRepository::save)
.as(StepVerifier::create)
.verifyComplete();
return indexKey;
}
}

This file was deleted.

0 comments on commit d380c6b

Please sign in to comment.