Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

import com.openblocks.domain.user.model.AuthorizedUser;
import com.openblocks.domain.user.model.Connection;
import com.openblocks.domain.user.model.UserDetail;
import com.openblocks.domain.user.model.User;
import com.openblocks.domain.user.model.UserDetail;
import com.openblocks.infra.annotation.NonEmptyMono;

import reactor.core.publisher.Mono;
Expand Down Expand Up @@ -45,6 +45,8 @@ public interface UserService {

Mono<Boolean> updatePassword(String userId, String oldPassword, String newPassword);

Mono<String> resetPassword(String userId);

Mono<Boolean> setPassword(String userId, String password);

Mono<UserDetail> buildUserDetail(User user, boolean withoutDynamicGroups);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static com.openblocks.sdk.util.ExceptionUtils.ofError;
import static com.openblocks.sdk.util.ExceptionUtils.ofException;

import java.security.SecureRandom;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
Expand All @@ -17,9 +18,11 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.codec.multipart.Part;
Expand All @@ -37,9 +40,9 @@
import com.openblocks.domain.organization.service.OrgMemberService;
import com.openblocks.domain.user.model.AuthorizedUser;
import com.openblocks.domain.user.model.Connection;
import com.openblocks.domain.user.model.UserDetail;
import com.openblocks.domain.user.model.User;
import com.openblocks.domain.user.model.User.TransformedUserInfo;
import com.openblocks.domain.user.model.UserDetail;
import com.openblocks.domain.user.model.UserState;
import com.openblocks.domain.user.repository.UserRepository;
import com.openblocks.infra.mongo.MongoUpsertHelper;
Expand Down Expand Up @@ -245,6 +248,31 @@ public Mono<Boolean> updatePassword(String userId, String oldPassword, String ne
.thenReturn(true);
}

@Override
public Mono<String> resetPassword(String userId) {
return findById(userId)
.flatMap(user -> {
String password = user.getPassword();
if (StringUtils.isBlank(password)) {
return ofError(BizError.INVALID_PASSWORD, "PASSWORD_NOT_SET_YET");
}

String randomStr = generateNewRandomPwd();
user.setPassword(encryptionService.encryptPassword(randomStr));
return repository.save(user)
.thenReturn(randomStr);
});
}

@SuppressWarnings("SpellCheckingInspection")
@Nonnull
private static String generateNewRandomPwd() {
char[] possibleCharacters = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*()-_=+[{]}<>?")
.toCharArray();
return RandomStringUtils.random(12, 0, possibleCharacters.length - 1,
false, false, possibleCharacters, new SecureRandom());
}

@Override
public Mono<Boolean> setPassword(String userId, String password) {
return findById(userId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ public boolean isSelfHost() {
return !isCloud();
}

public boolean isEnterpriseMode() {
return workspace.getMode() == WorkspaceMode.ENTERPRISE;
}

@Data
public static class Domain {
private String defaultValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ USER_NOT_SIGNED_IN=Unknown user, you have to log in first.
FAIL_TO_GET_OIDC_INFO=Failed to get OIDC information, error message: {0}.
LOG_IN_SOURCE_NOT_SUPPORTED=Sorry, this log in channel is not supported.
USER_LOGIN_ID_EXIST=Current email already used by another user.
INVALID_PASSWORD=Sorry, passwords do not match, please retype.
INVALID_PASSWORD=Sorry, passwords do not match.
PASSWORD_NOT_SET_YET=This user hasn't set password yet and cannot be reset.
INVALID_EMAIL_OR_PASSWORD=Invalid email or password.
ALREADY_BIND=Sorry, {0} has been bound by user {1}.
NEED_BIND_THIRD_PARTY_CONNECTION=Sorry, it needs to bind the current workspace login channel.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ public class UserApiService {
private UserService userService;

public Mono<UserDetail> getUserDetailById(String userId) {
return checkPermission(userId)
return checkAdminPermissionAndUserBelongsToCurrentOrg(userId)
.then(userService.findById(userId)
.flatMap(user -> userService.buildUserDetail(user, false)));
}

private Mono<Void> checkPermission(String userId) {
return sessionUserService.getVisitorOrgMember()
private Mono<Void> checkAdminPermissionAndUserBelongsToCurrentOrg(String userId) {
return sessionUserService.getVisitorOrgMemberCache()
.flatMap(orgMember -> {
if (!orgMember.isAdmin()) {
return ofError(UNSUPPORTED_OPERATION, "BAD_REQUEST");
Expand All @@ -50,4 +50,8 @@ private Mono<Void> checkPermission(String userId) {
});
}

public Mono<String> resetPassword(String userId) {
return checkAdminPermissionAndUserBelongsToCurrentOrg(userId)
.then(userService.resetPassword(userId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.openblocks.domain.user.service.UserStatusService;
import com.openblocks.infra.constant.NewUrl;
import com.openblocks.infra.constant.Url;
import com.openblocks.sdk.config.CommonConfig;
import com.openblocks.sdk.exception.BizError;
import com.openblocks.sdk.util.UriUtils;

Expand Down Expand Up @@ -61,6 +62,9 @@ public class UserController {
@Autowired
private UserApiService userApiService;

@Autowired
private CommonConfig commonConfig;

@GetMapping("/me")
public Mono<ResponseView<?>> getUserProfile(ServerWebExchange exchange) {
String domain = UriUtils.getRefererDomain(exchange);
Expand Down Expand Up @@ -133,11 +137,23 @@ public Mono<Void> getProfilePhoto(ServerWebExchange exchange, @PathVariable Stri

@PutMapping("/password")
public Mono<ResponseView<Boolean>> updatePassword(@RequestBody UpdatePasswordRequest request) {
if (StringUtils.isBlank(request.oldPassword) || StringUtils.isBlank(request.newPassword)) {
if (StringUtils.isBlank(request.oldPassword()) || StringUtils.isBlank(request.newPassword())) {
return ofError(BizError.INVALID_PARAMETER, "PASSWORD_EMPTY");
}
return sessionUserService.getVisitorId()
.flatMap(user -> userService.updatePassword(user, request.oldPassword, request.newPassword))
.flatMap(user -> userService.updatePassword(user, request.oldPassword(), request.newPassword()))
.map(ResponseView::success);
}

@PostMapping("/reset-password")
public Mono<ResponseView<String>> resetPassword(@RequestBody ResetPasswordRequest request) {
if (!commonConfig.isEnterpriseMode()) {
return ofError(BizError.UNSUPPORTED_OPERATION, "BAD_REQUEST");
}
if (StringUtils.isBlank(request.userId())) {
return ofError(BizError.INVALID_PARAMETER, "INVALID_USER_ID");
}
return userApiService.resetPassword(request.userId())
.map(ResponseView::success);

}
Expand Down Expand Up @@ -165,6 +181,9 @@ public Mono<ResponseView<?>> getUserDetail(@PathVariable("id") String userId) {
.map(ResponseView::success);
}

public record ResetPasswordRequest(String userId) {
}

public record UpdatePasswordRequest(String oldPassword, String newPassword) {
}

Expand Down