feat(admin): implement tenant/user/role account APIs
This commit is contained in:
@@ -36,6 +36,11 @@
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-spring</artifactId>
|
||||
<version>3.0.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
@@ -58,6 +63,12 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-webmvc-test</artifactId>
|
||||
<version>4.1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.sino.mci.admin.controller;
|
||||
|
||||
import com.sino.mci.admin.dto.CreateTenantRequest;
|
||||
import com.sino.mci.admin.dto.CreateUserRequest;
|
||||
import com.sino.mci.admin.dto.LoginRequest;
|
||||
import com.sino.mci.admin.service.AccountService;
|
||||
import com.sino.mci.shared.web.ApiResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/account")
|
||||
@RequiredArgsConstructor
|
||||
public class AccountController {
|
||||
|
||||
private final AccountService accountService;
|
||||
|
||||
@PostMapping("/tenant")
|
||||
public ApiResponse<?> createTenant(@Valid @RequestBody CreateTenantRequest request) {
|
||||
return ApiResponse.ok(accountService.createTenant(request));
|
||||
}
|
||||
|
||||
@PostMapping("/user")
|
||||
public ApiResponse<?> createUser(
|
||||
@RequestHeader("X-Tenant-Code") String tenantCode,
|
||||
@Valid @RequestBody CreateUserRequest request) {
|
||||
return ApiResponse.ok(accountService.createUser(tenantCode, request));
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ApiResponse<?> login(
|
||||
@RequestHeader("X-Tenant-Code") String tenantCode,
|
||||
@Valid @RequestBody LoginRequest request) {
|
||||
return ApiResponse.ok(accountService.login(tenantCode, request.getUsername(), request.getPassword()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.sino.mci.admin.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CreateTenantRequest {
|
||||
|
||||
@NotBlank
|
||||
private String tenantCode;
|
||||
|
||||
@NotBlank
|
||||
private String tenantName;
|
||||
|
||||
private String inboundWebhookUrl;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.sino.mci.admin.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class CreateUserRequest {
|
||||
|
||||
@NotBlank
|
||||
private String username;
|
||||
|
||||
@NotBlank
|
||||
private String password;
|
||||
|
||||
private String realName;
|
||||
private String phone;
|
||||
private List<String> roleCodes;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.sino.mci.admin.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class LoginRequest {
|
||||
|
||||
@NotBlank
|
||||
private String username;
|
||||
|
||||
@NotBlank
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.sino.mci.admin.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.sino.mci.admin.dto.CreateTenantRequest;
|
||||
import com.sino.mci.admin.dto.CreateUserRequest;
|
||||
import com.sino.mci.admin.entity.PlatformRole;
|
||||
import com.sino.mci.admin.entity.PlatformUser;
|
||||
import com.sino.mci.admin.entity.Tenant;
|
||||
import com.sino.mci.admin.entity.UserRole;
|
||||
import com.sino.mci.admin.repository.PlatformRoleMapper;
|
||||
import com.sino.mci.admin.repository.PlatformUserMapper;
|
||||
import com.sino.mci.admin.repository.TenantMapper;
|
||||
import com.sino.mci.admin.repository.UserRoleMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.crypto.bcrypt.BCrypt;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AccountService {
|
||||
|
||||
private final TenantMapper tenantMapper;
|
||||
private final PlatformUserMapper userMapper;
|
||||
private final PlatformRoleMapper roleMapper;
|
||||
private final UserRoleMapper userRoleMapper;
|
||||
|
||||
@Transactional
|
||||
public Tenant createTenant(CreateTenantRequest request) {
|
||||
Tenant tenant = new Tenant();
|
||||
tenant.setTenantCode(request.getTenantCode());
|
||||
tenant.setTenantName(request.getTenantName());
|
||||
tenant.setInboundWebhookUrl(request.getInboundWebhookUrl());
|
||||
tenant.setStatus(1);
|
||||
tenantMapper.insert(tenant);
|
||||
return tenant;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public PlatformUser createUser(String tenantCode, CreateUserRequest request) {
|
||||
PlatformUser user = new PlatformUser();
|
||||
user.setTenantCode(tenantCode);
|
||||
user.setUsername(request.getUsername());
|
||||
user.setPassword(BCrypt.hashpw(request.getPassword(), BCrypt.gensalt()));
|
||||
user.setRealName(request.getRealName());
|
||||
user.setPhone(request.getPhone());
|
||||
user.setStatus(1);
|
||||
userMapper.insert(user);
|
||||
|
||||
if (!CollectionUtils.isEmpty(request.getRoleCodes())) {
|
||||
for (String roleCode : request.getRoleCodes()) {
|
||||
PlatformRole role = roleMapper.selectOne(
|
||||
new LambdaQueryWrapper<PlatformRole>().eq(PlatformRole::getRoleCode, roleCode));
|
||||
if (role != null) {
|
||||
UserRole userRole = new UserRole();
|
||||
userRole.setUserId(user.getId());
|
||||
userRole.setRoleId(role.getId());
|
||||
userRoleMapper.insert(userRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
public PlatformUser login(String tenantCode, String username, String password) {
|
||||
PlatformUser user = userMapper.selectOne(
|
||||
new LambdaQueryWrapper<PlatformUser>()
|
||||
.eq(PlatformUser::getTenantCode, tenantCode)
|
||||
.eq(PlatformUser::getUsername, username)
|
||||
.eq(PlatformUser::getStatus, 1));
|
||||
if (user == null || !BCrypt.checkpw(password, user.getPassword())) {
|
||||
throw new RuntimeException("用户名或密码错误");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,28 @@
|
||||
package com.sino.mci.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@Configuration
|
||||
@MapperScan("com.sino.mci.admin.repository")
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
@Bean
|
||||
public SqlSessionFactory sqlSessionFactory(DataSource dataSource, MetaObjectHandler metaObjectHandler) throws Exception {
|
||||
MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
|
||||
factoryBean.setDataSource(dataSource);
|
||||
|
||||
GlobalConfig globalConfig = new GlobalConfig();
|
||||
globalConfig.setMetaObjectHandler(metaObjectHandler);
|
||||
factoryBean.setGlobalConfig(globalConfig);
|
||||
|
||||
return factoryBean.getObject();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.sino.mci.admin.controller;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
public class AccountControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void shouldCreateTenant() throws Exception {
|
||||
String tenantCode = "test-" + UUID.randomUUID().toString().substring(0, 8);
|
||||
String payload = String.format("{\"tenantCode\":\"%s\",\"tenantName\":\"测试租户\"}", tenantCode);
|
||||
mockMvc.perform(post("/msg-platform/api/v1/account/tenant")
|
||||
.contextPath("/msg-platform")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(payload))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andExpect(jsonPath("$.data.tenantCode").value(tenantCode));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.springframework.boot.test.autoconfigure.web.servlet;
|
||||
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@ImportAutoConfiguration({
|
||||
org.springframework.boot.webmvc.test.autoconfigure.MockMvcAutoConfiguration.class,
|
||||
org.springframework.boot.webmvc.test.autoconfigure.MockMvcWebClientAutoConfiguration.class,
|
||||
org.springframework.boot.webmvc.test.autoconfigure.MockMvcWebDriverAutoConfiguration.class
|
||||
})
|
||||
public @interface AutoConfigureMockMvc {
|
||||
}
|
||||
Reference in New Issue
Block a user