feat:增加密码管理接口

This commit is contained in:
2025-06-12 14:02:17 +08:00
parent 7ca52c0537
commit d119e7aee8
30 changed files with 335 additions and 32 deletions

View File

@@ -0,0 +1,55 @@
package com.cxx.home.controller;
import com.cxx.common.ReadView;
import com.cxx.common.WriteView;
import com.cxx.home.dto.password.PasswordDto;
import com.cxx.home.service.PasswordService;
import com.cxx.home.vo.PasswordQueryVo;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/password")
@Tag(name = "密码管理")
public class PasswordController {
@Resource
private PasswordService passwordService;
@Operation(summary = "查询密码记录")
@GetMapping("")
public @JsonView(ReadView.class) List<PasswordDto> queryPassword(PasswordQueryVo query) {
return passwordService.query(query);
}
@Operation(summary = "新增密码记录")
@PostMapping("")
public Boolean addPassword(@RequestBody @JsonView(WriteView.class) @Validated PasswordDto passwordDto) {
return passwordService.add(passwordDto);
}
@Operation(summary = "更新密码记录")
@PutMapping("/{id}")
public Boolean updatePassword(@PathVariable("id") long id,
@RequestBody @JsonView(WriteView.class) PasswordDto passwordDto) {
return passwordService.update(id, passwordDto);
}
@Operation(summary = "删除密码记录")
@DeleteMapping("/{id}")
public Boolean deletePassword(@PathVariable("id") long id) {
return passwordService.delete(id);
}
@Operation(summary = "查询密码记录类别")
@GetMapping("/category")
public List<String> queryPasswordCategory() {
return passwordService.queryCategory();
}
}

View File

@@ -1,8 +1,8 @@
package com.cxx.home.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.cxx.common.dto.SessionDto;
import com.cxx.home.service.SessionService;
import com.cxx.common.dto.user.SessionDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;

View File

@@ -0,0 +1,33 @@
package com.cxx.home.controller;
import com.cxx.common.ReadView;
import com.cxx.common.WriteView;
import com.cxx.common.dto.UserDto;
import com.cxx.home.service.UserService;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user")
@Tag(name = "用户管理")
public class UserController {
@Resource
private UserService userService;
@Operation(summary = "查询用户")
@GetMapping("/{id}")
public @JsonView(ReadView.class) UserDto queryUser(@PathVariable("id") Long id) {
return userService.queryUser(id);
}
@Operation(summary = "更新用户")
@PutMapping("/{id}")
public Boolean updateUser(@PathVariable("id") Long id,
@JsonView(WriteView.class) @Validated @RequestBody UserDto userDto) {
return userService.updateUser(id, userDto);
}
}

View File

@@ -0,0 +1,15 @@
package com.cxx.home.dao;
import com.cxx.home.dto.password.PasswordDto;
import com.cxx.home.vo.PasswordQueryVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface PasswordDao {
List<PasswordDto> query(@Param("query") PasswordQueryVo query);
List<String> queryCategory();
}

View File

@@ -0,0 +1,39 @@
package com.cxx.home.dto.password;
import com.cxx.common.PlainView;
import com.cxx.common.ReadView;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@JsonView(PlainView.class)
public class PasswordDto
{
@Schema(description = "id")
@JsonView(ReadView.class)
private Long id;
@Schema(description = "标题")
private String title;
@Schema(description = "网站")
private String website;
@Schema(description = "用户名")
private String username;
@Schema(description = "密码")
private String password;
@Schema(description = "类别")
private String category;
@Schema(description = "所属人")
private String owner;
@Schema(description = "备注")
private String remark;
}

View File

@@ -0,0 +1,36 @@
package com.cxx.home.dto.user;
import com.cxx.common.PlainView;
import com.cxx.common.ReadView;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter
@Setter
@JsonView(PlainView.class)
public class UserSummaryDto {
@Schema(description = "id")
@JsonView(ReadView.class)
private Long id;
@Schema(description = "id")
@JsonView(ReadView.class)
private String accountName;
@Schema(description = "用户名称")
@NotBlank(message = "用户名称不能为空")
private String username;
@Schema(description = "账户状态")
private Integer state;
@Schema(description = "创建日期")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private LocalDateTime date;
}

View File

@@ -0,0 +1,33 @@
package com.cxx.home.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.cxx.framework.data.AbstractEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("password")
public class Password extends AbstractEntity {
@TableField(value = "title")
private String title;
@TableField("website")
private String website;
@TableField("username")
private String username;
@TableField("password")
private String password;
@TableField("category")
private String category;
@TableField("owner")
private String owner;
@TableField("remark")
private String remark;
}

View File

@@ -0,0 +1,10 @@
package com.cxx.home.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cxx.home.entity.Password;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface PasswordMapper extends BaseMapper<Password> {
}

View File

@@ -0,0 +1,18 @@
package com.cxx.home.service;
import com.cxx.home.dto.password.PasswordDto;
import com.cxx.home.vo.PasswordQueryVo;
import java.util.List;
public interface PasswordService {
Boolean add(PasswordDto passwordDto);
Boolean update(Long id, PasswordDto passwordDto);
Boolean delete(Long id);
List<PasswordDto> query(PasswordQueryVo query);
List<String> queryCategory();
}

View File

