Initialize patbond microservice modules
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
package com.patbond.patbond.user;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class UserApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(UserApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.patbond.patbond.user.controller;
|
||||
|
||||
import com.patbond.patbond.common.response.ApiResponse;
|
||||
import com.patbond.patbond.common.user.CreateUserRequest;
|
||||
import com.patbond.patbond.common.user.UserProfile;
|
||||
import com.patbond.patbond.common.user.VerifyPasswordRequest;
|
||||
import com.patbond.patbond.common.user.VerifyPasswordResponse;
|
||||
import com.patbond.patbond.user.service.UserService;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/internal/users")
|
||||
public class UserController {
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
public UserController(UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ApiResponse<UserProfile> createUser(@Valid @RequestBody CreateUserRequest request) {
|
||||
return ApiResponse.success(userService.createUser(request));
|
||||
}
|
||||
|
||||
@PostMapping("/verify-password")
|
||||
public ApiResponse<VerifyPasswordResponse> verifyPassword(@Valid @RequestBody VerifyPasswordRequest request) {
|
||||
return ApiResponse.success(userService.verifyPassword(request));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ApiResponse<UserProfile> getById(@PathVariable Long id) {
|
||||
return ApiResponse.success(userService.getById(id));
|
||||
}
|
||||
|
||||
@GetMapping("/by-username/{username}")
|
||||
public ApiResponse<UserProfile> getByUsername(@PathVariable String username) {
|
||||
return ApiResponse.success(userService.getByUsername(username));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.patbond.patbond.user.service;
|
||||
|
||||
import com.patbond.patbond.common.user.CreateUserRequest;
|
||||
import com.patbond.patbond.common.user.UserProfile;
|
||||
import com.patbond.patbond.common.user.VerifyPasswordRequest;
|
||||
import com.patbond.patbond.common.user.VerifyPasswordResponse;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
@Service
|
||||
public class UserService {
|
||||
|
||||
private final AtomicLong idGenerator = new AtomicLong(1);
|
||||
private final Map<Long, UserRecord> usersById = new ConcurrentHashMap<>();
|
||||
private final Map<String, UserRecord> usersByUsername = new ConcurrentHashMap<>();
|
||||
private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||
|
||||
public synchronized UserProfile createUser(CreateUserRequest request) {
|
||||
String username = request.getUsername().trim();
|
||||
if (usersByUsername.containsKey(username)) {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "用户名已存在");
|
||||
}
|
||||
|
||||
UserRecord user = new UserRecord(
|
||||
idGenerator.getAndIncrement(),
|
||||
username,
|
||||
passwordEncoder.encode(request.getPassword()),
|
||||
normalizeBlank(request.getNickname()),
|
||||
normalizeBlank(request.getPhone()),
|
||||
LocalDateTime.now()
|
||||
);
|
||||
usersById.put(user.getId(), user);
|
||||
usersByUsername.put(user.getUsername(), user);
|
||||
return toProfile(user);
|
||||
}
|
||||
|
||||
public VerifyPasswordResponse verifyPassword(VerifyPasswordRequest request) {
|
||||
UserRecord user = usersByUsername.get(request.getUsername().trim());
|
||||
if (user == null || !passwordEncoder.matches(request.getPassword(), user.getPasswordHash())) {
|
||||
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "用户名或密码错误");
|
||||
}
|
||||
return new VerifyPasswordResponse(user.getId(), user.getUsername(), user.getNickname());
|
||||
}
|
||||
|
||||
public UserProfile getById(Long id) {
|
||||
UserRecord user = usersById.get(id);
|
||||
if (user == null) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "用户不存在");
|
||||
}
|
||||
return toProfile(user);
|
||||
}
|
||||
|
||||
public UserProfile getByUsername(String username) {
|
||||
UserRecord user = usersByUsername.get(username.trim());
|
||||
if (user == null) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "用户不存在");
|
||||
}
|
||||
return toProfile(user);
|
||||
}
|
||||
|
||||
private UserProfile toProfile(UserRecord user) {
|
||||
return new UserProfile(user.getId(), user.getUsername(), user.getNickname(), user.getPhone(), user.getCreatedAt());
|
||||
}
|
||||
|
||||
private String normalizeBlank(String value) {
|
||||
return value == null || value.trim().isEmpty() ? null : value.trim();
|
||||
}
|
||||
|
||||
private static class UserRecord {
|
||||
|
||||
private final Long id;
|
||||
private final String username;
|
||||
private final String passwordHash;
|
||||
private final String nickname;
|
||||
private final String phone;
|
||||
private final LocalDateTime createdAt;
|
||||
|
||||
private UserRecord(Long id, String username, String passwordHash, String nickname, String phone,
|
||||
LocalDateTime createdAt) {
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
this.passwordHash = passwordHash;
|
||||
this.nickname = nickname;
|
||||
this.phone = phone;
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
private Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
private String getPasswordHash() {
|
||||
return passwordHash;
|
||||
}
|
||||
|
||||
private String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
private String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
private LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
server:
|
||||
port: 8082
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: patbond-user
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: ${NACOS_SERVER_ADDR:127.0.0.1:8848}
|
||||
config:
|
||||
server-addr: ${NACOS_SERVER_ADDR:127.0.0.1:8848}
|
||||
Reference in New Issue
Block a user