This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-paimon-webui.git
The following commit(s) were added to refs/heads/main by this push:
new 6b61132 Feat ldap login (#21)
6b61132 is described below
commit 6b611323024ffea04bd35ed58b69bbf82d936063
Author: G-XD <[email protected]>
AuthorDate: Wed Aug 16 14:37:37 2023 +0800
Feat ldap login (#21)
---
paimon-web-server/pom.xml | 10 ++
.../server/configrue/GlobalExceptionHandler.java | 46 ++++++++
.../web/server/controller/LoginController.java | 10 +-
.../paimon/web/server/data/dto/LoginDto.java | 38 ++++++
.../paimon/web/server/data/enums/UserType.java | 43 +++++++
.../web/server/data/result/enums/Status.java | 6 +-
.../exception/user/UserDisabledException.java} | 40 ++-----
.../service/{UserService.java => LdapService.java} | 38 +++---
.../web/server/service/PermissionService.java | 1 -
.../paimon/web/server/service/SysRoleService.java | 6 +-
.../paimon/web/server/service/UserService.java | 6 +-
.../web/server/service/impl/LdapServiceImpl.java | 131 +++++++++++++++++++++
.../web/server/service/impl/UserServiceImpl.java | 55 ++++++++-
.../src/main/resources/application-dev.yml | 8 +-
.../src/main/resources/i18n/messages.properties | 4 +-
.../main/resources/i18n/messages_en_US.properties | 4 +-
.../main/resources/i18n/messages_zh_CN.properties | 4 +-
.../src/main/resources/mapper/SysRoleMapper.xml | 2 +-
.../web/server/controller/PermissionTest.java | 8 +-
.../server/controller/SysMenuControllerTest.java | 8 +-
.../server/controller/SysRoleControllerTest.java | 8 +-
21 files changed, 390 insertions(+), 86 deletions(-)
diff --git a/paimon-web-server/pom.xml b/paimon-web-server/pom.xml
index 993f48e..ca9b0ac 100644
--- a/paimon-web-server/pom.xml
+++ b/paimon-web-server/pom.xml
@@ -129,6 +129,16 @@ under the License.
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-ldap</artifactId>
+ </dependency>
+
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/GlobalExceptionHandler.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/GlobalExceptionHandler.java
index f8de4da..fa4f5cb 100644
---
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/GlobalExceptionHandler.java
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/GlobalExceptionHandler.java
@@ -26,14 +26,27 @@ import
org.apache.paimon.web.server.data.result.exception.BaseException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.validation.BindException;
+import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
/** GlobalExceptionHandler. */
@Slf4j
@ControllerAdvice
@@ -73,6 +86,39 @@ public class GlobalExceptionHandler {
return R.failed(Status.UNKNOWN_ERROR, "sql error");
}
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(BindException.class)
+ public R<Void> bindExceptionHandler(BindException e) {
+ List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
+ Optional<String> msg =
+ fieldErrors.stream()
+ .filter(Objects::nonNull)
+ .map(DefaultMessageSourceResolvable::getDefaultMessage)
+ .filter(StringUtils::isNotBlank)
+ .findFirst();
+ return msg.<R<Void>>map(s -> R.failed(Status.REQUEST_PARAMS_ERROR, s))
+ .orElseGet(() -> R.failed(Status.REQUEST_PARAMS_ERROR));
+ }
+
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(ConstraintViolationException.class)
+ public R<Void>
constraintViolationExceptionHandler(ConstraintViolationException e) {
+ Set<ConstraintViolation<?>> constraintViolations =
e.getConstraintViolations();
+ Optional<String> msg =
+ constraintViolations.stream()
+ .filter(Objects::nonNull)
+ .map(ConstraintViolation::getMessage)
+ .findFirst();
+ return msg.<R<Void>>map(s -> R.failed(Status.REQUEST_PARAMS_ERROR, s))
+ .orElseGet(() -> R.failed(Status.REQUEST_PARAMS_ERROR));
+ }
+
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(HttpMessageNotReadableException.class)
+ public R<Void>
constraintViolationExceptionHandler(HttpMessageNotReadableException e) {
+ return R.failed(Status.REQUEST_PARAMS_ERROR, "Required request body is
missing");
+ }
+
@ExceptionHandler
public R<Void> unknownException(Exception e) {
log.error("UnknownException", e);
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/LoginController.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/LoginController.java
index 3db7dd2..b209464 100644
---
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/LoginController.java
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/LoginController.java
@@ -18,6 +18,7 @@
package org.apache.paimon.web.server.controller;
+import org.apache.paimon.web.server.data.dto.LoginDto;
import org.apache.paimon.web.server.data.result.R;
import org.apache.paimon.web.server.service.UserService;
@@ -25,8 +26,10 @@ import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -41,13 +44,12 @@ public class LoginController {
/**
* login by username and password.
*
- * @param username username
- * @param password password
+ * @param loginDto login info
* @return token string
*/
@PostMapping("/login")
- public R<String> login(String username, String password) {
- return R.succeed(userService.login(username, password));
+ public R<String> login(@Validated @RequestBody LoginDto loginDto) {
+ return R.succeed(userService.login(loginDto));
}
/**
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/dto/LoginDto.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/dto/LoginDto.java
new file mode 100644
index 0000000..1e23c7b
--- /dev/null
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/dto/LoginDto.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.paimon.web.server.data.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/** login dto. */
+@Data
+public class LoginDto {
+ /** login username. */
+ @NotBlank(message = "username is required")
+ private String username;
+ /** login password. */
+ @NotBlank(message = "password is required")
+ private String password;
+ /** remember me flag. */
+ private boolean rememberMe;
+ /** ldap login flag. */
+ private boolean ldapLogin;
+}
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/enums/UserType.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/enums/UserType.java
new file mode 100644
index 0000000..5d1e257
--- /dev/null
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/enums/UserType.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.paimon.web.server.data.enums;
+
+/** user type. */
+public enum UserType {
+ /** ldap user. */
+ LDAP(1, "LDAP"),
+ /** local user. */
+ LOCAL(0, "LOCAL");
+
+ private final int code;
+ private final String type;
+
+ public int getCode() {
+ return this.code;
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ UserType(int code, String type) {
+ this.code = code;
+ this.type = type;
+ }
+}
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
index c8dc0d3..27283ba 100644
---
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java
@@ -36,11 +36,13 @@ public enum Status {
// TODO
UNKNOWN_ERROR(500, "unknown.error"),
INTERNAL_SERVER_ERROR_ARGS(501, "internal.server.error"),
- REQUEST_PARAMS_NOT_VALID_ERROR(7002, "invalid.request.parameter"),
- REQUEST_PARAMS_ERROR(7003, "request.parameter.error"),
+
+ REQUEST_PARAMS_NOT_VALID_ERROR(4001, "invalid.request.parameter"),
+ REQUEST_PARAMS_ERROR(4002, "request.parameter.error"),
USER_NOT_EXIST(10001, "user.not.exist"),
USER_PASSWORD_ERROR(10002, "user.password.error"),
+ USER_DISABLED_ERROR(10003, "user.is.disabled"),
/** ------------role-----------------. */
ROLE_IN_USED(10101, "role.in.used"),
ROLE_NAME_IS_EXIST(10102, "role.name.exist"),
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/UserService.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/exception/user/UserDisabledException.java
similarity index 51%
copy from
paimon-web-server/src/main/java/org/apache/paimon/web/server/service/UserService.java
copy to
paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/exception/user/UserDisabledException.java
index e0bd750..01341cc 100644
---
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/UserService.java
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/exception/user/UserDisabledException.java
@@ -16,40 +16,16 @@
* limitations under the License.
*/
-package org.apache.paimon.web.server.service;
+package org.apache.paimon.web.server.data.result.exception.user;
-import org.apache.paimon.web.server.data.model.User;
+import org.apache.paimon.web.server.data.result.enums.Status;
import org.apache.paimon.web.server.data.result.exception.BaseException;
-import com.baomidou.mybatisplus.extension.service.IService;
+/** Exception to user disabled. */
+public class UserDisabledException extends BaseException {
+ private static final long serialVersionUID = 1L;
-import java.util.List;
-
-/** User Service. */
-public interface UserService extends IService<User> {
-
- /**
- * login by username and password.
- *
- * @param username username
- * @param password pwd
- * @return {@link String}
- */
- String login(String username, String password) throws BaseException;
-
- /**
- * Query the list of assigned user roles.
- *
- * @param user query params
- * @return user list
- */
- List<User> selectAllocatedList(User user);
-
- /**
- * Query the list of unassigned user roles.
- *
- * @param user query params
- * @return user list
- */
- List<User> selectUnallocatedList(User user);
+ public UserDisabledException() {
+ super(Status.USER_DISABLED_ERROR);
+ }
}
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/UserService.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/LdapService.java
similarity index 55%
copy from
paimon-web-server/src/main/java/org/apache/paimon/web/server/service/UserService.java
copy to
paimon-web-server/src/main/java/org/apache/paimon/web/server/service/LdapService.java
index e0bd750..a28f80a 100644
---
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/UserService.java
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/LdapService.java
@@ -19,37 +19,27 @@
package org.apache.paimon.web.server.service;
import org.apache.paimon.web.server.data.model.User;
-import org.apache.paimon.web.server.data.result.exception.BaseException;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-import java.util.List;
-
-/** User Service. */
-public interface UserService extends IService<User> {
-
- /**
- * login by username and password.
- *
- * @param username username
- * @param password pwd
- * @return {@link String}
- */
- String login(String username, String password) throws BaseException;
+import java.util.Optional;
+/** ldap service. */
+public interface LdapService {
/**
- * Query the list of assigned user roles.
+ * get user info by ldap user identification.
*
- * @param user query params
- * @return user list
+ * @param uid login name of ldap user
+ * @return {@link Optional} of {@link User} when user not exist then
return {@link
+ * Optional#empty()}
*/
- List<User> selectAllocatedList(User user);
+ Optional<User> getUser(String uid);
/**
- * Query the list of unassigned user roles.
+ * authenticate by ldap.
*
- * @param user query params
- * @return user list
+ * @param name login name of ldap user
+ * @param password login password of ldap user
+ * @return {@link Optional} of {@link User} when user authenticate failed
then return {@link
+ * Optional#empty()}
*/
- List<User> selectUnallocatedList(User user);
+ Optional<User> authenticate(String name, String password);
}
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/PermissionService.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/PermissionService.java
index 6a746a7..acce42e 100644
---
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/PermissionService.java
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/PermissionService.java
@@ -50,7 +50,6 @@ public class PermissionService implements StpInterface {
Preconditions.checkArgument(userId != null);
int userIdNum = Integer.parseInt(userId.toString());
Set<String> perms = new HashSet<String>();
- // 管理员拥有所有权限
if (userIdNum == Constants.ADMIN_ID) {
perms.add(Constants.ALL_PERMISSION);
} else {
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/SysRoleService.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/SysRoleService.java
index d7701c0..dd0ab61 100644
---
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/SysRoleService.java
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/SysRoleService.java
@@ -36,7 +36,7 @@ public interface SysRoleService extends IService<SysRole> {
* @param role query params
* @return role list
*/
- public List<SysRole> selectRoleList(IPage<SysRole> page, SysRole role);
+ List<SysRole> selectRoleList(IPage<SysRole> page, SysRole role);
/**
* Query role list based on user ID.
@@ -44,7 +44,7 @@ public interface SysRoleService extends IService<SysRole> {
* @param userId user ID
* @return role list
*/
- public List<SysRole> selectRolesByUserId(Integer userId);
+ List<SysRole> selectRolesByUserId(Integer userId);
/**
* Query role permissions based on user ID.
@@ -52,7 +52,7 @@ public interface SysRoleService extends IService<SysRole> {
* @param userId user ID
* @return permissions
*/
- public Set<String> selectRolePermissionByUserId(Integer userId);
+ Set<String> selectRolePermissionByUserId(Integer userId);
/**
* Query user role list by user ID.
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/UserService.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/UserService.java
index e0bd750..c6ed35e 100644
---
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/UserService.java
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/UserService.java
@@ -18,6 +18,7 @@
package org.apache.paimon.web.server.service;
+import org.apache.paimon.web.server.data.dto.LoginDto;
import org.apache.paimon.web.server.data.model.User;
import org.apache.paimon.web.server.data.result.exception.BaseException;
@@ -31,11 +32,10 @@ public interface UserService extends IService<User> {
/**
* login by username and password.
*
- * @param username username
- * @param password pwd
+ * @param loginDto login info
* @return {@link String}
*/
- String login(String username, String password) throws BaseException;
+ String login(LoginDto loginDto) throws BaseException;
/**
* Query the list of assigned user roles.
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/LdapServiceImpl.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/LdapServiceImpl.java
new file mode 100644
index 0000000..9f9d060
--- /dev/null
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/LdapServiceImpl.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.paimon.web.server.service.impl;
+
+import org.apache.paimon.web.server.data.enums.UserType;
+import org.apache.paimon.web.server.data.model.User;
+import org.apache.paimon.web.server.service.LdapService;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.ldap.core.AttributesMapper;
+import org.springframework.ldap.core.LdapTemplate;
+import org.springframework.ldap.filter.EqualsFilter;
+import org.springframework.ldap.query.LdapQuery;
+import org.springframework.ldap.query.LdapQueryBuilder;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+
+import java.util.List;
+import java.util.Optional;
+
+/** ldap service impl. */
+@Slf4j
+@Service
+public class LdapServiceImpl implements LdapService {
+
+ private static final UserAttributesMapperMapper MAPPER = new
UserAttributesMapperMapper();
+
+ private static final String FILTER = "cn";
+
+ @Autowired private LdapTemplate ldapTemplate;
+
+ /**
+ * get user info by ldap user identification.
+ *
+ * @param uid login name of ldap user
+ * @return {@link Optional} of {@link User} when user not exist then
return {@link
+ * Optional#empty()}
+ */
+ @Override
+ public Optional<User> getUser(String uid) {
+ LdapQuery query = LdapQueryBuilder.query().where(FILTER).is(uid);
+ try {
+ List<User> users = ldapTemplate.search(query, MAPPER);
+ return CollectionUtils.isEmpty(users)
+ ? Optional.empty()
+ : Optional.ofNullable(users.get(0));
+ } catch (EmptyResultDataAccessException e) {
+ return Optional.empty();
+ }
+ }
+
+ /**
+ * authenticate by ldap.
+ *
+ * @param name login name of ldap user
+ * @param password login password of ldap user
+ * @return {@link Optional} of {@link User} when user authenticate failed
then return {@link
+ * Optional#empty()}
+ */
+ @Override
+ public Optional<User> authenticate(String name, String password) {
+ EqualsFilter filter = new EqualsFilter(FILTER, name);
+ if (ldapTemplate.authenticate(StringUtils.EMPTY, filter.toString(),
password)) {
+ return this.getUser(name);
+ }
+ return Optional.empty();
+ }
+
+ /** Attributes mapper from LDAP user to Local user. */
+ private static class UserAttributesMapperMapper implements
AttributesMapper<User> {
+
+ /**
+ * Map the LDAP attributes to User object.
+ *
+ * @param attributes LDAP attributes
+ * @return User object
+ * @throws NamingException if there is an error during mapping
+ */
+ @Override
+ public User mapFromAttributes(Attributes attributes) throws
NamingException {
+ Attribute usernameAttr = attributes.get(FILTER);
+ Attribute nicknameAttr = attributes.get("sn");
+ Attribute email = attributes.get("email");
+
+ if (usernameAttr != null && nicknameAttr != null) {
+ User user = new User();
+ user.setUsername(usernameAttr.get().toString());
+ user.setNickname(nicknameAttr.get().toString());
+ user.setEmail(
+ Optional.ofNullable(email)
+ .map(
+ e -> {
+ try {
+ return e.get().toString();
+ } catch (NamingException ignore) {
+ }
+ return StringUtils.EMPTY;
+ })
+ .orElse(StringUtils.EMPTY));
+ user.setUserType(UserType.LDAP.getCode());
+ user.setEnabled(true);
+ return user;
+ }
+
+ return null;
+ }
+ }
+}
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/UserServiceImpl.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/UserServiceImpl.java
index 35e45e5..5d66c7f 100644
---
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/UserServiceImpl.java
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/UserServiceImpl.java
@@ -18,11 +18,15 @@
package org.apache.paimon.web.server.service.impl;
+import org.apache.paimon.web.server.data.dto.LoginDto;
+import org.apache.paimon.web.server.data.enums.UserType;
import org.apache.paimon.web.server.data.model.User;
import org.apache.paimon.web.server.data.result.exception.BaseException;
+import
org.apache.paimon.web.server.data.result.exception.user.UserDisabledException;
import
org.apache.paimon.web.server.data.result.exception.user.UserNotExistsException;
import
org.apache.paimon.web.server.data.result.exception.user.UserPasswordNotMatchException;
import org.apache.paimon.web.server.mapper.UserMapper;
+import org.apache.paimon.web.server.service.LdapService;
import org.apache.paimon.web.server.service.UserService;
import cn.dev33.satoken.stp.StpUtil;
@@ -31,32 +35,71 @@ import
org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
+import java.util.Optional;
/** UserServiceImpl. */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements
UserService {
+ @Autowired private LdapService ldapService;
@Autowired private UserMapper userMapper;
/**
* login by username and password.
*
- * @param username username
- * @param password pwd
+ * @param loginDto login info
* @return {@link String}
*/
@Override
- public String login(String username, String password) throws BaseException
{
- User user = this.lambdaQuery().eq(User::getUsername, username).one();
+ public String login(LoginDto loginDto) throws BaseException {
+ String username = loginDto.getUsername();
+ String password = loginDto.getPassword();
+
+ User user =
+ loginDto.isLdapLogin()
+ ? ldapLogin(username, password)
+ : localLogin(username, password);
+ if (!user.getEnabled()) {
+ throw new UserDisabledException();
+ }
+
+ StpUtil.login(user.getId(), loginDto.isRememberMe());
+
+ return StpUtil.getTokenValue();
+ }
+
+ private User localLogin(String username, String password) throws
BaseException {
+ User user =
+ this.lambdaQuery()
+ .eq(User::getUsername, username)
+ .eq(User::getUserType, UserType.LOCAL.getCode())
+ .one();
if (user == null) {
throw new UserNotExistsException();
}
if (!user.getPassword().equals(password)) {
throw new UserPasswordNotMatchException();
}
- StpUtil.login(user.getId());
+ return user;
+ }
- return StpUtil.getTokenValue();
+ private User ldapLogin(String username, String password) throws
BaseException {
+ Optional<User> authenticate = ldapService.authenticate(username,
password);
+ if (!authenticate.isPresent()) {
+ throw new UserPasswordNotMatchException();
+ }
+
+ User user =
+ this.lambdaQuery()
+ .eq(User::getUsername, username)
+ .eq(User::getUserType, UserType.LDAP.getCode())
+ .one();
+ if (user == null) {
+ user = authenticate.get();
+ this.save(user);
+ // TODO assign default roles and tenants
+ }
+ return user;
}
/**
diff --git a/paimon-web-server/src/main/resources/application-dev.yml
b/paimon-web-server/src/main/resources/application-dev.yml
index 70756dd..3a4532d 100644
--- a/paimon-web-server/src/main/resources/application-dev.yml
+++ b/paimon-web-server/src/main/resources/application-dev.yml
@@ -28,4 +28,10 @@ spring:
continue-on-error: true
username: root
password: root
- mode: always
\ No newline at end of file
+ mode: always
+
+ ldap:
+ urls: ldap://${LDAP_HOST:127.0.0.1}:${LDAP_PORT:389}
+ base: dc=test,dc=com
+ username: ${LDAP_USER:cn=admin,dc=test,dc=com}
+ password: ${LDAP_PASSWORD:admin}
diff --git a/paimon-web-server/src/main/resources/i18n/messages.properties
b/paimon-web-server/src/main/resources/i18n/messages.properties
index a96af9f..957a9fc 100644
--- a/paimon-web-server/src/main/resources/i18n/messages.properties
+++ b/paimon-web-server/src/main/resources/i18n/messages.properties
@@ -21,9 +21,11 @@ forbidden=User Not Have Permission
unknown.error=Unknown Error:{0}
method.not.allowed=Method Not Allowed
invalid.request.parameter=Request Parameter {0} Is Not Valid
-request.parameter.error=Request Parameter Error
+request.parameter.error=Request Parameter Error:{0}
internal.server.error=Internal Server Error:{0}
user.not.exist=User Not Exist
+user.password.error=User Password Error
+user.is.disabled=User Is Disabled
role.in.used=This role {0} is in used
role.name.exist=This role name {0} is exist
role.key.exist=This role key {0} is exist
diff --git
a/paimon-web-server/src/main/resources/i18n/messages_en_US.properties
b/paimon-web-server/src/main/resources/i18n/messages_en_US.properties
index ed08361..df1cb11 100644
--- a/paimon-web-server/src/main/resources/i18n/messages_en_US.properties
+++ b/paimon-web-server/src/main/resources/i18n/messages_en_US.properties
@@ -21,9 +21,11 @@ forbidden=User Not Have Permission
unknown.error=Unknown Error:{0}
method.not.allowed=Method Not Allowed
invalid.request.parameter=Request Parameter {0} Is Not Valid
-request.parameter.error=Request Parameter Error
+request.parameter.error=Request Parameter Error:{0}
internal.server.error=Internal Server Error:{0}
user.not.exist=User Not Exist
+user.password.error=User Password Error
+user.is.disabled=User Is Disabled
role.in.used=This role {0} is in used
role.name.exist=This role name {0} is exist
role.key.exist=This role key {0} is exist
diff --git
a/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties
b/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties
index 84e3484..98aa255 100644
--- a/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties
+++ b/paimon-web-server/src/main/resources/i18n/messages_zh_CN.properties
@@ -21,9 +21,11 @@ forbidden=用户无权限
unknown.error=未知错误:{0}
method.not.allowed=请求方法不支持
invalid.request.parameter=请求参数 {0} 无效
-request.parameter.error=请求参数错误
+request.parameter.error=请求参数错误:{0}
internal.server.error=服务器内部错误:{0}
user.not.exist=用户不存在
+user.password.error=密码错误
+user.is.disabled=用户已禁用
role.in.used=此角色{0}正在使用中
role.name.exist=此角色名称{0}已使用
role.key.exist=此角色关键字{0}已使用
diff --git a/paimon-web-server/src/main/resources/mapper/SysRoleMapper.xml
b/paimon-web-server/src/main/resources/mapper/SysRoleMapper.xml
index 213ae26..75256ea 100644
--- a/paimon-web-server/src/main/resources/mapper/SysRoleMapper.xml
+++ b/paimon-web-server/src/main/resources/mapper/SysRoleMapper.xml
@@ -68,7 +68,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectRolePermissionByUserId" parameterType="Integer"
resultMap="SysRoleResult">
<include refid="selectRoleVo"/>
- WHERE r.is_delete = '0' and ur.user_id = #{userId}
+ WHERE r.is_delete = '0' and urole.user_id = #{userId}
</select>
<select id="selectRoleAll" resultMap="SysRoleResult">
diff --git
a/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/PermissionTest.java
b/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/PermissionTest.java
index 730693e..21d22dd 100644
---
a/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/PermissionTest.java
+++
b/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/PermissionTest.java
@@ -18,6 +18,7 @@
package org.apache.paimon.web.server.controller;
+import org.apache.paimon.web.server.data.dto.LoginDto;
import org.apache.paimon.web.server.data.model.User;
import org.apache.paimon.web.server.data.result.R;
import org.apache.paimon.web.server.data.result.enums.Status;
@@ -59,11 +60,14 @@ public class PermissionTest {
@BeforeEach
public void before() throws Exception {
+ LoginDto login = new LoginDto();
+ login.setUsername("common");
+ login.setPassword("21232f297a57a5a743894a0e4a801fc3");
+
String result =
mockMvc.perform(
MockMvcRequestBuilders.post(loginPath)
- .queryParam("username", "common")
- .queryParam("password",
"21232f297a57a5a743894a0e4a801fc3")
+
.content(ObjectMapperUtils.toJSON(login))
.contentType(MediaType.APPLICATION_JSON_VALUE)
.accept(MediaType.APPLICATION_JSON_VALUE))
.andExpect(MockMvcResultMatchers.status().isOk())
diff --git
a/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/SysMenuControllerTest.java
b/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/SysMenuControllerTest.java
index ae4505b..6d9f09e 100644
---
a/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/SysMenuControllerTest.java
+++
b/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/SysMenuControllerTest.java
@@ -18,6 +18,7 @@
package org.apache.paimon.web.server.controller;
+import org.apache.paimon.web.server.data.dto.LoginDto;
import org.apache.paimon.web.server.data.model.SysMenu;
import org.apache.paimon.web.server.data.result.R;
import org.apache.paimon.web.server.data.tree.TreeSelect;
@@ -63,11 +64,14 @@ public class SysMenuControllerTest {
@BeforeEach
public void before() throws Exception {
+ LoginDto login = new LoginDto();
+ login.setUsername("admin");
+ login.setPassword("21232f297a57a5a743894a0e4a801fc3");
+
String result =
mockMvc.perform(
MockMvcRequestBuilders.post(loginPath)
- .queryParam("username", "admin")
- .queryParam("password",
"21232f297a57a5a743894a0e4a801fc3")
+
.content(ObjectMapperUtils.toJSON(login))
.contentType(MediaType.APPLICATION_JSON_VALUE)
.accept(MediaType.APPLICATION_JSON_VALUE))
.andExpect(MockMvcResultMatchers.status().isOk())
diff --git
a/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/SysRoleControllerTest.java
b/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/SysRoleControllerTest.java
index 462a585..216e269 100644
---
a/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/SysRoleControllerTest.java
+++
b/paimon-web-server/src/test/java/org/apache/paimon/web/server/controller/SysRoleControllerTest.java
@@ -18,6 +18,7 @@
package org.apache.paimon.web.server.controller;
+import org.apache.paimon.web.server.data.dto.LoginDto;
import org.apache.paimon.web.server.data.model.SysRole;
import org.apache.paimon.web.server.data.result.PageR;
import org.apache.paimon.web.server.data.result.R;
@@ -67,11 +68,14 @@ public class SysRoleControllerTest {
@BeforeEach
public void before() throws Exception {
+ LoginDto login = new LoginDto();
+ login.setUsername("admin");
+ login.setPassword("21232f297a57a5a743894a0e4a801fc3");
+
String result =
mockMvc.perform(
MockMvcRequestBuilders.post(loginPath)
- .queryParam("username", "admin")
- .queryParam("password",
"21232f297a57a5a743894a0e4a801fc3")
+
.content(ObjectMapperUtils.toJSON(login))
.contentType(MediaType.APPLICATION_JSON_VALUE)
.accept(MediaType.APPLICATION_JSON_VALUE))
.andExpect(MockMvcResultMatchers.status().isOk())