From ed8218a2b0d32e11306164f0c6bf4339b970862d Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Sat, 14 Jul 2018 23:02:07 -0500 Subject: [PATCH] ReactiveUserDetailsPasswordService Issue: gh-2778 --- .../MapReactiveUserDetailsService.java | 16 +++++++- .../ReactiveUserDetailsPasswordService.java | 37 +++++++++++++++++++ .../MapReactiveUserDetailsServiceTests.java | 6 +++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsPasswordService.java diff --git a/core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java b/core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java index ce44d886cd..45923a1e9f 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsService.java @@ -31,7 +31,7 @@ import reactor.core.publisher.Mono; * @author Rob Winch * @since 5.0 */ -public class MapReactiveUserDetailsService implements ReactiveUserDetailsService { +public class MapReactiveUserDetailsService implements ReactiveUserDetailsService, ReactiveUserDetailsPasswordService { private final Map users; /** @@ -66,6 +66,20 @@ public class MapReactiveUserDetailsService implements ReactiveUserDetailsService return result == null ? Mono.empty() : Mono.just(User.withUserDetails(result).build()); } + @Override + public Mono updatePassword(UserDetails user, String newPassword) { + return Mono.just(user) + .map(u -> + User.withUserDetails(u) + .password(newPassword) + .build() + ) + .doOnNext(u -> { + String key = getKey(user.getUsername()); + this.users.put(key, u); + }); + } + private String getKey(String username) { return username.toLowerCase(); } diff --git a/core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsPasswordService.java b/core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsPasswordService.java new file mode 100644 index 0000000000..1dcadf719a --- /dev/null +++ b/core/src/main/java/org/springframework/security/core/userdetails/ReactiveUserDetailsPasswordService.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.core.userdetails; + +import reactor.core.publisher.Mono; + +/** + * An API for changing a {@link UserDetails} password. + * @author Rob Winch + * @since 5.1 + */ +public interface ReactiveUserDetailsPasswordService { + + /** + * Modify the specified user's password. This should change the user's password in the + * persistent user repository (datbase, LDAP etc). + * + * @param user the user to modify the password for + * @param newPassword the password to change to + * @return the updated UserDetails with the new password + */ + Mono updatePassword(UserDetails user, String newPassword); +} diff --git a/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java b/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java index 5c8b701507..186c522bea 100644 --- a/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java +++ b/core/src/test/java/org/springframework/security/core/userdetails/MapReactiveUserDetailsServiceTests.java @@ -71,4 +71,10 @@ public class MapReactiveUserDetailsServiceTests { public void findByUsernameWhenNotFoundThenEmpty() { assertThat((users.findByUsername("notfound"))).isEqualTo(Mono.empty()); } + + @Test + public void updatePassword() { + users.updatePassword(USER_DETAILS, "new").block(); + assertThat(users.findByUsername(USER_DETAILS.getUsername()).block().getPassword()).isEqualTo("new"); + } }