@@ -1,6 +1,6 @@
package com.cxx.home.service;
import com.cxx.common.dto.user.SessionDto;
import com.cxx.common.dto.SessionDto;
public interface SessionService {
SessionDto create(String name, String password);

View File

@@ -0,0 +1,10 @@
package com.cxx.home.service;
import com.cxx.common.dto.UserDto;
public interface UserService {
UserDto queryUser(Long id);
Boolean updateUser(Long id, UserDto userDto);
}

View File

@@ -0,0 +1,78 @@
package com.cxx.home.service.impl;
import cn.hutool.crypto.SecureUtil;
import com.cxx.framework.web.CustomException;
import com.cxx.home.dao.PasswordDao;
import com.cxx.home.dto.password.PasswordDto;
import com.cxx.home.entity.Password;
import com.cxx.home.mapper.PasswordMapper;
import com.cxx.home.service.PasswordService;
import com.cxx.home.vo.PasswordQueryVo;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class PasswordServiceImpl implements PasswordService {
@Resource
private PasswordDao passwordDao;
@Resource
private PasswordMapper passwordMapper;
private static final String SECRET_KEY = "MySuperSecretKey";
@Override
public Boolean add(PasswordDto passwordDto) {
Password password = new Password();
BeanUtils.copyProperties(passwordDto, password);
password.setPassword(encryptPassword(passwordDto.getPassword()));
return passwordMapper.insert(password) == 1;
}
@Override
public Boolean update(Long id, PasswordDto passwordDto) {
if (passwordMapper.selectById(id) == null) {
throw new CustomException("该密码记录不存在");
}
Password password = new Password();
BeanUtils.copyProperties(passwordDto, password);
password.setId(id);
password.setPassword(encryptPassword(passwordDto.getPassword()));
return passwordMapper.updateById(password) == 1;
}
@Override
public Boolean delete(Long id) {
if (passwordMapper.selectById(id) == null) {
throw new CustomException("该密码记录不存在");
}
return passwordMapper.deleteById(id) == 1;
}
@Override
public List<PasswordDto> query(PasswordQueryVo query) {
List<PasswordDto> passwordList = passwordDao.query(query);
passwordList.forEach(item -> item.setPassword(decryptStr(item.getPassword())));
return passwordList;
}
@Override
public List<String > queryCategory() {
return passwordDao.queryCategory();
}
private String encryptPassword(String password) {
return SecureUtil.aes(SECRET_KEY.getBytes()).encryptBase64(password);
}
private String decryptStr(String password) {
return SecureUtil.aes(SECRET_KEY.getBytes()).decryptStr(password);
}
}

View File

@@ -5,9 +5,8 @@ import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cxx.common.dto.user.SessionDto;
import com.cxx.common.dto.user.UserDto;
import com.cxx.common.dto.SessionDto;
import com.cxx.common.dto.UserDto;
import com.cxx.common.entity.Account;
import com.cxx.common.entity.User;
import com.cxx.common.mapper.AccountMapper;

View File

@@ -0,0 +1,56 @@
package com.cxx.home.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cxx.common.dto.UserDto;
import com.cxx.common.entity.Account;
import com.cxx.common.entity.User;
import com.cxx.common.mapper.AccountMapper;
import com.cxx.common.mapper.UserMapper;
import com.cxx.framework.web.CustomException;
import com.cxx.home.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private AccountMapper accountMapper;
@Override
public UserDto queryUser(Long id) {
User user = userMapper.selectById(id);
if (user == null) {
throw new CustomException("未查询到该用户");
}
UserDto userDto = new UserDto();
BeanUtils.copyProperties(user, userDto);
LambdaQueryWrapper<Account> queryWrapper = new LambdaQueryWrapper<>();
userDto.setAccountName(accountMapper.selectOne(queryWrapper.eq(Account::getUserId, id)).getAccountName());
return userDto;
}
@Override
public Boolean updateUser(Long id, UserDto userDto) {
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
if (!userMapper.exists(queryWrapper.eq(User::getId, id))) {
throw new CustomException("该用户不存在");
}
queryWrapper.clear();
if (userMapper.exists(queryWrapper.eq(User::getUsername, userDto.getUsername()).ne(User::getId, id))) {
throw new CustomException("该用户已经存在");
}
User user = new User();
BeanUtils.copyProperties(userDto, user);
user.setId(id);
return userMapper.updateById(user) == 1;
}
}

View File

@@ -0,0 +1,16 @@
package com.cxx.home.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class PasswordQueryVo {
@Schema(description = "类别")
private String category;
@Schema(description = "所属人")
private String owner;
}

View File

@@ -6,7 +6,7 @@ spring:
name: @project.artifactId@
version: @project.version@
profiles:
active: dev
active: prod
mail:
host: smtp.163.com
port: 465

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cxx.home.dao.PasswordDao">
<select id="query" resultType="com.cxx.home.dto.password.PasswordDto">
SELECT
id AS id,
title AS title,
website AS website,
username AS username,
password AS password,
category AS category,
owner AS owner,
remark AS remark
FROM
password
<where>
<if test="query.category != null and query.category != ''">
category = #{query.category}
</if>
<if test="query.owner != null and query.owner != ''">
AND owner = #{query.owner}
</if>
</where>
</select>
<select id="queryCategory" resultType="string">
SELECT DISTINCT category
FROM password
WHERE category IS NOT NULL AND category != '';
</select>
</mapper>