Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dedf95865e | |||
| 9d2fc024ea | |||
| 6f29904349 | |||
| 08c18fea90 | |||
| 776ddd28c1 | |||
| a3596ad086 | |||
| e1ad5cdfd8 | |||
| 712a675325 | |||
| 8b343af4e8 | |||
| 69e3f84bec |
@@ -1,7 +1,6 @@
|
|||||||
package com.onixbyte.helix.config;
|
package com.onixbyte.helix.config;
|
||||||
|
|
||||||
import com.onixbyte.identitygenerator.IdentityGenerator;
|
import com.onixbyte.identitygenerator.IdentityGenerator;
|
||||||
import com.onixbyte.identitygenerator.impl.SequentialUuidGenerator;
|
|
||||||
import com.onixbyte.identitygenerator.impl.SnowflakeIdentityGenerator;
|
import com.onixbyte.identitygenerator.impl.SnowflakeIdentityGenerator;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -28,24 +27,6 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
@Configuration
|
@Configuration
|
||||||
public class GuidConfig {
|
public class GuidConfig {
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Snowflake-based identity generator for user IDs.
|
|
||||||
* <p>
|
|
||||||
* This method configures a {@link SnowflakeIdentityGenerator} with machine ID and data centre
|
|
||||||
* ID both set to 0. The generator produces unique 64-bit Long identifiers suitable for user
|
|
||||||
* entity primary keys in distributed environments.
|
|
||||||
* <p>
|
|
||||||
* The generated IDs are:
|
|
||||||
* <ul>
|
|
||||||
* <li>Globally unique across all instances</li>
|
|
||||||
* <li>Time-ordered (newer IDs have higher values)</li>
|
|
||||||
* <li>Highly performant with minimal coordination overhead</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @return a configured {@link SnowflakeIdentityGenerator} instance for generating user IDs
|
|
||||||
* @see SnowflakeIdentityGenerator
|
|
||||||
* @see IdentityGenerator
|
|
||||||
*/
|
|
||||||
@Bean
|
@Bean
|
||||||
public IdentityGenerator<Long> userIdentityGenerator() {
|
public IdentityGenerator<Long> userIdentityGenerator() {
|
||||||
return new SnowflakeIdentityGenerator(0x0, 0x0);
|
return new SnowflakeIdentityGenerator(0x0, 0x0);
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024-2026 OnixByte
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.onixbyte.helix.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.LocaleResolver;
|
||||||
|
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class I18nConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public LocaleResolver localeResolver() {
|
||||||
|
var slr = new AcceptHeaderLocaleResolver();
|
||||||
|
slr.setDefaultLocale(Locale.UK);
|
||||||
|
return slr;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.onixbyte.helix.config;
|
package com.onixbyte.helix.config;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
|
||||||
import com.onixbyte.helix.common.jackson.JacksonModules;
|
import com.onixbyte.helix.common.jackson.JacksonModules;
|
||||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024-2026 OnixByte
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.onixbyte.helix.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class ValidationConfig {
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public ValidationConfig(MessageSource messageSource) {
|
||||||
|
this.messageSource = messageSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public LocalValidatorFactoryBean getValidator() {
|
||||||
|
var factoryBean = new LocalValidatorFactoryBean();
|
||||||
|
factoryBean.setValidationMessageSource(messageSource);
|
||||||
|
return factoryBean;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import com.onixbyte.helix.shared.AssetPrefix;
|
|||||||
import com.onixbyte.helix.domain.web.response.FileUploadResponse;
|
import com.onixbyte.helix.domain.web.response.FileUploadResponse;
|
||||||
import com.onixbyte.helix.exception.BizException;
|
import com.onixbyte.helix.exception.BizException;
|
||||||
import com.onixbyte.helix.service.AssetService;
|
import com.onixbyte.helix.service.AssetService;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -26,11 +27,6 @@ public class AssetController {
|
|||||||
|
|
||||||
private final AssetService assetService;
|
private final AssetService assetService;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new FileController with the specified file service.
|
|
||||||
*
|
|
||||||
* @param assetService the file service to use for file operations
|
|
||||||
*/
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public AssetController(AssetService assetService) {
|
public AssetController(AssetService assetService) {
|
||||||
this.assetService = assetService;
|
this.assetService = assetService;
|
||||||
@@ -48,7 +44,7 @@ public class AssetController {
|
|||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if (file.isEmpty()) {
|
if (file.isEmpty()) {
|
||||||
throw new BizException(HttpStatus.BAD_REQUEST, "File cannot be empty.");
|
throw new BizException(HttpStatus.BAD_REQUEST, MessageName.ASSET_NOT_EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileUrl = assetService.uploadFile(AssetPrefix.UPLOADS, file);
|
var fileUrl = assetService.uploadFile(AssetPrefix.UPLOADS, file);
|
||||||
@@ -61,10 +57,13 @@ public class AssetController {
|
|||||||
file.getSize(),
|
file.getSize(),
|
||||||
fileUrl
|
fileUrl
|
||||||
));
|
));
|
||||||
|
} catch (BizException ex) {
|
||||||
|
throw ex;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("File upload failed: {}", e.getMessage(), e);
|
log.error("File upload failed: {}", e.getMessage(), e);
|
||||||
throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR,
|
throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
"Failed upload file: " + e.getMessage());
|
MessageName.ASSET_UPLOAD_FAILED,
|
||||||
|
e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import com.onixbyte.helix.service.AuthService;
|
|||||||
import com.onixbyte.helix.service.TokenService;
|
import com.onixbyte.helix.service.TokenService;
|
||||||
import com.onixbyte.helix.service.UserService;
|
import com.onixbyte.helix.service.UserService;
|
||||||
import com.onixbyte.helix.shared.TokenConstant;
|
import com.onixbyte.helix.shared.TokenConstant;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -27,7 +25,6 @@ import java.time.Duration;
|
|||||||
@RequestMapping("/auth")
|
@RequestMapping("/auth")
|
||||||
public class AuthController {
|
public class AuthController {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(AuthController.class);
|
|
||||||
private final AuthService authService;
|
private final AuthService authService;
|
||||||
private final TokenService tokenService;
|
private final TokenService tokenService;
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package com.onixbyte.helix.controller;
|
package com.onixbyte.helix.controller;
|
||||||
|
|
||||||
import com.onixbyte.helix.domain.entity.Authority;
|
import com.onixbyte.helix.domain.entity.Authority;
|
||||||
import com.onixbyte.helix.domain.web.request.AddAuthorityRequest;
|
import com.onixbyte.helix.domain.web.request.AuthorityRequest;
|
||||||
import com.onixbyte.helix.domain.web.request.EditAuthorityRequest;
|
|
||||||
import com.onixbyte.helix.domain.web.request.QueryAuthorityRequest;
|
import com.onixbyte.helix.domain.web.request.QueryAuthorityRequest;
|
||||||
|
import com.onixbyte.helix.domain.web.response.ActionResponse;
|
||||||
import com.onixbyte.helix.service.AuthorityService;
|
import com.onixbyte.helix.service.AuthorityService;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
|
import com.onixbyte.helix.utils.MessageUtil;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -21,9 +23,14 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
public class AuthorityController {
|
public class AuthorityController {
|
||||||
|
|
||||||
private final AuthorityService authorityService;
|
private final AuthorityService authorityService;
|
||||||
|
private final MessageUtil messageUtil;
|
||||||
|
|
||||||
public AuthorityController(AuthorityService authorityService) {
|
public AuthorityController(
|
||||||
|
AuthorityService authorityService,
|
||||||
|
MessageUtil messageUtil
|
||||||
|
) {
|
||||||
this.authorityService = authorityService;
|
this.authorityService = authorityService;
|
||||||
|
this.messageUtil = messageUtil;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,7 +58,7 @@ public class AuthorityController {
|
|||||||
* @return created authority
|
* @return created authority
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public Authority addAuthority(@Validated @RequestBody AddAuthorityRequest request) {
|
public Authority addAuthority(@Validated @RequestBody AuthorityRequest request) {
|
||||||
return authorityService.addAuthority(request);
|
return authorityService.addAuthority(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,8 +68,17 @@ public class AuthorityController {
|
|||||||
* @param request authority specs
|
* @param request authority specs
|
||||||
* @return edited authority
|
* @return edited authority
|
||||||
*/
|
*/
|
||||||
@PutMapping
|
@PutMapping("/{id:\\d+}")
|
||||||
public Authority editAuthority(@Validated @RequestBody EditAuthorityRequest request) {
|
public Authority editAuthority(
|
||||||
return authorityService.editAuthority(request);
|
@PathVariable Long id,
|
||||||
|
@Validated @RequestBody AuthorityRequest request
|
||||||
|
) {
|
||||||
|
return authorityService.editAuthority(id, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{authorityId:\\d+}")
|
||||||
|
public ActionResponse deleteAuthority(@PathVariable Long authorityId) {
|
||||||
|
var name = authorityService.deleteAuthority(authorityId);
|
||||||
|
return ActionResponse.success(messageUtil.getMessage(MessageName.AUTHORITY_DELETED, name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.onixbyte.helix.controller;
|
|||||||
|
|
||||||
import com.onixbyte.helix.domain.entity.Department;
|
import com.onixbyte.helix.domain.entity.Department;
|
||||||
import com.onixbyte.helix.domain.common.TreeNode;
|
import com.onixbyte.helix.domain.common.TreeNode;
|
||||||
import com.onixbyte.helix.domain.web.request.AddDepartmentRequest;
|
import com.onixbyte.helix.domain.web.request.DepartmentRequest;
|
||||||
import com.onixbyte.helix.service.DepartmentService;
|
import com.onixbyte.helix.service.DepartmentService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -38,7 +38,15 @@ public class DepartmentController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public Department addDepartment(@Validated @RequestBody AddDepartmentRequest request) {
|
public Department addDepartment(@Validated @RequestBody DepartmentRequest request) {
|
||||||
return departmentService.addDepartment(request);
|
return departmentService.addDepartment(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id:\\d+}")
|
||||||
|
public Department editDepartment(
|
||||||
|
@PathVariable Long id,
|
||||||
|
@Validated @RequestBody DepartmentRequest request
|
||||||
|
) {
|
||||||
|
return departmentService.editDepartment(id, request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.onixbyte.helix.controller;
|
|||||||
|
|
||||||
import com.onixbyte.helix.domain.web.response.BizExceptionResponse;
|
import com.onixbyte.helix.domain.web.response.BizExceptionResponse;
|
||||||
import com.onixbyte.helix.exception.BizException;
|
import com.onixbyte.helix.exception.BizException;
|
||||||
|
import com.onixbyte.helix.utils.MessageUtil;
|
||||||
import jakarta.validation.ConstraintViolationException;
|
import jakarta.validation.ConstraintViolationException;
|
||||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -27,12 +28,22 @@ import java.util.stream.Collectors;
|
|||||||
@RestControllerAdvice
|
@RestControllerAdvice
|
||||||
public class ExceptionController {
|
public class ExceptionController {
|
||||||
|
|
||||||
|
private final MessageUtil messageUtil;
|
||||||
|
|
||||||
|
public ExceptionController(MessageUtil messageUtil) {
|
||||||
|
this.messageUtil = messageUtil;
|
||||||
|
}
|
||||||
|
|
||||||
@ExceptionHandler(BizException.class)
|
@ExceptionHandler(BizException.class)
|
||||||
public ResponseEntity<BizExceptionResponse> handleBizException(BizException ex) {
|
public ResponseEntity<BizExceptionResponse> handleBizException(BizException ex) {
|
||||||
|
var message = ex.getMessageCode() == null
|
||||||
|
? ex.getMessage()
|
||||||
|
: messageUtil.getMessage(ex.getMessageCode(), ex.getMessageArgs());
|
||||||
|
|
||||||
return ResponseEntity.status(ex.getStatus())
|
return ResponseEntity.status(ex.getStatus())
|
||||||
.body(new BizExceptionResponse(
|
.body(new BizExceptionResponse(
|
||||||
LocalDateTime.now(),
|
LocalDateTime.now(),
|
||||||
ex.getMessage())
|
message)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package com.onixbyte.helix.controller;
|
package com.onixbyte.helix.controller;
|
||||||
|
|
||||||
import com.onixbyte.helix.domain.entity.Role;
|
import com.onixbyte.helix.domain.entity.Role;
|
||||||
import com.onixbyte.helix.domain.web.request.AddRoleRequest;
|
|
||||||
import com.onixbyte.helix.domain.web.request.EditRoleRequest;
|
|
||||||
import com.onixbyte.helix.domain.web.request.QueryRoleRequest;
|
import com.onixbyte.helix.domain.web.request.QueryRoleRequest;
|
||||||
|
import com.onixbyte.helix.domain.web.request.RoleRequest;
|
||||||
|
import com.onixbyte.helix.domain.web.response.ActionResponse;
|
||||||
import com.onixbyte.helix.service.RoleService;
|
import com.onixbyte.helix.service.RoleService;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
|
import com.onixbyte.helix.utils.MessageUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -24,10 +25,12 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
public class RoleController {
|
public class RoleController {
|
||||||
|
|
||||||
private final RoleService roleService;
|
private final RoleService roleService;
|
||||||
|
private final MessageUtil messageUtil;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public RoleController(RoleService roleService) {
|
public RoleController(RoleService roleService, MessageUtil messageUtil) {
|
||||||
this.roleService = roleService;
|
this.roleService = roleService;
|
||||||
|
this.messageUtil = messageUtil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
@@ -41,20 +44,21 @@ public class RoleController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public ResponseEntity<Void> addRole(@Validated @RequestBody AddRoleRequest request) {
|
public Role addRole(@Validated @RequestBody RoleRequest request) {
|
||||||
roleService.addRole(request);
|
return roleService.addRole(request);
|
||||||
return ResponseEntity.ok(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping("/{id:\\d+}")
|
||||||
public ResponseEntity<Void> editRole(@Validated @RequestBody EditRoleRequest request) {
|
public Role editRole(
|
||||||
roleService.editRole(request);
|
@PathVariable Long id,
|
||||||
return ResponseEntity.ok(null);
|
@Validated @RequestBody RoleRequest request
|
||||||
|
) {
|
||||||
|
return roleService.editRole(id, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id:\\d+}")
|
@DeleteMapping("/{id:\\d+}")
|
||||||
public ResponseEntity<Void> deleteRole(@PathVariable Long id) {
|
public ActionResponse deleteRole(@PathVariable Long id) {
|
||||||
roleService.deleteRole(id);
|
var name = roleService.deleteRole(id);
|
||||||
return ResponseEntity.ok(null);
|
return ActionResponse.success(messageUtil.getMessage(MessageName.ROLE_DELETED, name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ import com.onixbyte.helix.domain.web.request.ResetPasswordRequest;
|
|||||||
import com.onixbyte.helix.domain.web.response.ActionResponse;
|
import com.onixbyte.helix.domain.web.response.ActionResponse;
|
||||||
import com.onixbyte.helix.domain.web.response.UserDetailResponse;
|
import com.onixbyte.helix.domain.web.response.UserDetailResponse;
|
||||||
import com.onixbyte.helix.service.UserService;
|
import com.onixbyte.helix.service.UserService;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
|
import com.onixbyte.helix.utils.MessageUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -27,10 +28,12 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
public class UserController {
|
public class UserController {
|
||||||
|
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
|
private final MessageUtil messageUtil;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public UserController(UserService userService) {
|
public UserController(UserService userService, MessageUtil messageUtil) {
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
|
this.messageUtil = messageUtil;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,13 +81,16 @@ public class UserController {
|
|||||||
/**
|
/**
|
||||||
* Edit a user.
|
* Edit a user.
|
||||||
*
|
*
|
||||||
|
* @param id user ID
|
||||||
* @param request user to be edited
|
* @param request user to be edited
|
||||||
* @return edited user
|
* @return edited user
|
||||||
*/
|
*/
|
||||||
@PutMapping
|
@PutMapping("/{id:\\d+}")
|
||||||
public ResponseEntity<Void> editUser(@Validated @RequestBody EditUserRequest request) {
|
public UserDetailResponse editUser(
|
||||||
userService.updateUser(request);
|
@PathVariable Long id,
|
||||||
return ResponseEntity.ok(null);
|
@Validated @RequestBody EditUserRequest request
|
||||||
|
) {
|
||||||
|
return userService.updateUser(id, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,10 +100,13 @@ public class UserController {
|
|||||||
* @return action response
|
* @return action response
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("hasAnyAuthority('system:user:reset-password')")
|
@PreAuthorize("hasAnyAuthority('system:user:reset-password')")
|
||||||
@PatchMapping("/reset-password")
|
@PatchMapping("/reset-password/{id:\\d+}")
|
||||||
public ActionResponse resetPassword(@Validated @RequestBody ResetPasswordRequest request) {
|
public ActionResponse resetPassword(
|
||||||
userService.resetPassword(request);
|
@PathVariable Long id,
|
||||||
return ActionResponse.success("密码修改成功");
|
@Validated @RequestBody ResetPasswordRequest request
|
||||||
|
) {
|
||||||
|
userService.resetPassword(id, request);
|
||||||
|
return ActionResponse.success(messageUtil.getMessage(MessageName.USER_PASSWORD_RESET_SUCCESS));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,6 +119,6 @@ public class UserController {
|
|||||||
@DeleteMapping("/{userId:\\d+}")
|
@DeleteMapping("/{userId:\\d+}")
|
||||||
public ActionResponse deleteUser(@PathVariable Long userId) {
|
public ActionResponse deleteUser(@PathVariable Long userId) {
|
||||||
userService.deleteUser(userId);
|
userService.deleteUser(userId);
|
||||||
return ActionResponse.success("删除成功");
|
return ActionResponse.success(messageUtil.getMessage(MessageName.USER_DELETED, userId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
package com.onixbyte.helix.domain.web.request;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import jakarta.validation.constraints.Pattern;
|
|
||||||
|
|
||||||
public record AddAuthorityRequest(
|
|
||||||
@NotNull @NotBlank(message = "权限编码不能为空") String code,
|
|
||||||
@NotNull @NotBlank(message = "权限名称不能为空") String name,
|
|
||||||
String description,
|
|
||||||
@Pattern(
|
|
||||||
regexp = "^(ACTIVE|INACTIVE)?$",
|
|
||||||
message = "状态错误") String status
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.onixbyte.helix.domain.web.request;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import jakarta.validation.constraints.Pattern;
|
|
||||||
|
|
||||||
public record AddRoleRequest(
|
|
||||||
@NotBlank(message = "角色名称不能为空")
|
|
||||||
String name,
|
|
||||||
@NotBlank(message = "角色编码不能为空")
|
|
||||||
String code,
|
|
||||||
@NotNull(message = "排序编号不能为空")
|
|
||||||
Integer sort,
|
|
||||||
Boolean defaultValue,
|
|
||||||
String description,
|
|
||||||
@Pattern(
|
|
||||||
regexp = "^(ACTIVE|INACTIVE)?$",
|
|
||||||
message = "状态仅可以是 ACTIVE、INACTIVE 其中之一")
|
|
||||||
String status
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
package com.onixbyte.helix.domain.web.request;
|
package com.onixbyte.helix.domain.web.request;
|
||||||
|
|
||||||
import com.onixbyte.helix.enumeration.UserStatus;
|
import com.onixbyte.helix.enumeration.UserStatus;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public record AddUserRequest(
|
public record AddUserRequest(
|
||||||
@NotBlank(message = "Username cannot be empty.")
|
@NotBlank(message = "{" + MessageName.REQUEST_ADD_USER_USERNAME_NOT_EMPTY + "}")
|
||||||
String username,
|
String username,
|
||||||
@NotBlank(message = "Password cannot be empty.")
|
@NotBlank(message = "{" + MessageName.REQUEST_ADD_USER_PASSWORD_NOT_EMPTY + "}")
|
||||||
String password,
|
String password,
|
||||||
@NotBlank(message = "Full name cannot be empty.")
|
@NotBlank(message = "{" + MessageName.REQUEST_ADD_USER_FULL_NAME_NOT_EMPTY + "}")
|
||||||
String fullName,
|
String fullName,
|
||||||
String email,
|
String email,
|
||||||
String regionAbbreviation,
|
String regionAbbreviation,
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.onixbyte.helix.domain.web.request;
|
||||||
|
|
||||||
|
import com.onixbyte.helix.enumeration.Status;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
|
import com.onixbyte.helix.validation.group.OnCreate;
|
||||||
|
import com.onixbyte.helix.validation.group.OnUpdate;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Null;
|
||||||
|
|
||||||
|
public record AuthorityRequest(
|
||||||
|
@Null(groups = {OnUpdate.class}, message = "{" + MessageName.REQUEST_AUTHORITY_CODE_NOT_EDITABLE + "}")
|
||||||
|
@NotNull(groups = {OnCreate.class}, message = "{" + MessageName.REQUEST_AUTHORITY_CODE_NOT_NULL + "}")
|
||||||
|
String code,
|
||||||
|
@NotNull(message = "{" + MessageName.REQUEST_AUTHORITY_NAME_NOT_NULL + "}")
|
||||||
|
@NotBlank(message = "{" + MessageName.REQUEST_AUTHORITY_NAME_NOT_NULL + "}")
|
||||||
|
String name,
|
||||||
|
String description,
|
||||||
|
Status status
|
||||||
|
) {
|
||||||
|
}
|
||||||
+4
-3
@@ -23,12 +23,13 @@
|
|||||||
package com.onixbyte.helix.domain.web.request;
|
package com.onixbyte.helix.domain.web.request;
|
||||||
|
|
||||||
import com.onixbyte.helix.enumeration.Status;
|
import com.onixbyte.helix.enumeration.Status;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
public record AddDepartmentRequest(
|
public record DepartmentRequest(
|
||||||
@NotNull(message = "Name of the department should not be null")
|
@NotNull(message = "{" + MessageName.REQUEST_DEPARTMENT_NAME_NOT_NULL + "}")
|
||||||
@NotBlank(message = "Name of the department should not be null")
|
@NotBlank(message = "{" + MessageName.REQUEST_DEPARTMENT_NAME_NOT_NULL + "}")
|
||||||
String name,
|
String name,
|
||||||
Long parentId,
|
Long parentId,
|
||||||
Integer sort,
|
Integer sort,
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package com.onixbyte.helix.domain.web.request;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.Pattern;
|
|
||||||
|
|
||||||
public record EditAuthorityRequest(
|
|
||||||
Long id,
|
|
||||||
String name,
|
|
||||||
String description,
|
|
||||||
@Pattern(
|
|
||||||
regexp = "^(ACTIVE|INACTIVE)?$",
|
|
||||||
message = "状态参数错误")
|
|
||||||
String status
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.onixbyte.helix.domain.web.request;
|
package com.onixbyte.helix.domain.web.request;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import jakarta.validation.constraints.Pattern;
|
import jakarta.validation.constraints.Pattern;
|
||||||
|
|
||||||
public record EditRoleRequest(
|
public record EditRoleRequest(
|
||||||
@NotNull(message = "角色 ID 不能为空")
|
@NotNull(message = "{" + MessageName.REQUEST_EDIT_ROLE_ID_NOT_NULL + "}")
|
||||||
Long id,
|
Long id,
|
||||||
String name,
|
String name,
|
||||||
String code,
|
String code,
|
||||||
@@ -14,7 +14,7 @@ public record EditRoleRequest(
|
|||||||
String description,
|
String description,
|
||||||
@Pattern(
|
@Pattern(
|
||||||
regexp = "^(ACTIVE|INACTIVE)?$",
|
regexp = "^(ACTIVE|INACTIVE)?$",
|
||||||
message = "状态仅可以是 ACTIVE、INACTIVE 其中之一")
|
message = "{" + MessageName.REQUEST_EDIT_ROLE_STATUS_INVALID + "}")
|
||||||
String status
|
String status
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package com.onixbyte.helix.domain.web.request;
|
package com.onixbyte.helix.domain.web.request;
|
||||||
|
|
||||||
import com.onixbyte.helix.enumeration.UserStatus;
|
import com.onixbyte.helix.enumeration.UserStatus;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import jakarta.validation.constraints.Positive;
|
import jakarta.validation.constraints.Positive;
|
||||||
|
|
||||||
public record EditUserRequest(
|
public record EditUserRequest(
|
||||||
@NotNull(message = "User ID cannot be null")
|
@NotNull(message = "{" + MessageName.REQUEST_EDIT_USER_ID_NOT_NULL + "}")
|
||||||
@Positive(message = "User ID must be positive")
|
@Positive(message = "{" + MessageName.REQUEST_EDIT_USER_ID_POSITIVE + "}")
|
||||||
Long id,
|
Long id,
|
||||||
String fullName,
|
String fullName,
|
||||||
String email,
|
String email,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.onixbyte.helix.domain.web.request;
|
package com.onixbyte.helix.domain.web.request;
|
||||||
|
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import jakarta.validation.constraints.Pattern;
|
import jakarta.validation.constraints.Pattern;
|
||||||
|
|
||||||
public record QueryRoleRequest(
|
public record QueryRoleRequest(
|
||||||
@@ -7,7 +8,7 @@ public record QueryRoleRequest(
|
|||||||
String code,
|
String code,
|
||||||
@Pattern(
|
@Pattern(
|
||||||
regexp = "^(ACTIVE|INACTIVE)?$",
|
regexp = "^(ACTIVE|INACTIVE)?$",
|
||||||
message = "状态仅可以是 ACTIVE、INACTIVE 其中之一")
|
message = "{" + MessageName.REQUEST_QUERY_ROLE_STATUS_INVALID + "}")
|
||||||
String status
|
String status
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.onixbyte.helix.domain.web.request;
|
package com.onixbyte.helix.domain.web.request;
|
||||||
|
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import jakarta.validation.constraints.Pattern;
|
import jakarta.validation.constraints.Pattern;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -11,7 +12,7 @@ public record QueryUserRequest(
|
|||||||
String phoneNumber,
|
String phoneNumber,
|
||||||
@Pattern(
|
@Pattern(
|
||||||
regexp = "^(ACTIVE|INACTIVE|LOCKED)?$",
|
regexp = "^(ACTIVE|INACTIVE|LOCKED)?$",
|
||||||
message = "状态仅可以是 ACTIVE、INACTIVE 或 LOCKED 其中之一")
|
message = "{" + MessageName.REQUEST_QUERY_USER_STATUS_INVALID + "}")
|
||||||
String status,
|
String status,
|
||||||
LocalDateTime createdAtStart,
|
LocalDateTime createdAtStart,
|
||||||
LocalDateTime createdAtEnd
|
LocalDateTime createdAtEnd
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.onixbyte.helix.domain.web.request;
|
package com.onixbyte.helix.domain.web.request;
|
||||||
|
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
public record ResetPasswordRequest(
|
public record ResetPasswordRequest(
|
||||||
@NotNull(message = "用户 ID 不能为空") Long id,
|
@NotBlank(message = "{" + MessageName.REQUEST_RESET_PASSWORD_NOT_EMPTY + "}") String password
|
||||||
@NotBlank(message = "密码不能为空") String password
|
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.onixbyte.helix.domain.web.request;
|
||||||
|
|
||||||
|
import com.onixbyte.helix.enumeration.Status;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Pattern;
|
||||||
|
|
||||||
|
public record RoleRequest(
|
||||||
|
@NotBlank(message = "{" + MessageName.REQUEST_ROLE_NAME_NOT_EMPTY + "}")
|
||||||
|
String name,
|
||||||
|
@NotBlank(message = "{" + MessageName.REQUEST_ROLE_CODE_NOT_EMPTY + "}")
|
||||||
|
String code,
|
||||||
|
@NotNull(message = "{" + MessageName.REQUEST_ROLE_SORT_NOT_NULL + "}")
|
||||||
|
Integer sort,
|
||||||
|
Boolean defaultValue,
|
||||||
|
String description,
|
||||||
|
Status status
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -41,26 +41,19 @@ public class BizException extends RuntimeException {
|
|||||||
* REST API endpoints.
|
* REST API endpoints.
|
||||||
*/
|
*/
|
||||||
private final HttpStatus status;
|
private final HttpStatus status;
|
||||||
|
private final String messageCode;
|
||||||
|
private final Object[] messageArgs;
|
||||||
|
|
||||||
/**
|
public BizException(String messageCode, Object... messageArgs) {
|
||||||
* Constructs a new business exception with the specified HTTP status and message.
|
|
||||||
*
|
|
||||||
* @param message the detailed error message explaining the business logic violation
|
|
||||||
*/
|
|
||||||
public BizException(String message) {
|
|
||||||
super(message);
|
|
||||||
this.status = HttpStatus.INTERNAL_SERVER_ERROR;
|
this.status = HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
this.messageCode = messageCode;
|
||||||
|
this.messageArgs = messageArgs == null ? new Object[0] : messageArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public BizException(HttpStatus status, String messageCode, Object... messageArgs) {
|
||||||
* Constructs a new business exception with the specified HTTP status and message.
|
|
||||||
*
|
|
||||||
* @param status the HTTP status code to associate with this exception
|
|
||||||
* @param message the detailed error message explaining the business logic violation
|
|
||||||
*/
|
|
||||||
public BizException(HttpStatus status, String message) {
|
|
||||||
super(message);
|
|
||||||
this.status = status;
|
this.status = status;
|
||||||
|
this.messageCode = messageCode;
|
||||||
|
this.messageArgs = messageArgs == null ? new Object[0] : messageArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,4 +64,12 @@ public class BizException extends RuntimeException {
|
|||||||
public HttpStatus getStatus() {
|
public HttpStatus getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMessageCode() {
|
||||||
|
return messageCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getMessageArgs() {
|
||||||
|
return messageArgs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.onixbyte.helix.manager;
|
|||||||
|
|
||||||
import com.onixbyte.helix.shared.CacheName;
|
import com.onixbyte.helix.shared.CacheName;
|
||||||
import com.onixbyte.helix.domain.entity.Asset;
|
import com.onixbyte.helix.domain.entity.Asset;
|
||||||
import com.onixbyte.helix.mapper.AssetMapper;
|
|
||||||
import com.onixbyte.helix.repository.AssetRepository;
|
import com.onixbyte.helix.repository.AssetRepository;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
@@ -13,12 +12,10 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
public class AssetManager {
|
public class AssetManager {
|
||||||
|
|
||||||
private final AssetMapper assetMapper;
|
|
||||||
private final AssetRepository assetRepository;
|
private final AssetRepository assetRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public AssetManager(AssetMapper assetMapper, AssetRepository assetRepository) {
|
public AssetManager(AssetRepository assetRepository) {
|
||||||
this.assetMapper = assetMapper;
|
|
||||||
this.assetRepository = assetRepository;
|
this.assetRepository = assetRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,13 @@ package com.onixbyte.helix.manager;
|
|||||||
|
|
||||||
import com.onixbyte.helix.domain.database.query.wrapper.QueryAuthorityWrapper;
|
import com.onixbyte.helix.domain.database.query.wrapper.QueryAuthorityWrapper;
|
||||||
import com.onixbyte.helix.domain.entity.Authority;
|
import com.onixbyte.helix.domain.entity.Authority;
|
||||||
import com.onixbyte.helix.domain.web.request.EditAuthorityRequest;
|
import com.onixbyte.helix.domain.web.request.AuthorityRequest;
|
||||||
import com.onixbyte.helix.enumeration.Status;
|
import com.onixbyte.helix.enumeration.Status;
|
||||||
import com.onixbyte.helix.exception.BizException;
|
import com.onixbyte.helix.exception.BizException;
|
||||||
import com.onixbyte.helix.mapper.AuthorityMapper;
|
import com.onixbyte.helix.mapper.AuthorityMapper;
|
||||||
import com.onixbyte.helix.repository.AuthorityRepository;
|
import com.onixbyte.helix.repository.AuthorityRepository;
|
||||||
import com.onixbyte.helix.shared.CacheName;
|
import com.onixbyte.helix.shared.CacheName;
|
||||||
import org.slf4j.Logger;
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.data.domain.Example;
|
import org.springframework.data.domain.Example;
|
||||||
@@ -19,13 +18,13 @@ import org.springframework.http.HttpStatus;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class AuthorityManager {
|
public class AuthorityManager {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(AuthorityManager.class);
|
|
||||||
private final AuthorityMapper authorityMapper;
|
private final AuthorityMapper authorityMapper;
|
||||||
private final AuthorityRepository authorityRepository;
|
private final AuthorityRepository authorityRepository;
|
||||||
|
|
||||||
@@ -56,20 +55,38 @@ public class AuthorityManager {
|
|||||||
return authorityRepository.save(authority);
|
return authorityRepository.save(authority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fully updates an existing authority by ID.
|
||||||
|
* <p>
|
||||||
|
* The method loads the target authority, replaces mutable fields ({@code name},
|
||||||
|
* {@code description}, {@code status}), and refreshes {@code updatedAt} to the current time.
|
||||||
|
* The update runs within a transactional context.
|
||||||
|
*
|
||||||
|
* @param id the ID of the authority to update
|
||||||
|
* @param authority the source data carrying new field values
|
||||||
|
* @return the supplied {@link Authority} object
|
||||||
|
* @throws BizException if the target authority does not exist
|
||||||
|
*/
|
||||||
@Transactional
|
@Transactional
|
||||||
public Authority update(EditAuthorityRequest request) {
|
public Authority fullUpdateById(Long id, Authority authority) {
|
||||||
var authority = authorityRepository.findById(request.id())
|
var updatedAt = LocalDateTime.now();
|
||||||
.orElseThrow(() -> new BizException(HttpStatus.NOT_FOUND, "找不到指定的权限信息"));
|
|
||||||
|
|
||||||
Optional.ofNullable(request.name())
|
var authorityToUpdate = authorityRepository.findById(id)
|
||||||
.ifPresent(authority::setName);
|
.orElseThrow(() -> new BizException(HttpStatus.NOT_FOUND, MessageName.AUTHORITY_NOT_FOUND, id));
|
||||||
|
|
||||||
authority.setDescription(request.description());
|
authorityToUpdate.setName(authority.getName());
|
||||||
|
authorityToUpdate.setDescription(authority.getDescription());
|
||||||
Optional.ofNullable(request.status())
|
authorityToUpdate.setStatus(authority.getStatus());
|
||||||
.map(Status::valueOf)
|
authorityToUpdate.setUpdatedAt(updatedAt);
|
||||||
.ifPresent(authority::setStatus);
|
|
||||||
|
|
||||||
return authority;
|
return authority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String findAuthorityNameById(Long authorityId) {
|
||||||
|
return authorityRepository.findAuthorityNameById(authorityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteById(Long authorityId) {
|
||||||
|
authorityRepository.deleteById(authorityId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,27 @@
|
|||||||
package com.onixbyte.helix.manager;
|
package com.onixbyte.helix.manager;
|
||||||
|
|
||||||
import com.onixbyte.helix.domain.entity.Department;
|
import com.onixbyte.helix.domain.entity.Department;
|
||||||
import com.onixbyte.helix.mapper.DepartmentMapper;
|
import com.onixbyte.helix.exception.BizException;
|
||||||
import com.onixbyte.helix.repository.DepartmentRepository;
|
import com.onixbyte.helix.repository.DepartmentRepository;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class DepartmentManager {
|
public class DepartmentManager {
|
||||||
|
|
||||||
private final DepartmentMapper departmentMapper;
|
|
||||||
private final DepartmentRepository departmentRepository;
|
private final DepartmentRepository departmentRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DepartmentManager(DepartmentMapper departmentMapper, DepartmentRepository departmentRepository) {
|
public DepartmentManager(DepartmentRepository departmentRepository) {
|
||||||
this.departmentMapper = departmentMapper;
|
|
||||||
this.departmentRepository = departmentRepository;
|
this.departmentRepository = departmentRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,4 +40,38 @@ public class DepartmentManager {
|
|||||||
public Department save(Department department) {
|
public Department save(Department department) {
|
||||||
return departmentRepository.save(department);
|
return departmentRepository.save(department);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fully updates an existing department by ID.
|
||||||
|
* <p>
|
||||||
|
* The method loads the target department, replaces mutable fields ({@code name},
|
||||||
|
* {@code parentId}, {@code sort}, {@code status}), and refreshes {@code updatedAt} to the
|
||||||
|
* current time.
|
||||||
|
*
|
||||||
|
* @param id the ID of the department to update
|
||||||
|
* @param department the source data carrying new field values
|
||||||
|
* @return the managed and updated {@link Department} entity
|
||||||
|
* @throws BizException if the target department does not exist
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public Department fullUpdateById(Long id, Department department) {
|
||||||
|
var updatedAt = LocalDateTime.now();
|
||||||
|
|
||||||
|
var departmentToEdit = departmentRepository.findById(id)
|
||||||
|
.orElseThrow(() -> new BizException(
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
"Department (ID: %d) to be edited not found.".formatted(department.getId()))
|
||||||
|
);
|
||||||
|
|
||||||
|
departmentToEdit.setName(department.getName());
|
||||||
|
departmentToEdit.setParentId(department.getParentId());
|
||||||
|
departmentToEdit.setSort(department.getSort());
|
||||||
|
departmentToEdit.setStatus(department.getStatus());
|
||||||
|
departmentToEdit.setUpdatedAt(updatedAt);
|
||||||
|
return departmentToEdit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean existsByName(String name) {
|
||||||
|
return departmentRepository.existsByName(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package com.onixbyte.helix.manager;
|
|||||||
|
|
||||||
import com.onixbyte.helix.domain.entity.Menu;
|
import com.onixbyte.helix.domain.entity.Menu;
|
||||||
import com.onixbyte.helix.mapper.MenuMapper;
|
import com.onixbyte.helix.mapper.MenuMapper;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -11,7 +9,7 @@ import java.util.List;
|
|||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class MenuManager {
|
public class MenuManager {
|
||||||
private static final Logger log = LoggerFactory.getLogger(MenuManager.class);
|
|
||||||
private final MenuMapper menuMapper;
|
private final MenuMapper menuMapper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.onixbyte.helix.manager;
|
package com.onixbyte.helix.manager;
|
||||||
|
|
||||||
import com.onixbyte.helix.domain.entity.Position;
|
import com.onixbyte.helix.domain.entity.Position;
|
||||||
import com.onixbyte.helix.mapper.PositionMapper;
|
|
||||||
import com.onixbyte.helix.repository.PositionRepository;
|
import com.onixbyte.helix.repository.PositionRepository;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
@@ -11,12 +10,10 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
public class PositionManager {
|
public class PositionManager {
|
||||||
|
|
||||||
private final PositionMapper positionMapper;
|
|
||||||
private final PositionRepository positionRepository;
|
private final PositionRepository positionRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public PositionManager(PositionMapper positionMapper, PositionRepository positionRepository) {
|
public PositionManager(PositionRepository positionRepository) {
|
||||||
this.positionMapper = positionMapper;
|
|
||||||
this.positionRepository = positionRepository;
|
this.positionRepository = positionRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.onixbyte.helix.manager;
|
package com.onixbyte.helix.manager;
|
||||||
|
|
||||||
import com.onixbyte.helix.repository.RoleAuthorityRepository;
|
import com.onixbyte.helix.mapper.RoleAuthorityMapper;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -9,14 +9,20 @@ import org.springframework.stereotype.Component;
|
|||||||
public class RoleAuthorityManager {
|
public class RoleAuthorityManager {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(RoleAuthorityManager.class);
|
private static final Logger log = LoggerFactory.getLogger(RoleAuthorityManager.class);
|
||||||
private final RoleAuthorityRepository roleAuthorityRepository;
|
private final RoleAuthorityMapper roleAuthorityMapper;
|
||||||
|
|
||||||
public RoleAuthorityManager(RoleAuthorityRepository roleAuthorityRepository) {
|
public RoleAuthorityManager(RoleAuthorityMapper roleAuthorityMapper) {
|
||||||
this.roleAuthorityRepository = roleAuthorityRepository;
|
this.roleAuthorityMapper = roleAuthorityMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteByRoleId(Long roleId) {
|
public void deleteByRoleId(Long roleId) {
|
||||||
var affectedRows = roleAuthorityRepository.deleteByRoleId(roleId);
|
var affectedRows = roleAuthorityMapper.deleteByRoleId(roleId);
|
||||||
log.info("角色 {} 关联的权限绑定已全部移除(共 {} 条)", roleId, affectedRows);
|
log.info("A total of {} authorities linked to Role ID: {} have been successfully cleared.",
|
||||||
|
affectedRows, roleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteByAuthorityId(Long authorityId) {
|
||||||
|
var affectedRows = roleAuthorityMapper.deleteByAuthorityId(authorityId);
|
||||||
|
log.info("The binding between {} authorities and the role has been cleared.", affectedRows);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,17 @@ package com.onixbyte.helix.manager;
|
|||||||
import com.onixbyte.helix.domain.database.query.wrapper.QueryRoleWrapper;
|
import com.onixbyte.helix.domain.database.query.wrapper.QueryRoleWrapper;
|
||||||
import com.onixbyte.helix.domain.entity.Role;
|
import com.onixbyte.helix.domain.entity.Role;
|
||||||
import com.onixbyte.helix.exception.BizException;
|
import com.onixbyte.helix.exception.BizException;
|
||||||
import com.onixbyte.helix.mapper.RoleAuthorityMapper;
|
|
||||||
import com.onixbyte.helix.mapper.RoleMapper;
|
import com.onixbyte.helix.mapper.RoleMapper;
|
||||||
import com.onixbyte.helix.repository.RoleRepository;
|
import com.onixbyte.helix.repository.RoleRepository;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
|
import com.onixbyte.helix.utils.MessageUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.*;
|
import org.springframework.data.domain.*;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -20,18 +22,18 @@ public class RoleManager {
|
|||||||
|
|
||||||
private final RoleMapper roleMapper;
|
private final RoleMapper roleMapper;
|
||||||
private final RoleRepository roleRepository;
|
private final RoleRepository roleRepository;
|
||||||
private final RoleAuthorityMapper roleAuthorityMapper;
|
private final MessageUtil messageUtil;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public RoleManager(RoleMapper roleMapper, RoleRepository roleRepository, RoleAuthorityMapper roleAuthorityMapper) {
|
public RoleManager(RoleMapper roleMapper, RoleRepository roleRepository, MessageUtil messageUtil) {
|
||||||
this.roleMapper = roleMapper;
|
this.roleMapper = roleMapper;
|
||||||
this.roleRepository = roleRepository;
|
this.roleRepository = roleRepository;
|
||||||
this.roleAuthorityMapper = roleAuthorityMapper;
|
this.messageUtil = messageUtil;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateRoles(List<Long> roleIds) {
|
public void validateRoles(List<Long> roleIds) {
|
||||||
if (!roleMapper.areRolesExisted(roleIds)) {
|
if (!roleMapper.areRolesExisted(roleIds)) {
|
||||||
throw new BizException(HttpStatus.BAD_REQUEST, "Role does not exist in database.");
|
throw new BizException(HttpStatus.BAD_REQUEST, MessageName.ROLE_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,23 +57,24 @@ public class RoleManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void updateRole(Role role) {
|
public Role fullUpdateById(Long id, Role role) {
|
||||||
var roleToUpdate = roleRepository.findById(role.getId())
|
var updatedAt = LocalDateTime.now();
|
||||||
.orElseThrow(() -> new BizException(HttpStatus.NOT_FOUND, "找不到指定的角色信息。"));
|
|
||||||
|
|
||||||
Optional.ofNullable(role.getName())
|
var roleToUpdate = roleRepository.findById(id)
|
||||||
.ifPresent(roleToUpdate::setName);
|
.orElseThrow(() -> new BizException(
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
Optional.ofNullable(role.getCode())
|
messageUtil.getMessage(MessageName.ROLE_NOT_FOUND, id))
|
||||||
.ifPresent(roleToUpdate::setCode);
|
);
|
||||||
|
|
||||||
Optional.ofNullable(role.getSort())
|
|
||||||
.ifPresent(roleToUpdate::setSort);
|
|
||||||
|
|
||||||
|
roleToUpdate.setName(role.getName());
|
||||||
|
roleToUpdate.setCode(role.getCode());
|
||||||
|
roleToUpdate.setSort(role.getSort());
|
||||||
|
roleToUpdate.setDefaultValue(role.getDefaultValue());
|
||||||
roleToUpdate.setDescription(role.getDescription());
|
roleToUpdate.setDescription(role.getDescription());
|
||||||
|
roleToUpdate.setStatus(role.getStatus());
|
||||||
|
roleToUpdate.setUpdatedAt(updatedAt);
|
||||||
|
|
||||||
Optional.ofNullable(role.getStatus())
|
return role;
|
||||||
.ifPresent(roleToUpdate::setStatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteRole(Long id) {
|
public void deleteRole(Long id) {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.onixbyte.helix.exception.BizException;
|
|||||||
import com.onixbyte.helix.mapper.UserMapper;
|
import com.onixbyte.helix.mapper.UserMapper;
|
||||||
import com.onixbyte.helix.repository.UserRepository;
|
import com.onixbyte.helix.repository.UserRepository;
|
||||||
import com.onixbyte.region.Region;
|
import com.onixbyte.region.Region;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.cache.annotation.CachePut;
|
import org.springframework.cache.annotation.CachePut;
|
||||||
@@ -112,7 +113,7 @@ public class UserManager {
|
|||||||
@Transactional(rollbackFor = Throwable.class)
|
@Transactional(rollbackFor = Throwable.class)
|
||||||
public User updateUser(User user) {
|
public User updateUser(User user) {
|
||||||
var userToUpdate = userRepository.findById(user.getId())
|
var userToUpdate = userRepository.findById(user.getId())
|
||||||
.orElseThrow(() -> new BizException(HttpStatus.BAD_REQUEST, "找不到 ID 为" + user.getId() + "的用户信息"));
|
.orElseThrow(() -> new BizException(HttpStatus.BAD_REQUEST, MessageName.USER_NOT_FOUND, user.getId()));
|
||||||
|
|
||||||
Optional.ofNullable(user.getFullName())
|
Optional.ofNullable(user.getFullName())
|
||||||
.filter(StringUtils::isNotBlank)
|
.filter(StringUtils::isNotBlank)
|
||||||
@@ -150,9 +151,9 @@ public class UserManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Throwable.class)
|
@Transactional(rollbackFor = Throwable.class)
|
||||||
public void updateUserPassword(ResetPasswordRequest request) {
|
public void updatePasswordById(Long id, ResetPasswordRequest request) {
|
||||||
userCredentialMapper.updateUserCredential(
|
userCredentialMapper.updateUserCredential(
|
||||||
request.id(),
|
id,
|
||||||
passwordEncoder.encode(request.password())
|
passwordEncoder.encode(request.password())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package com.onixbyte.helix.manager;
|
package com.onixbyte.helix.manager;
|
||||||
|
|
||||||
import com.onixbyte.helix.domain.entity.UserRole;
|
import com.onixbyte.helix.domain.entity.UserRole;
|
||||||
import com.onixbyte.helix.domain.entity.embeddable.UserRoleId;
|
|
||||||
import com.onixbyte.helix.mapper.UserRoleMapper;
|
|
||||||
import com.onixbyte.helix.repository.UserRoleRepository;
|
import com.onixbyte.helix.repository.UserRoleRepository;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -15,12 +13,10 @@ import java.util.List;
|
|||||||
public class UserRoleManager {
|
public class UserRoleManager {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(UserRoleManager.class);
|
private static final Logger log = LoggerFactory.getLogger(UserRoleManager.class);
|
||||||
private final UserRoleMapper userRoleMapper;
|
|
||||||
private final UserRoleRepository userRoleRepository;
|
private final UserRoleRepository userRoleRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public UserRoleManager(UserRoleMapper userRoleMapper, UserRoleRepository userRoleRepository) {
|
public UserRoleManager(UserRoleRepository userRoleRepository) {
|
||||||
this.userRoleMapper = userRoleMapper;
|
|
||||||
this.userRoleRepository = userRoleRepository;
|
this.userRoleRepository = userRoleRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,4 +7,6 @@ import org.apache.ibatis.annotations.Param;
|
|||||||
public interface RoleAuthorityMapper {
|
public interface RoleAuthorityMapper {
|
||||||
|
|
||||||
int deleteByRoleId(@Param("roleId") Long roleId);
|
int deleteByRoleId(@Param("roleId") Long roleId);
|
||||||
|
|
||||||
|
int deleteByAuthorityId(@Param("authorityId") Long authorityId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,16 @@ package com.onixbyte.helix.repository;
|
|||||||
|
|
||||||
import com.onixbyte.helix.domain.entity.Authority;
|
import com.onixbyte.helix.domain.entity.Authority;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface AuthorityRepository extends JpaRepository<Authority, Long> {
|
public interface AuthorityRepository extends JpaRepository<Authority, Long> {
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
select a.name
|
||||||
|
from Authority a
|
||||||
|
where a.id = :authorityId
|
||||||
|
""")
|
||||||
|
String findAuthorityNameById(Long authorityId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,6 @@ public interface DepartmentRepository extends JpaRepository<Department, Long> {
|
|||||||
or d.parentId = :parentId
|
or d.parentId = :parentId
|
||||||
""")
|
""")
|
||||||
Integer findMaxSort(Long parentId);
|
Integer findMaxSort(Long parentId);
|
||||||
|
|
||||||
|
boolean existsByName(String name);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -8,6 +8,7 @@ import com.onixbyte.helix.manager.AuthorityManager;
|
|||||||
import com.onixbyte.helix.manager.UserManager;
|
import com.onixbyte.helix.manager.UserManager;
|
||||||
import com.onixbyte.helix.repository.UserCredentialRepository;
|
import com.onixbyte.helix.repository.UserCredentialRepository;
|
||||||
import com.onixbyte.helix.security.authentication.UsernamePasswordAuthentication;
|
import com.onixbyte.helix.security.authentication.UsernamePasswordAuthentication;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -46,14 +47,14 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro
|
|||||||
@Override
|
@Override
|
||||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
if (!(authentication instanceof UsernamePasswordAuthentication usernamePasswordAuthentication)) {
|
if (!(authentication instanceof UsernamePasswordAuthentication usernamePasswordAuthentication)) {
|
||||||
throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, "用户认证失败,请稍后再试。");
|
throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, MessageName.AUTH_PROVIDER_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get user from database
|
// get user from database
|
||||||
var user = userManager.selectByUsername(usernamePasswordAuthentication.getPrincipal());
|
var user = userManager.selectByUsername(usernamePasswordAuthentication.getPrincipal());
|
||||||
if (Objects.isNull(user)) {
|
if (Objects.isNull(user)) {
|
||||||
log.error("User {} is trying to authenticate but no user found.", usernamePasswordAuthentication.getPrincipal());
|
log.error("User {} is trying to authenticate but no user found.", usernamePasswordAuthentication.getPrincipal());
|
||||||
throw new BizException(HttpStatus.UNAUTHORIZED, "用户名或密码错误。");
|
throw new BizException(HttpStatus.UNAUTHORIZED, MessageName.AUTH_PROVIDER_BAD_CREDENTIALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get user credentials from database
|
// get user credentials from database
|
||||||
@@ -61,12 +62,12 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro
|
|||||||
.provider(CredentialProvider.LOCAL)
|
.provider(CredentialProvider.LOCAL)
|
||||||
.userId(user.getId())
|
.userId(user.getId())
|
||||||
.build()))
|
.build()))
|
||||||
.orElseThrow(() -> new BizException(HttpStatus.UNAUTHORIZED, "您还没有配置密码,请使用第三方账号登录"));
|
.orElseThrow(() -> new BizException(HttpStatus.UNAUTHORIZED, MessageName.AUTH_PROVIDER_PASSWORD_NOT_CONFIGURED));
|
||||||
|
|
||||||
// validate password
|
// validate password
|
||||||
if (!passwordEncoder.matches(usernamePasswordAuthentication.getCredentials(), userCredentials.getCredential())) {
|
if (!passwordEncoder.matches(usernamePasswordAuthentication.getCredentials(), userCredentials.getCredential())) {
|
||||||
log.error("User {} is trying to authenticate but password is incorrect.", usernamePasswordAuthentication.getPrincipal());
|
log.error("User {} is trying to authenticate but password is incorrect.", usernamePasswordAuthentication.getPrincipal());
|
||||||
throw new BizException(HttpStatus.UNAUTHORIZED, "用户名或密码错误。");
|
throw new BizException(HttpStatus.UNAUTHORIZED, MessageName.AUTH_PROVIDER_BAD_CREDENTIALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// erase credentials
|
// erase credentials
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.onixbyte.helix.domain.entity.Asset;
|
|||||||
import com.onixbyte.helix.exception.BizException;
|
import com.onixbyte.helix.exception.BizException;
|
||||||
import com.onixbyte.helix.manager.AssetManager;
|
import com.onixbyte.helix.manager.AssetManager;
|
||||||
import com.onixbyte.helix.properties.AssetProperties;
|
import com.onixbyte.helix.properties.AssetProperties;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import com.onixbyte.helix.utils.SecurityUtil;
|
import com.onixbyte.helix.utils.SecurityUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -62,7 +63,7 @@ public class AssetService {
|
|||||||
if (Objects.isNull(prefix) || prefix.isBlank() || prefix.startsWith("/") || prefix.startsWith("..")) {
|
if (Objects.isNull(prefix) || prefix.isBlank() || prefix.startsWith("/") || prefix.startsWith("..")) {
|
||||||
throw new BizException(
|
throw new BizException(
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
"Prefix must not be empty, and should not start with '/' or '..'."
|
MessageName.ASSET_INVALID_PREFIX
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +109,7 @@ public class AssetService {
|
|||||||
var asset = assetManager.queryByAssetId(assetId);
|
var asset = assetManager.queryByAssetId(assetId);
|
||||||
|
|
||||||
if (!Objects.equals(currentUser.getId(), asset.getUploadBy())) {
|
if (!Objects.equals(currentUser.getId(), asset.getUploadBy())) {
|
||||||
throw new BizException(HttpStatus.FORBIDDEN, "You are not able to delete an asset that is not uploaded by you.");
|
throw new BizException(HttpStatus.FORBIDDEN, MessageName.ASSET_DELETE_FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
assetManager.deleteById(assetId);
|
assetManager.deleteById(assetId);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.onixbyte.helix.manager.CaptchaManager;
|
|||||||
import com.onixbyte.helix.manager.SecurityManager;
|
import com.onixbyte.helix.manager.SecurityManager;
|
||||||
import com.onixbyte.helix.manager.SettingManager;
|
import com.onixbyte.helix.manager.SettingManager;
|
||||||
import com.onixbyte.helix.security.authentication.UsernamePasswordAuthentication;
|
import com.onixbyte.helix.security.authentication.UsernamePasswordAuthentication;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import com.onixbyte.helix.shared.SettingName;
|
import com.onixbyte.helix.shared.SettingName;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -63,10 +64,10 @@ public class AuthService {
|
|||||||
var rawCaptcha = captchaManager.getCaptcha(uuid);
|
var rawCaptcha = captchaManager.getCaptcha(uuid);
|
||||||
|
|
||||||
if (Objects.isNull(rawCaptcha) || rawCaptcha.isBlank()) {
|
if (Objects.isNull(rawCaptcha) || rawCaptcha.isBlank()) {
|
||||||
throw new BizException(HttpStatus.BAD_REQUEST, "未找到验证码");
|
throw new BizException(HttpStatus.BAD_REQUEST, MessageName.AUTH_LOGIN_CAPTCHA_NOT_FOUND);
|
||||||
}
|
}
|
||||||
if (!rawCaptcha.equalsIgnoreCase(request.captcha())) {
|
if (!rawCaptcha.equalsIgnoreCase(request.captcha())) {
|
||||||
throw new BizException(HttpStatus.BAD_REQUEST, "验证码错误");
|
throw new BizException(HttpStatus.BAD_REQUEST, MessageName.AUTH_LOGIN_CAPTCHA_INCORRECT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +79,7 @@ public class AuthService {
|
|||||||
_authentication.getClass()
|
_authentication.getClass()
|
||||||
);
|
);
|
||||||
throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR,
|
throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
"Cannot perform login due to server crashes.");
|
MessageName.AUTH_LOGIN_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
return authentication.getDetails();
|
return authentication.getDetails();
|
||||||
|
|||||||
@@ -2,26 +2,28 @@ package com.onixbyte.helix.service;
|
|||||||
|
|
||||||
import com.onixbyte.helix.domain.database.query.wrapper.QueryAuthorityWrapper;
|
import com.onixbyte.helix.domain.database.query.wrapper.QueryAuthorityWrapper;
|
||||||
import com.onixbyte.helix.domain.entity.Authority;
|
import com.onixbyte.helix.domain.entity.Authority;
|
||||||
import com.onixbyte.helix.domain.web.request.AddAuthorityRequest;
|
import com.onixbyte.helix.domain.web.request.AuthorityRequest;
|
||||||
import com.onixbyte.helix.domain.web.request.EditAuthorityRequest;
|
|
||||||
import com.onixbyte.helix.domain.web.request.QueryAuthorityRequest;
|
import com.onixbyte.helix.domain.web.request.QueryAuthorityRequest;
|
||||||
import com.onixbyte.helix.enumeration.Status;
|
|
||||||
import com.onixbyte.helix.exception.BizException;
|
import com.onixbyte.helix.exception.BizException;
|
||||||
import com.onixbyte.helix.manager.AuthorityManager;
|
import com.onixbyte.helix.manager.AuthorityManager;
|
||||||
|
import com.onixbyte.helix.manager.RoleAuthorityManager;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class AuthorityService {
|
public class AuthorityService {
|
||||||
|
|
||||||
private final AuthorityManager authorityManager;
|
private final AuthorityManager authorityManager;
|
||||||
|
private final RoleAuthorityManager roleAuthorityManager;
|
||||||
|
|
||||||
public AuthorityService(AuthorityManager authorityManager) {
|
public AuthorityService(AuthorityManager authorityManager, RoleAuthorityManager roleAuthorityManager) {
|
||||||
this.authorityManager = authorityManager;
|
this.authorityManager = authorityManager;
|
||||||
|
this.roleAuthorityManager = roleAuthorityManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<Authority> getAuthorities(Pageable pageable, QueryAuthorityRequest request) {
|
public Page<Authority> getAuthorities(Pageable pageable, QueryAuthorityRequest request) {
|
||||||
@@ -30,24 +32,40 @@ public class AuthorityService {
|
|||||||
return authorityManager.selectAll(pageable, wrapper);
|
return authorityManager.selectAll(pageable, wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Authority addAuthority(AddAuthorityRequest request) {
|
public Authority addAuthority(AuthorityRequest request) {
|
||||||
var authority = Authority.builder()
|
var authority = Authority.builder()
|
||||||
.code(request.code())
|
.code(request.code())
|
||||||
.name(request.name())
|
.name(request.name())
|
||||||
.description(request.description())
|
.description(request.description())
|
||||||
.status(Optional.ofNullable(request.status())
|
.status(request.status())
|
||||||
.map(Status::valueOf)
|
|
||||||
.orElse(Status.ACTIVE))
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (authorityManager.existsByCode(authority)) {
|
if (authorityManager.existsByCode(authority)) {
|
||||||
throw new BizException(HttpStatus.CONFLICT, "权限编码 `" + authority.getCode() + "` 已被使用");
|
throw new BizException(HttpStatus.CONFLICT, MessageName.AUTHORITY_CODE_USED, authority.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
return authorityManager.save(authority);
|
return authorityManager.save(authority);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Authority editAuthority(EditAuthorityRequest request) {
|
public Authority editAuthority(Long id, AuthorityRequest request) {
|
||||||
return authorityManager.update(request);
|
return authorityManager.fullUpdateById(id, Authority.builder()
|
||||||
|
.name(request.name())
|
||||||
|
.description(request.description())
|
||||||
|
.status(request.status())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Throwable.class)
|
||||||
|
public String deleteAuthority(Long authorityId) {
|
||||||
|
var authorityName = authorityManager.findAuthorityNameById(authorityId);
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(authorityName)) {
|
||||||
|
throw new BizException(HttpStatus.NOT_FOUND, MessageName.AUTHORITY_NOT_FOUND, authorityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
roleAuthorityManager.deleteByAuthorityId(authorityId);
|
||||||
|
authorityManager.deleteById(authorityId);
|
||||||
|
|
||||||
|
return authorityName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package com.onixbyte.helix.service;
|
package com.onixbyte.helix.service;
|
||||||
|
|
||||||
import com.onixbyte.captcha.Producer;
|
import com.onixbyte.captcha.Producer;
|
||||||
import com.onixbyte.helix.shared.FileType;
|
|
||||||
import com.onixbyte.helix.shared.SettingName;
|
|
||||||
import com.onixbyte.helix.domain.entity.Setting;
|
import com.onixbyte.helix.domain.entity.Setting;
|
||||||
import com.onixbyte.helix.domain.web.response.CaptchaResponse;
|
import com.onixbyte.helix.domain.web.response.CaptchaResponse;
|
||||||
import com.onixbyte.helix.exception.BizException;
|
import com.onixbyte.helix.exception.BizException;
|
||||||
import com.onixbyte.helix.manager.CaptchaManager;
|
import com.onixbyte.helix.manager.CaptchaManager;
|
||||||
import com.onixbyte.helix.manager.SettingManager;
|
import com.onixbyte.helix.manager.SettingManager;
|
||||||
|
import com.onixbyte.helix.shared.FileType;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
|
import com.onixbyte.helix.shared.SettingName;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.FastByteArrayOutputStream;
|
import org.springframework.util.FastByteArrayOutputStream;
|
||||||
@@ -66,7 +67,7 @@ public class CaptchaService {
|
|||||||
Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
|
Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
|
||||||
return new CaptchaResponse(captchaDataUrl, uuid);
|
return new CaptchaResponse(captchaDataUrl, uuid);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new BizException("无法生成验证码图片。");
|
throw new BizException(MessageName.CAPTCHA_GENERATE_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,15 @@ package com.onixbyte.helix.service;
|
|||||||
|
|
||||||
import com.onixbyte.helix.domain.common.TreeNode;
|
import com.onixbyte.helix.domain.common.TreeNode;
|
||||||
import com.onixbyte.helix.domain.entity.Department;
|
import com.onixbyte.helix.domain.entity.Department;
|
||||||
import com.onixbyte.helix.domain.web.request.AddDepartmentRequest;
|
import com.onixbyte.helix.domain.web.request.DepartmentRequest;
|
||||||
import com.onixbyte.helix.enumeration.Status;
|
import com.onixbyte.helix.enumeration.Status;
|
||||||
|
import com.onixbyte.helix.exception.BizException;
|
||||||
import com.onixbyte.helix.manager.DepartmentManager;
|
import com.onixbyte.helix.manager.DepartmentManager;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import com.onixbyte.helix.utils.TreeUtil;
|
import com.onixbyte.helix.utils.TreeUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@@ -35,9 +38,13 @@ public class DepartmentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Throwable.class)
|
@Transactional(rollbackFor = Throwable.class)
|
||||||
public Department addDepartment(AddDepartmentRequest request) {
|
public Department addDepartment(DepartmentRequest request) {
|
||||||
var createdAt = LocalDateTime.now();
|
var createdAt = LocalDateTime.now();
|
||||||
|
|
||||||
|
if (departmentManager.existsByName(request.name())) {
|
||||||
|
throw new BizException(HttpStatus.CONFLICT, MessageName.REQUEST_CREATE_DEPARTMENT_NAME_DUPLICATED);
|
||||||
|
}
|
||||||
|
|
||||||
var parentId = request.parentId();
|
var parentId = request.parentId();
|
||||||
var sort = Optional.ofNullable(request.sort())
|
var sort = Optional.ofNullable(request.sort())
|
||||||
.orElseGet(() -> departmentManager.getNextSort(parentId));
|
.orElseGet(() -> departmentManager.getNextSort(parentId));
|
||||||
@@ -51,4 +58,17 @@ public class DepartmentService {
|
|||||||
.updatedAt(createdAt)
|
.updatedAt(createdAt)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Department editDepartment(Long id, DepartmentRequest request) {
|
||||||
|
if (departmentManager.existsByName(request.name())) {
|
||||||
|
throw new BizException(HttpStatus.CONFLICT, MessageName.REQUEST_CREATE_DEPARTMENT_NAME_DUPLICATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return departmentManager.fullUpdateById(id, Department.builder()
|
||||||
|
.name(request.name())
|
||||||
|
.parentId(request.parentId())
|
||||||
|
.sort(request.sort())
|
||||||
|
.status(request.status())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import com.onixbyte.helix.domain.common.TreeNode;
|
|||||||
import com.onixbyte.helix.manager.MenuManager;
|
import com.onixbyte.helix.manager.MenuManager;
|
||||||
import com.onixbyte.helix.utils.SecurityUtil;
|
import com.onixbyte.helix.utils.SecurityUtil;
|
||||||
import com.onixbyte.helix.utils.TreeUtil;
|
import com.onixbyte.helix.utils.TreeUtil;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -14,7 +12,7 @@ import java.util.List;
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class MenuService {
|
public class MenuService {
|
||||||
private static final Logger log = LoggerFactory.getLogger(MenuService.class);
|
|
||||||
private final MenuManager menuManager;
|
private final MenuManager menuManager;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
package com.onixbyte.helix.service;
|
package com.onixbyte.helix.service;
|
||||||
|
|
||||||
import com.onixbyte.helix.enumeration.Status;
|
|
||||||
import com.onixbyte.helix.domain.database.query.wrapper.QueryRoleWrapper;
|
import com.onixbyte.helix.domain.database.query.wrapper.QueryRoleWrapper;
|
||||||
import com.onixbyte.helix.domain.entity.Role;
|
import com.onixbyte.helix.domain.entity.Role;
|
||||||
import com.onixbyte.helix.domain.web.request.AddRoleRequest;
|
|
||||||
import com.onixbyte.helix.domain.web.request.EditRoleRequest;
|
|
||||||
import com.onixbyte.helix.domain.web.request.QueryRoleRequest;
|
import com.onixbyte.helix.domain.web.request.QueryRoleRequest;
|
||||||
|
import com.onixbyte.helix.domain.web.request.RoleRequest;
|
||||||
|
import com.onixbyte.helix.enumeration.Status;
|
||||||
|
import com.onixbyte.helix.exception.BizException;
|
||||||
import com.onixbyte.helix.manager.RoleAuthorityManager;
|
import com.onixbyte.helix.manager.RoleAuthorityManager;
|
||||||
import com.onixbyte.helix.manager.RoleManager;
|
import com.onixbyte.helix.manager.RoleManager;
|
||||||
import com.onixbyte.helix.manager.UserRoleManager;
|
import com.onixbyte.helix.manager.UserRoleManager;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
|
import com.onixbyte.helix.utils.MessageUtil;
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -24,16 +27,19 @@ public class RoleService {
|
|||||||
private final RoleManager roleManager;
|
private final RoleManager roleManager;
|
||||||
private final RoleAuthorityManager roleAuthorityManager;
|
private final RoleAuthorityManager roleAuthorityManager;
|
||||||
private final UserRoleManager userRoleManager;
|
private final UserRoleManager userRoleManager;
|
||||||
|
private final MessageUtil messageUtil;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public RoleService(
|
public RoleService(
|
||||||
RoleManager roleManager,
|
RoleManager roleManager,
|
||||||
RoleAuthorityManager roleAuthorityManager,
|
RoleAuthorityManager roleAuthorityManager,
|
||||||
UserRoleManager userRoleManager
|
UserRoleManager userRoleManager,
|
||||||
|
MessageUtil messageUtil
|
||||||
) {
|
) {
|
||||||
this.roleManager = roleManager;
|
this.roleManager = roleManager;
|
||||||
this.roleAuthorityManager = roleAuthorityManager;
|
this.roleAuthorityManager = roleAuthorityManager;
|
||||||
this.userRoleManager = userRoleManager;
|
this.userRoleManager = userRoleManager;
|
||||||
|
this.messageUtil = messageUtil;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<Role> getRoles(Pageable pageable, QueryRoleRequest request) {
|
public Page<Role> getRoles(Pageable pageable, QueryRoleRequest request) {
|
||||||
@@ -55,11 +61,12 @@ public class RoleService {
|
|||||||
return roleManager.selectAll(pageable, wrapper);
|
return roleManager.selectAll(pageable, wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Role addRole(AddRoleRequest request) {
|
public Role addRole(RoleRequest request) {
|
||||||
var isDefaultRole = Optional.ofNullable(request.defaultValue())
|
var isDefaultRole = Optional.of(request)
|
||||||
|
.map(RoleRequest::defaultValue)
|
||||||
.orElse(false);
|
.orElse(false);
|
||||||
var status = Optional.ofNullable(request.status())
|
var status = Optional.of(request)
|
||||||
.map(Status::valueOf)
|
.map(RoleRequest::status)
|
||||||
.orElse(Status.ACTIVE);
|
.orElse(Status.ACTIVE);
|
||||||
|
|
||||||
var role = Role.builder()
|
var role = Role.builder()
|
||||||
@@ -75,24 +82,29 @@ public class RoleService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void editRole(EditRoleRequest request) {
|
public Role editRole(Long id, RoleRequest request) {
|
||||||
roleManager.updateRole(Role.builder()
|
return roleManager.fullUpdateById(id, Role.builder()
|
||||||
.id(request.id())
|
|
||||||
.name(request.name())
|
.name(request.name())
|
||||||
.code(request.code())
|
.code(request.code())
|
||||||
.sort(request.sort())
|
.sort(request.sort())
|
||||||
.defaultValue(request.defaultValue())
|
.defaultValue(request.defaultValue())
|
||||||
.description(request.description())
|
.description(request.description())
|
||||||
.status(Optional.ofNullable(request.status())
|
.status(request.status())
|
||||||
.map(Status::valueOf)
|
|
||||||
.orElse(null))
|
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void deleteRole(Long id) {
|
public String deleteRole(Long id) {
|
||||||
|
var role = roleManager.getRoleById(id)
|
||||||
|
.orElseThrow(() -> new BizException(
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
messageUtil.getMessage(MessageName.ROLE_NOT_FOUND, id))
|
||||||
|
);
|
||||||
|
|
||||||
roleAuthorityManager.deleteByRoleId(id);
|
roleAuthorityManager.deleteByRoleId(id);
|
||||||
userRoleManager.deleteByRoleId(id);
|
userRoleManager.deleteByRoleId(id);
|
||||||
roleManager.deleteRole(id);
|
roleManager.deleteRole(id);
|
||||||
|
|
||||||
|
return role.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,9 +143,9 @@ public class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Throwable.class)
|
@Transactional(rollbackFor = Throwable.class)
|
||||||
public void updateUser(EditUserRequest request) {
|
public UserDetailResponse updateUser(Long id, EditUserRequest request) {
|
||||||
userManager.updateUser(User.builder()
|
userManager.updateUser(User.builder()
|
||||||
.id(request.id())
|
.id(id)
|
||||||
.fullName(request.fullName())
|
.fullName(request.fullName())
|
||||||
.email(request.email())
|
.email(request.email())
|
||||||
.regionAbbreviation(request.regionAbbreviation())
|
.regionAbbreviation(request.regionAbbreviation())
|
||||||
@@ -155,6 +155,8 @@ public class UserService {
|
|||||||
.departmentId(request.departmentId())
|
.departmentId(request.departmentId())
|
||||||
.positionId(request.positionId())
|
.positionId(request.positionId())
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
|
return getUserDetailByUserId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserDetailResponse getUserDetailByUserId(Long userId) {
|
public UserDetailResponse getUserDetailByUserId(Long userId) {
|
||||||
@@ -162,8 +164,8 @@ public class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Throwable.class)
|
@Transactional(rollbackFor = Throwable.class)
|
||||||
public void resetPassword(ResetPasswordRequest request) {
|
public void resetPassword(Long id, ResetPasswordRequest request) {
|
||||||
userManager.updateUserPassword(request);
|
userManager.updatePasswordById(id, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Throwable.class)
|
@Transactional(rollbackFor = Throwable.class)
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024-2026 OnixByte
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.onixbyte.helix.shared;
|
||||||
|
|
||||||
|
public class MessageName {
|
||||||
|
|
||||||
|
public static final String ASSET_NOT_EMPTY = "asset.not-empty";
|
||||||
|
public static final String ASSET_INVALID_PREFIX = "asset.invalid-prefix";
|
||||||
|
public static final String ASSET_DELETE_FORBIDDEN = "asset.delete-forbidden";
|
||||||
|
public static final String ASSET_UPLOAD_FAILED = "asset.upload-failed";
|
||||||
|
|
||||||
|
public static final String AUTHORITY_DELETED = "authority.deleted";
|
||||||
|
public static final String AUTHORITY_CODE_USED = "authority.code-used";
|
||||||
|
public static final String AUTHORITY_NOT_FOUND = "authority.not-found";
|
||||||
|
|
||||||
|
public static final String AUTH_LOGIN_CAPTCHA_NOT_FOUND = "auth.login.captcha-not-found";
|
||||||
|
public static final String AUTH_LOGIN_CAPTCHA_INCORRECT = "auth.login.captcha-incorrect";
|
||||||
|
public static final String AUTH_LOGIN_FAILED = "auth.login.failed";
|
||||||
|
|
||||||
|
public static final String AUTH_PROVIDER_FAILED = "auth.provider.failed";
|
||||||
|
public static final String AUTH_PROVIDER_BAD_CREDENTIALS = "auth.provider.bad-credentials";
|
||||||
|
public static final String AUTH_PROVIDER_PASSWORD_NOT_CONFIGURED = "auth.provider.password-not-configured";
|
||||||
|
|
||||||
|
public static final String CAPTCHA_GENERATE_FAILED = "captcha.generate-failed";
|
||||||
|
|
||||||
|
public static final String ROLE_NOT_EXISTS = "role.not-exists";
|
||||||
|
|
||||||
|
public static final String USER_PASSWORD_RESET_SUCCESS = "user.password-reset-success";
|
||||||
|
public static final String USER_DELETED = "user.deleted";
|
||||||
|
public static final String USER_NOT_FOUND = "user.not-found";
|
||||||
|
|
||||||
|
public static final String SECURITY_CONTEXT_USER_NOT_FOUND = "security.context-user-not-found";
|
||||||
|
public static final String TREE_MULTIPLE_ROOTS = "tree.multiple-roots";
|
||||||
|
|
||||||
|
public static final String ROLE_NOT_FOUND = "role.not-found";
|
||||||
|
public static final String ROLE_DELETED = "role.deleted";
|
||||||
|
|
||||||
|
public static final String REQUEST_ADD_USER_USERNAME_NOT_EMPTY = "request.add-user.username.not-empty";
|
||||||
|
public static final String REQUEST_ADD_USER_PASSWORD_NOT_EMPTY = "request.add-user.password.not-empty";
|
||||||
|
public static final String REQUEST_ADD_USER_FULL_NAME_NOT_EMPTY = "request.add-user.full-name.not-empty";
|
||||||
|
|
||||||
|
public static final String REQUEST_AUTHORITY_CODE_NOT_EDITABLE = "request.authority.code.not-editable";
|
||||||
|
public static final String REQUEST_AUTHORITY_CODE_NOT_NULL = "request.authority.code.not-null";
|
||||||
|
public static final String REQUEST_AUTHORITY_NAME_NOT_NULL = "request.authority.name.not-null";
|
||||||
|
|
||||||
|
public static final String REQUEST_DEPARTMENT_NAME_NOT_NULL = "request.department.name.not-null";
|
||||||
|
|
||||||
|
public static final String REQUEST_EDIT_ROLE_ID_NOT_NULL = "request.edit-role.id.not-null";
|
||||||
|
public static final String REQUEST_EDIT_ROLE_STATUS_INVALID = "request.edit-role.status.invalid";
|
||||||
|
|
||||||
|
public static final String REQUEST_EDIT_USER_ID_NOT_NULL = "request.edit-user.id.not-null";
|
||||||
|
public static final String REQUEST_EDIT_USER_ID_POSITIVE = "request.edit-user.id.positive";
|
||||||
|
|
||||||
|
public static final String REQUEST_RESET_PASSWORD_NOT_EMPTY = "request.reset-password.password.not-empty";
|
||||||
|
|
||||||
|
public static final String REQUEST_ROLE_NAME_NOT_EMPTY = "request.role.name.not-empty";
|
||||||
|
public static final String REQUEST_ROLE_CODE_NOT_EMPTY = "request.role.code.not-empty";
|
||||||
|
public static final String REQUEST_ROLE_SORT_NOT_NULL = "request.role.sort.not-null";
|
||||||
|
|
||||||
|
public static final String REQUEST_QUERY_ROLE_STATUS_INVALID = "request.query-role.status.invalid";
|
||||||
|
public static final String REQUEST_QUERY_USER_STATUS_INVALID = "request.query-user.status.invalid";
|
||||||
|
|
||||||
|
public static final String REQUEST_CREATE_DEPARTMENT_NAME_DUPLICATED = "request.create-department.name-duplicated";
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024-2026 OnixByte
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.onixbyte.helix.utils;
|
||||||
|
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class MessageUtil {
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
public MessageUtil(MessageSource messageSource) {
|
||||||
|
this.messageSource = messageSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage(String code, Object... args) {
|
||||||
|
var locale = LocaleContextHolder.getLocale();
|
||||||
|
return messageSource.getMessage(code, args, locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.onixbyte.helix.utils;
|
|||||||
|
|
||||||
import com.onixbyte.helix.domain.entity.User;
|
import com.onixbyte.helix.domain.entity.User;
|
||||||
import com.onixbyte.helix.exception.BizException;
|
import com.onixbyte.helix.exception.BizException;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -32,7 +33,7 @@ public class SecurityUtil {
|
|||||||
|
|
||||||
if (!(_details instanceof User user)) {
|
if (!(_details instanceof User user)) {
|
||||||
log.error("Authentication details is {}", _details);
|
log.error("Authentication details is {}", _details);
|
||||||
throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, "Cannot retrieve user information from context.");
|
throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, MessageName.SECURITY_CONTEXT_USER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.onixbyte.helix.utils;
|
|||||||
import com.onixbyte.helix.domain.common.Treeable;
|
import com.onixbyte.helix.domain.common.Treeable;
|
||||||
import com.onixbyte.helix.domain.common.TreeNode;
|
import com.onixbyte.helix.domain.common.TreeNode;
|
||||||
import com.onixbyte.helix.exception.BizException;
|
import com.onixbyte.helix.exception.BizException;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ public class TreeUtil {
|
|||||||
|
|
||||||
// Ensure only 1 root node is included
|
// Ensure only 1 root node is included
|
||||||
if (rootItems.size() > 1) {
|
if (rootItems.size() > 1) {
|
||||||
throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, "Multiple root items found in given values.");
|
throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, MessageName.TREE_MULTIPLE_ROOTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get root item and build root node
|
// Get root item and build root node
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ spring:
|
|||||||
hikari:
|
hikari:
|
||||||
minimum-idle: 1
|
minimum-idle: 1
|
||||||
maximum-pool-size: 10
|
maximum-pool-size: 10
|
||||||
|
messages:
|
||||||
|
basename: i18n/messages
|
||||||
flyway:
|
flyway:
|
||||||
enabled: true
|
enabled: true
|
||||||
baseline-on-migrate: true
|
baseline-on-migrate: true
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2024-2026 OnixByte
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
asset.not-empty = File cannot be empty.
|
||||||
|
asset.invalid-prefix = Prefix must not be empty and must not start with '/' or '..'.
|
||||||
|
asset.delete-forbidden = You are not able to delete an asset that is not uploaded by you.
|
||||||
|
asset.upload-failed = Failed to upload file: {0}
|
||||||
|
|
||||||
|
authority.deleted = Authority [{0}] deleted.
|
||||||
|
authority.code-used = Authority code [{0}] is already in use.
|
||||||
|
authority.not-found = Authority with ID [{0}] not found.
|
||||||
|
|
||||||
|
auth.login.captcha-not-found = Captcha not found.
|
||||||
|
auth.login.captcha-incorrect = Captcha is incorrect.
|
||||||
|
auth.login.failed = Cannot perform login due to server error.
|
||||||
|
|
||||||
|
auth.provider.failed = Authentication failed, please try again later.
|
||||||
|
auth.provider.bad-credentials = Username or password is incorrect.
|
||||||
|
auth.provider.password-not-configured=Username or password is incorrect.
|
||||||
|
|
||||||
|
captcha.generate-failed = Unable to generate captcha image.
|
||||||
|
role.not-exists=Name of the authority cannot be null.
|
||||||
|
role.not-found = Role with ID {0} not found.
|
||||||
|
role.deleted = Role [{0}] deleted.
|
||||||
|
|
||||||
|
user.password-reset-success = Password has been reset.
|
||||||
|
user.deleted = User [{0}] deleted.
|
||||||
|
user.not-found = User with ID [{0}] not found.
|
||||||
|
|
||||||
|
security.context-user-not-found = Cannot retrieve user information from security context.
|
||||||
|
tree.multiple-roots = Multiple root items found in given values.
|
||||||
|
|
||||||
|
request.add-user.username.not-empty = Username cannot be empty.
|
||||||
|
request.add-user.password.not-empty = Password cannot be empty.
|
||||||
|
request.add-user.full-name.not-empty = Full name cannot be empty.
|
||||||
|
|
||||||
|
request.authority.code.not-editable = Code cannot be edited.
|
||||||
|
request.authority.code.not-null = Code cannot be null.
|
||||||
|
request.authority.name.not-null = Name of the authority cannot be null.
|
||||||
|
|
||||||
|
request.department.name.not-null = Name of the department should not be null.
|
||||||
|
|
||||||
|
request.edit-role.id.not-null = Role ID cannot be null.
|
||||||
|
request.edit-role.status.invalid = Status can only be ACTIVE or INACTIVE.
|
||||||
|
|
||||||
|
request.edit-user.id.not-null = User ID cannot be null.
|
||||||
|
request.edit-user.id.positive = User ID must be positive.
|
||||||
|
|
||||||
|
request.reset-password.password.not-empty = Password cannot be empty.
|
||||||
|
|
||||||
|
request.role.name.not-empty = Name of the role cannot be empty.
|
||||||
|
request.role.code.not-empty = Code of the role cannot be empty.
|
||||||
|
request.role.sort.not-null = Sort number cannot be null.
|
||||||
|
|
||||||
|
request.query-role.status.invalid = Status can only be ACTIVE or INACTIVE.
|
||||||
|
request.query-user.status.invalid = Status can only be ACTIVE, INACTIVE, or LOCKED.
|
||||||
|
request.create-department.name-duplicated=Name of the department already exists.
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2024-2026 OnixByte
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
asset.not-empty = File cannot be empty.
|
||||||
|
asset.invalid-prefix = Prefix must not be empty and must not start with '/' or '..'.
|
||||||
|
asset.delete-forbidden = You are not able to delete an asset that is not uploaded by you.
|
||||||
|
asset.upload-failed = Failed to upload file: {0}
|
||||||
|
|
||||||
|
authority.deleted = Authority [{0}] deleted.
|
||||||
|
authority.code-used = Authority code [{0}] is already in use.
|
||||||
|
authority.not-found = Authority with ID [{0}] not found.
|
||||||
|
|
||||||
|
auth.login.captcha-not-found = Captcha not found.
|
||||||
|
auth.login.captcha-incorrect = Captcha is incorrect.
|
||||||
|
auth.login.failed = Cannot perform login due to server error.
|
||||||
|
|
||||||
|
auth.provider.failed = Authentication failed, please try again later.
|
||||||
|
auth.provider.bad-credentials = Username or password is incorrect.
|
||||||
|
auth.provider.password-not-configured = Password is not configured. Please sign in with a third-party account.
|
||||||
|
|
||||||
|
captcha.generate-failed = Unable to generate captcha image.
|
||||||
|
|
||||||
|
role.not-exists = Role does not exist in database.
|
||||||
|
role.not-found = Role with ID {0} not found.
|
||||||
|
role.deleted = Role [{0}] deleted.
|
||||||
|
|
||||||
|
user.password-reset-success = Password has been reset.
|
||||||
|
user.deleted = User [{0}] deleted.
|
||||||
|
user.not-found = User with ID [{0}] not found.
|
||||||
|
|
||||||
|
security.context-user-not-found = Cannot retrieve user information from security context.
|
||||||
|
tree.multiple-roots = Multiple root items found in given values.
|
||||||
|
|
||||||
|
request.add-user.username.not-empty = Username cannot be empty.
|
||||||
|
request.add-user.password.not-empty = Password cannot be empty.
|
||||||
|
request.add-user.full-name.not-empty = Full name cannot be empty.
|
||||||
|
|
||||||
|
request.authority.code.not-editable = Code cannot be edited.
|
||||||
|
request.authority.code.not-null = Code cannot be null.
|
||||||
|
request.authority.name.not-null = Name of the authority cannot be null.
|
||||||
|
|
||||||
|
request.department.name.not-null = Name of the department should not be null.
|
||||||
|
|
||||||
|
request.edit-role.id.not-null = Role ID cannot be null.
|
||||||
|
request.edit-role.status.invalid = Status can only be ACTIVE or INACTIVE.
|
||||||
|
|
||||||
|
request.edit-user.id.not-null = User ID cannot be null.
|
||||||
|
request.edit-user.id.positive = User ID must be positive.
|
||||||
|
|
||||||
|
request.reset-password.password.not-empty = Password cannot be empty.
|
||||||
|
|
||||||
|
request.role.name.not-empty = Name of the role cannot be empty.
|
||||||
|
request.role.code.not-empty = Code of the role cannot be empty.
|
||||||
|
request.role.sort.not-null = Sort number cannot be null.
|
||||||
|
|
||||||
|
request.query-role.status.invalid = Status can only be ACTIVE or INACTIVE.
|
||||||
|
request.query-user.status.invalid = Status can only be ACTIVE, INACTIVE, or LOCKED.
|
||||||
|
request.create-department.name-duplicated=Name of the department already exists.
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2024-2026 OnixByte
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
asset.not-empty = 文件不能为空。
|
||||||
|
asset.invalid-prefix = 前缀不能为空,且不能以 '/' 或 '..' 开头。
|
||||||
|
asset.delete-forbidden = 你不能删除非自己上传的文件。
|
||||||
|
asset.upload-failed = 文件上传失败:{0}
|
||||||
|
|
||||||
|
authority.deleted = 权限【{0}】删除成功。
|
||||||
|
authority.code-used = 权限编码【{0}】已被使用。
|
||||||
|
authority.not-found = 找不到 ID 为【{0}】的权限。
|
||||||
|
|
||||||
|
auth.login.captcha-not-found = 未找到验证码。
|
||||||
|
auth.login.captcha-incorrect = 验证码错误。
|
||||||
|
auth.login.failed = 登录失败,服务器出现错误。
|
||||||
|
|
||||||
|
auth.provider.failed = 用户认证失败,请稍后再试。
|
||||||
|
auth.provider.bad-credentials = 用户名或密码错误。
|
||||||
|
auth.provider.password-not-configured = 你还没有配置密码,请使用第三方账号登录。
|
||||||
|
|
||||||
|
captcha.generate-failed = 无法生成验证码图片。
|
||||||
|
|
||||||
|
role.not-exists = 角色不存在。
|
||||||
|
role.not-found = 找不到 ID 为 {0} 的角色。
|
||||||
|
role.deleted = 角色【{0}】删除成功。
|
||||||
|
|
||||||
|
user.password-reset-success = 密码修改成功。
|
||||||
|
user.deleted = 用户【{0}】删除成功。
|
||||||
|
user.not-found = 找不到 ID 为【{0}】的用户信息。
|
||||||
|
|
||||||
|
security.context-user-not-found = 无法从安全上下文中获取用户信息。
|
||||||
|
tree.multiple-roots = 数据中包含多个根节点。
|
||||||
|
|
||||||
|
request.add-user.username.not-empty = 用户名不能为空。
|
||||||
|
request.add-user.password.not-empty = 密码不能为空。
|
||||||
|
request.add-user.full-name.not-empty = 姓名不能为空。
|
||||||
|
|
||||||
|
request.authority.code.not-editable = 权限编码不可修改。
|
||||||
|
request.authority.code.not-null = 权限编码不能为空。
|
||||||
|
request.authority.name.not-null = 权限名称不能为空。
|
||||||
|
|
||||||
|
request.department.name.not-null = 部门名称不能为空。
|
||||||
|
|
||||||
|
request.edit-role.id.not-null = 角色 ID 不能为空。
|
||||||
|
request.edit-role.status.invalid = 状态只能是 ACTIVE 或 INACTIVE。
|
||||||
|
|
||||||
|
request.edit-user.id.not-null = 用户 ID 不能为空。
|
||||||
|
request.edit-user.id.positive = 用户 ID 必须为正数。
|
||||||
|
|
||||||
|
request.reset-password.password.not-empty = 密码不能为空。
|
||||||
|
|
||||||
|
request.role.name.not-empty = 角色名称不能为空。
|
||||||
|
request.role.code.not-empty = 角色编码不能为空。
|
||||||
|
request.role.sort.not-null = 排序编号不能为空。
|
||||||
|
|
||||||
|
request.query-role.status.invalid = 状态只能是 ACTIVE 或 INACTIVE。
|
||||||
|
request.query-user.status.invalid = 状态只能是 ACTIVE、INACTIVE 或 LOCKED。
|
||||||
|
request.create-department.name-duplicated=部门名称已存在。
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.onixbyte.helix.mapper.AuthorityMapper">
|
<mapper namespace="com.onixbyte.helix.mapper.AuthorityMapper">
|
||||||
<select id="selectByUserId" parameterType="long">
|
<select id="selectByUserId" parameterType="long" resultType="com.onixbyte.helix.domain.entity.Authority">
|
||||||
SELECT DISTINCT a.id, a.code, a.name, a.description, a.status, a.created_at, a.updated_at
|
SELECT DISTINCT a.id, a.code, a.name, a.description, a.status, a.created_at, a.updated_at
|
||||||
FROM authority a
|
FROM authority a
|
||||||
JOIN role_authority ra ON a.id = ra.authority_id
|
JOIN role_authority ra ON a.id = ra.authority_id
|
||||||
|
|||||||
@@ -7,4 +7,10 @@
|
|||||||
FROM role_authority
|
FROM role_authority
|
||||||
WHERE role_id = #{roleId}
|
WHERE role_id = #{roleId}
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
|
<delete id="deleteByAuthorityId" parameterType="long">
|
||||||
|
DELETE
|
||||||
|
FROM role_authority
|
||||||
|
WHERE authority_id = #{authorityId}
|
||||||
|
</delete>
|
||||||
</mapper>
|
</mapper>
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="count" parameterType="com.onixbyte.helix.domain.database.query.wrapper.QueryRoleWrapper">
|
<select id="count" parameterType="com.onixbyte.helix.domain.database.query.wrapper.QueryRoleWrapper" resultType="int">
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*)
|
||||||
FROM role
|
FROM role
|
||||||
<where>
|
<where>
|
||||||
|
|||||||
Reference in New Issue
Block a user