Compare commits

...

6 Commits

Author SHA1 Message Date
DB
b01aa886c5 调整市场模块 2024-04-19 10:34:00 +08:00
DB
41bdad5ab4 修改品管controller 2024-04-18 17:23:07 +08:00
DB
7b38a28e0c 调整oam配置;调整日志打印 2024-04-18 11:13:12 +08:00
DB
5bbca4104c 调整支付包;调整系统包 2024-04-18 09:41:19 +08:00
DB
45385c0cdd 移除common模块;调整Api,ClockIn,Core,Generator模块 2024-04-17 11:21:41 +08:00
DB
ed9162bf9e 升级Springboot3;升级Java17; 2024-04-16 18:31:46 +08:00
396 changed files with 3009 additions and 8754 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Union</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
<relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>Cpop-Api</artifactId>

View File

@ -1,7 +1,6 @@
package com.cpop.api.cloudDb.core.dto;
import com.google.gson.annotations.SerializedName;
import io.swagger.models.auth.In;
import lombok.Data;
import java.util.List;

View File

@ -3,7 +3,6 @@ package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudBrandDto;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.exception.UtilException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

View File

@ -4,7 +4,7 @@ import com.alibaba.fastjson.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudClassCardDto;
import com.cpop.api.cloudDb.core.dto.CloudClassCardRecordDto;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.entity.ExtendPage;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.base.exception.UtilException;

View File

@ -5,7 +5,7 @@ import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudClassDto;
import com.cpop.api.cloudDb.core.dto.CloudClassStudentDto;
import com.cpop.api.cloudDb.core.dto.CloudCourseDto;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.exception.UtilException;
import com.mybatisflex.core.paginate.Page;
import org.springframework.beans.factory.annotation.Autowired;

View File

@ -3,10 +3,8 @@ package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudCourseDto;
import com.cpop.api.cloudDb.core.dto.CloudCourseStudentDto;
import com.cpop.api.cloudDb.core.dto.CloudCourseStudentListDto;
import com.cpop.api.cloudDb.core.dto.CloudCustomerDto;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.exception.UtilException;
import com.mybatisflex.core.paginate.Page;
import lombok.extern.slf4j.Slf4j;

View File

@ -4,7 +4,7 @@ import com.alibaba.fastjson.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudCustomerDto;
import com.cpop.api.cloudDb.core.dto.CloudStudentDto;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.exception.UtilException;
import com.mybatisflex.core.paginate.Page;
import lombok.extern.slf4j.Slf4j;

View File

@ -3,7 +3,7 @@ package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudOrderDto;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.entity.ExtendPage;
import com.cpop.core.base.exception.UtilException;
import com.mybatisflex.core.paginate.Page;

View File

@ -2,9 +2,8 @@ package com.cpop.api.cloudDb.handler;
import com.alibaba.fastjson.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudClassDto;
import com.cpop.api.cloudDb.core.dto.CloudStaffDto;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.exception.UtilException;
import com.mybatisflex.core.paginate.Page;
import org.springframework.beans.factory.annotation.Autowired;

View File

@ -4,7 +4,7 @@ import com.alibaba.fastjson.JSONObject;
import com.cpop.api.cloudDb.core.constant.CloudDbUrl;
import com.cpop.api.cloudDb.core.dto.CloudStoreActiveDto;
import com.cpop.api.cloudDb.core.dto.CloudStoreDto;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.base.exception.UtilException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

View File

@ -1,14 +1,9 @@
package com.cpop.api.tencent.location.handler;
import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSONObject;
import com.cpop.api.tencent.location.core.constant.TencentApiUrl;
import com.cpop.common.utils.http.HttpUtils;
import com.cpop.core.base.exception.UtilException;
import com.cpop.core.utils.SpringUtils;
import okhttp3.Response;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;

View File

@ -3,7 +3,7 @@ package com.cpop.api.tencent.wxWork.handler;
import com.alibaba.fastjson.JSONObject;
import com.cpop.api.tencent.wxWork.core.config.WxWorkApiConfig;
import com.cpop.api.tencent.wxWork.webHook.WebHookSendTextRequest;
import com.cpop.common.utils.http.HttpUtils;
import com.cpop.core.utils.http.HttpUtils;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Union</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
</parent>
<artifactId>Cpop-ClockIn-Demo</artifactId>

View File

@ -1,7 +1,7 @@
package com.cpop.clockin.business.bo;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
@ -10,7 +10,7 @@ import lombok.Data;
* @Version: 1.0
*/
@Data
@ApiModel(value = "打卡记录VO")
@Schema(description = "打卡记录VO")
public class ClockInRecordBo {
@ExcelProperty(value = "姓名")
private String staffName;

View File

@ -1,7 +1,10 @@
package com.cpop.clockin.business.controller;
import com.cpop.core.base.R;
import com.cpop.core.base.entity.R;
import com.mybatisflex.core.paginate.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@ -13,9 +16,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import com.cpop.clockin.business.entity.Classes;
import com.cpop.clockin.business.service.ClassesService;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.util.List;
@ -26,7 +26,7 @@ import java.util.List;
* @since 2024-01-23
*/
@RestController
@Api(tags = "打卡班次表接口")
@Tag(name = "打卡班次表接口")
@RequestMapping("/backstage/classes")
public class ClassesController {
@ -40,8 +40,8 @@ public class ClassesController {
* @return {@code true} 添加成功{@code false} 添加失败
*/
@PostMapping("/save")
@ApiOperation("保存打卡班次表")
public R<Void> save(@RequestBody @ApiParam("打卡班次表") Classes classes) {
@Operation(summary = "保存打卡班次表")
public R<Void> save(@RequestBody @Parameter(description = "打卡班次表") Classes classes) {
classesService.save(classes);
return R.ok();
}
@ -53,8 +53,8 @@ public class ClassesController {
* @return {@code true} 删除成功{@code false} 删除失败
*/
@DeleteMapping("/remove/{id}")
@ApiOperation("根据主键删除打卡班次表")
public R<Void> remove(@PathVariable @ApiParam("打卡班次表主键") Serializable id) {
@Operation(summary = "根据主键删除打卡班次表")
public R<Void> remove(@PathVariable @Parameter(description = "打卡班次表主键") Serializable id) {
classesService.removeById(id);
return R.ok();
}
@ -66,8 +66,8 @@ public class ClassesController {
* @return {@code true} 更新成功{@code false} 更新失败
*/
@PutMapping("/update")
@ApiOperation("根据主键更新打卡班次表")
public R<Void> update(@RequestBody @ApiParam("打卡班次表主键") Classes classes) {
@Operation(summary = "根据主键更新打卡班次表")
public R<Void> update(@RequestBody @Parameter(description = "打卡班次表主键") Classes classes) {
classesService.updateById(classes);
return R.ok();
}
@ -78,7 +78,7 @@ public class ClassesController {
* @return 所有数据
*/
@GetMapping("/list")
@ApiOperation("查询所有打卡班次表")
@Operation(summary = "查询所有打卡班次表")
public R<List<Classes>> list() {
return R.ok(classesService.list());
}
@ -90,8 +90,8 @@ public class ClassesController {
* @return 打卡班次表详情
*/
@GetMapping("/getInfo/{id}")
@ApiOperation("根据主键获取打卡班次表")
public R<Classes> getInfo(@PathVariable @ApiParam("打卡班次表主键") Serializable id) {
@Operation(summary = "根据主键获取打卡班次表")
public R<Classes> getInfo(@PathVariable @Parameter(description = "打卡班次表主键") Serializable id) {
return R.ok(classesService.getById(id));
}
@ -102,8 +102,8 @@ public class ClassesController {
* @return 分页对象
*/
@GetMapping("/page")
@ApiOperation("分页查询打卡班次表")
public R<Page<Classes>> page(@ApiParam("分页信息") Page<Classes> page) {
@Operation(summary = "分页查询打卡班次表")
public R<Page<Classes>> page(@Parameter(description = "分页信息") Page<Classes> page) {
return R.ok(classesService.page(page));
}

View File

@ -4,16 +4,16 @@ import com.alibaba.excel.EasyExcel;
import com.cpop.clockin.business.bo.EmployeeAttendanceBo;
import com.cpop.clockin.business.service.ClockInRecordService;
import com.cpop.clockin.framework.constant.ClockInConstant;
import com.cpop.core.base.R;
import com.cpop.core.base.entity.R;
import com.cpop.core.service.RedisService;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.ParseException;
@ -27,7 +27,7 @@ import java.util.List;
* @Version: 1.0
*/
@RestController
@Api(tags = "打卡记录接口")
@Tag(name = "打卡记录接口")
@RequestMapping("/backstage/clockInRecord")
public class ClockInRecordController {
@Autowired
@ -35,7 +35,7 @@ public class ClockInRecordController {
@Autowired
private RedisService redisService;
@PostMapping("/upload")
@ApiOperation("上传钉钉Excel表")
@Operation(summary = "上传钉钉Excel表")
public R<String> uploadRecord(@RequestParam("file") MultipartFile file) throws IOException, ParseException {
/* List<ClockInRecordBo> clockInRecordBoList = ;
// 将对象数据返回给前端*/
@ -43,7 +43,7 @@ public class ClockInRecordController {
}
@GetMapping("/output")
@ApiOperation("导出表格")
@Operation(summary = "导出表格")
public void outPut(HttpServletResponse response) throws IOException {
String manTimeJson = redisService.getCacheObject(ClockInConstant.MAN_TIME_JSON);
/*byte[] bytes = manTimeJson.getBytes();

View File

@ -3,14 +3,14 @@ package com.cpop.clockin.business.controller;
import com.cpop.clockin.business.dto.StaffClassesDto;
import com.cpop.clockin.business.service.StaffClassesService;
import com.cpop.clockin.business.vo.StaffClassesVo;
import com.cpop.core.base.R;
import com.cpop.core.base.entity.R;
import com.mybatisflex.core.paginate.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import com.cpop.clockin.business.entity.StaffClasses;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.Serializable;
import java.util.List;
@ -21,7 +21,7 @@ import java.util.List;
* @since 2024-01-23
*/
@RestController
@Api(tags = "员工-班次关联表接口")
@Tag(name = "员工-班次关联表接口")
@RequestMapping("/backstage/staffClasses")
public class StaffClassesController {
@ -34,11 +34,11 @@ public class StaffClassesController {
* @author: Yxz
* @date: 2024/1/24 20:54
* @param: [staffClassesDto]
* @return: com.cpop.core.base.R<java.lang.Void>
* @return: com.cpop.core.base.entity.R<java.lang.Void>
**/
@PostMapping("/save")
@ApiOperation("保存员工-班次关联表")
public R<Void> save(@RequestBody @ApiParam("员工-班次保存Dto") StaffClassesDto staffClassesDto) {
@Operation(summary = "保存员工-班次关联表")
public R<Void> save(@RequestBody @Parameter(description = "员工-班次保存Dto") StaffClassesDto staffClassesDto) {
staffClassesService.saveAll(staffClassesDto);
return R.ok();
}
@ -50,11 +50,11 @@ public class StaffClassesController {
* @author: Yxz
* @date: 2024/1/24 20:54
* @param: [staffClassesDto]
* @return: com.cpop.core.base.R<java.lang.Void>
* @return: com.cpop.core.base.entity.R<java.lang.Void>
**/
@PutMapping("/update")
@ApiOperation("更新员工-班次关联表")
public R<Void> update(@RequestBody @ApiParam("员工-班次修改Dto") StaffClassesDto staffClassesDto) {
@Operation(summary = "更新员工-班次关联表")
public R<Void> update(@RequestBody @Parameter(description = "员工-班次修改Dto") StaffClassesDto staffClassesDto) {
staffClassesService.updateAll(staffClassesDto);
return R.ok();
}
@ -65,7 +65,7 @@ public class StaffClassesController {
* @return 所有数据
*/
@GetMapping("/list")
@ApiOperation("查询员工班次信息")
@Operation(summary = "查询员工班次信息")
public R<List<StaffClassesVo>> list() {
return R.ok(staffClassesService.getStaffClassesVolist());
}
@ -78,8 +78,8 @@ public class StaffClassesController {
* @return 员工-班次关联表详情
*/
@GetMapping("/getInfo/{id}")
@ApiOperation("根据主键获取员工-班次关联表")
public R<StaffClasses> getInfo(@PathVariable @ApiParam("员工-班次关联表主键") Serializable id) {
@Operation(summary = "根据主键获取员工-班次关联表")
public R<StaffClasses> getInfo(@PathVariable @Parameter(description = "员工-班次关联表主键") Serializable id) {
return R.ok(staffClassesService.getById(id));
}
@ -89,11 +89,11 @@ public class StaffClassesController {
* @author: Yxz
* @date: 2024/1/24 20:55
* @param: [staffName]
* @return: com.cpop.core.base.R<com.mybatisflex.core.paginate.Page<com.cpop.clockin.business.vo.StaffClassesVo>>
* @return: com.cpop.core.base.entity.R<com.mybatisflex.core.paginate.Page<com.cpop.clockin.business.vo.StaffClassesVo>>
**/
@GetMapping("/page")
@ApiOperation("分页查询员工-班次信息")
public R<Page<StaffClassesVo>> page( @ApiParam("员工名称") @RequestParam(value = "staffName", required = false)String staffName) {
@Operation(summary = "分页查询员工-班次信息")
public R<Page<StaffClassesVo>> page( @Parameter(description = "员工名称") @RequestParam(value = "staffName", required = false)String staffName) {
return R.ok(staffClassesService.selectPage(staffName));
}

View File

@ -1,7 +1,6 @@
package com.cpop.clockin.business.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
@ -10,10 +9,10 @@ import lombok.Data;
* @Version: 1.0
*/
@Data
@ApiModel(value = "员工班次DTO")
@Schema(description = "员工班次DTO")
public class StaffClassesDto {
@ApiModelProperty(value = "员工id")
@Schema(description = "员工id")
private String staffId;
@ApiModelProperty(value = "班次id数组")
@Schema(description = "班次id数组")
private String[] classId;
}

View File

@ -8,11 +8,8 @@ import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
@ -28,7 +25,6 @@ import lombok.experimental.Accessors;
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ApiModel(value = "打卡班次表对象")
@Table(value = "cp_oam_classes", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false)
public class Classes extends BaseEntity implements Serializable {
@ -38,29 +34,23 @@ public class Classes extends BaseEntity implements Serializable {
/**
* 班次名称
*/
@ApiModelProperty(value = "班次名称")
private String className;
/**
* 开始时间
*/
@ApiModelProperty(value = "开始时间")
@JsonFormat(pattern = "HH:mm:ss",timezone = "GMT+8")
private Date startTime;
/**
* 结束时间
*/
@ApiModelProperty(value = "结束时间")
@JsonFormat(pattern = "HH:mm:ss",timezone = "GMT+8")
private Date endTime;
/**
* 逻辑删除0否1是
*/
@ApiModelProperty(value = "逻辑删除0否1是")
@Column(isLogicDelete = true)
private Integer isDelete;

View File

@ -8,8 +8,6 @@ import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
@ -25,85 +23,68 @@ import lombok.experimental.Accessors;
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ApiModel(value = "部门表对象")
@Table(value = "cp_oam_dept", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false)
public class ClockInDept extends BaseEntity implements Serializable {
/**
* 部门id
*/
@ApiModelProperty(value = "部门id")
@Id
private String id;
/**
* 父部门id
*/
@ApiModelProperty(value = "父部门id")
private String parentId;
/**
* 企微id
*/
@ApiModelProperty(value = "企微id")
private Long wxCpId;
/**
* 企微父id
*/
@ApiModelProperty(value = "企微父id")
private Long wxCpParentId;
/**
* 部门名称
*/
@ApiModelProperty(value = "部门名称")
private String name;
/**
* 排序
*/
@ApiModelProperty(value = "排序")
private Integer orderNo;
/**
* 负责人
*/
@ApiModelProperty(value = "负责人")
private String leader;
/**
* 电话
*/
@ApiModelProperty(value = "电话")
private String phone;
/**
* 邮箱
*/
@ApiModelProperty(value = "邮箱")
private String email;
/**
* 部门状态:1正常,0停用
*/
@ApiModelProperty(value = "部门状态:1正常,0停用")
private Boolean status;
/**
* 备注
*/
@ApiModelProperty(value = "备注")
private String remark;
/**
* 逻辑删除(0否1是)
*/
@ApiModelProperty(value = "逻辑删除(0否1是)")
@Column(isLogicDelete = true)
private Boolean isDelete;

View File

@ -8,8 +8,6 @@ import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
@ -25,61 +23,48 @@ import lombok.experimental.Accessors;
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ApiModel(value = "员工表对象")
@Table(value = "cp_oam_staff", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false)
public class ClockInStaff extends BaseEntity implements Serializable {
/**
* 主键
*/
@ApiModelProperty(value = "主键")
@Id
private String id;
/**
* 姓名
*/
@ApiModelProperty(value = "姓名")
private String name;
/**
* 用户id
*/
@ApiModelProperty(value = "用户id")
private String userId;
/**
* 员工类型(0:技术人员;1:售后人员;2:管理人员)
*/
@ApiModelProperty(value = "员工类型(0:技术人员;1:售后人员;2:管理人员)")
private Integer staffType;
/**
* 角色id
*/
@ApiModelProperty(value = "角色id")
private String roleId;
/**
* 微信用userId
*/
@ApiModelProperty(value = "微信用userId")
private String wxCpUserId;
/**
* 是否是运维账号
*/
@ApiModelProperty(value = "是否是运维账号")
private Boolean isOperation;
/**
* 逻辑删除(0否1是)
*/
@ApiModelProperty(value = "逻辑删除(0否1是)")
@Column(isLogicDelete = true)
private Boolean isDelete;

View File

@ -6,8 +6,6 @@ import com.cpop.core.base.entity.BaseUpdateListener;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
@ -23,20 +21,17 @@ import lombok.experimental.Accessors;
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ApiModel(value = "Oam-员工-用户中间表对象")
@Table(value = "cp_oam_staff_mid_dept", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false)
public class ClockInStaffMidDept extends BaseEntity implements Serializable {
/**
* 员工id
*/
@ApiModelProperty(value = "员工id")
private String staffId;
/**
* 部门id
*/
@ApiModelProperty(value = "部门id")
private String deptId;

View File

@ -7,9 +7,6 @@ import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
@ -25,7 +22,6 @@ import lombok.experimental.Accessors;
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ApiModel(value = "员工-班次关联表对象")
@Table(value = "cp_oam_staff_classes", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false)
public class StaffClasses extends BaseEntity implements Serializable {
@ -35,23 +31,16 @@ public class StaffClasses extends BaseEntity implements Serializable {
/**
* 员工id
*/
@ApiModelProperty(value = "员工id")
private String staffId;
/**
* 班次id
*/
@ApiModelProperty(value = "班次id")
private String classId;
/**
* 逻辑删除0否1是
*/
@ApiModelProperty(value = "逻辑删除0否1是")
@Column(isLogicDelete = true)
private Integer isDelete;

View File

@ -8,13 +8,9 @@ import com.cpop.clockin.business.service.*;
import com.cpop.clockin.business.vo.ClassesVo;
import com.cpop.clockin.business.vo.StaffClassesVo;
import com.cpop.core.base.entity.PageDomain;
import com.cpop.core.utils.SpringUtils;
import com.cpop.core.utils.sql.SqlUtils;
import com.cpop.core.utils.SqlUtils;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.DbChain;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.cpop.clockin.business.mapper.StaffClassesMapper;
import org.springframework.beans.BeanUtils;
@ -25,8 +21,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static com.mybatisflex.core.query.QueryMethods.groupConcat;
/**
* 员工-班次关联表 服务层实现
*

View File

@ -1,7 +1,6 @@
package com.cpop.clockin.business.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
@ -9,15 +8,15 @@ import lombok.Data;
* @Date: 2024/1/23 18:56
* @Version: 1.0
*/
@ApiModel(value = "班次VO")
@Schema(description = "班次VO")
@Data
public class ClassesVo {
@ApiModelProperty(value = "班次Id")
@Schema(description = "班次Id")
private String id;
/**
* 班次名称
*/
@ApiModelProperty(value = "班次名称")
@Schema(description = "班次名称")
private String className;
}

View File

@ -1,8 +1,6 @@
package com.cpop.clockin.business.vo;
import com.mybatisflex.annotation.RelationOneToMany;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@ -12,18 +10,18 @@ import java.util.List;
* @Date: 2024/1/23 17:45
* @Version: 1.0
*/
@ApiModel(value = "员工班次关联VO")
@Schema(description = "员工班次关联VO")
@Data
public class StaffClassesVo {
@ApiModelProperty("员工Id")
@Schema(description = "员工Id")
private String staffId;
@ApiModelProperty("员工名称")
@Schema(description = "员工名称")
private String staffName;
@ApiModelProperty("部门名称")
@Schema(description = "部门名称")
private String deptName;
@ApiModelProperty("考勤班次名称")
@Schema(description = "考勤班次名称")
private String className;
@ApiModelProperty("考勤班次集合")
@Schema(description = "考勤班次集合")
private List<ClassesVo> classesVoList;
}

View File

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Union</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>Cpop-Common</artifactId>
<name>Cpop-Common</name>
<description>公共包</description>
<packaging>jar</packaging>
<dependencies>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</dependency>
<!--https://mvnrepository.com/artifact/commons-io/commons-io-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!-- 时间工具类 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!-- okhttp3 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,653 +0,0 @@
package com.cpop.common.utils;
import com.cpop.common.enums.CycleEnum;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* 时间工具类
*
* @author DB
*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
public static String YYYY = "yyyy";
public static String YYYY_MM = "yyyy-MM";
public static String YYYY_MM_DD = "yyyy-MM-dd";
public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public static String YYYYMMDD = "yyyyMMdd";
public static String TIME = "HH:mm:ss";
/**
* yyyy-MM-dd HH:mm
*/
public final static String DATE_TIME_HOUR_MINUTE = "yyyy-MM-dd HH:mm";
private static final String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
public final static String HOUR = "HH:mm";
/**
* 获取当前Date型日期
*
* @return Date() 当前日期
*/
public static Date getNowDate() {
return new Date();
}
/**
* 获取当前日期, 默认格式为yyyy-MM-dd
*
* @return String
*/
public static String getDate() {
return dateTimeNow(YYYY_MM_DD);
}
public static String getTime() {
return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
}
public static String dateTimeNow() {
return dateTimeNow(YYYYMMDDHHMMSS);
}
public static String dateTimeNow(final String format) {
return parseDateToStr(format, new Date());
}
public static String dateTime(final Date date) {
return parseDateToStr(YYYY_MM_DD, date);
}
public static String parseDateToStr(final String format, final Date date) {
return new SimpleDateFormat(format).format(date);
}
public static Date dateTime(final String format, final String ts) {
try {
return new SimpleDateFormat(format).parse(ts);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
/**
* 日期路径 即年// 如2018/08/08
*/
public static String datePath() {
Date now = new Date();
return DateFormatUtils.format(now, "yyyy/MM/dd");
}
/**
* 日期路径 即年// 如20180808
*/
public static String dateTime() {
Date now = new Date();
return DateFormatUtils.format(now, "yyyyMMdd");
}
/**
* 日期型字符串转化为日期 格式
*/
public static Date parseDate(Object str) {
if (str == null) {
return null;
}
try {
return parseDate(str.toString(), parsePatterns);
} catch (ParseException e) {
return null;
}
}
/**
* 获取服务器启动时间
*/
public static Date getServerStartDate() {
long time = ManagementFactory.getRuntimeMXBean().getStartTime();
return new Date(time);
}
/**
* 计算两个时间差
*/
public static String getDatePoor(Date endDate, Date nowDate) {
long nd = 1000 * 24 * 60 * 60;
long nh = 1000 * 60 * 60;
long nm = 1000 * 60;
// long ns = 1000;
// 获得两个时间的毫秒时间差异
long diff = endDate.getTime() - nowDate.getTime();
// 计算差多少天
long day = diff / nd;
// 计算差多少小时
long hour = diff % nd / nh;
// 计算差多少分钟
long min = diff % nd % nh / nm;
// 计算差多少秒//输出结果
// long sec = diff % nd % nh % nm / ns;
return day + "" + hour + "小时" + min + "分钟";
}
/**
* 对日期的进行加/
*
* @param date 日期
* @param months 月数负数为减
* @return /减几月后的日期
*/
public static Date addDateMonths(Date date, int months) {
DateTime dateTime = new DateTime(date);
return dateTime.plusMonths(months).toDate();
}
/**
* 获取指定时间前一天的时间
*
* @param date
* @return
* @Author: ZJ
*/
public static Date getLasDate(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 1);
return calendar.getTime();
}
/**
* 对日期的进行加/
*
* @param date 日期
* @param days 天数负数为减
* @return /减几天后的日期
*/
public static Date addDateDays(Date date, int days) {
DateTime dateTime = new DateTime(date);
return dateTime.plusDays(days).toDate();
}
/**
* 对日期的小时进行加/
*
* @param date 日期
* @param hours 小时数负数为减
* @return /减几小时后的日期
*/
public static Date addDateHours(Date date, int hours) {
DateTime dateTime = new DateTime(date);
return dateTime.plusHours(hours).toDate();
}
/**
* 判断当前时间是周几
*
* @param date
* @return
*/
public static String getWeek(Date date) {
String format = DateUtils.parseDateToStr("yyyy-MM-dd", date);
DateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");
Date now = null;
try {
now = format1.parse(format);
} catch (ParseException e) {
e.printStackTrace();
}
assert now != null;
Instant instant = now.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
java.time.LocalDate localDate = instant.atZone(zoneId).toLocalDate();
DayOfWeek day = localDate.getDayOfWeek();
String WeekDay = "";
switch (day) {
case MONDAY:
WeekDay = "1";
break;
case FRIDAY:
WeekDay = "5";
break;
case SATURDAY:
WeekDay = "6";
break;
case SUNDAY:
WeekDay = "7";
break;
case THURSDAY:
WeekDay = "4";
break;
case TUESDAY:
WeekDay = "2";
break;
case WEDNESDAY:
WeekDay = "3";
break;
}
return WeekDay;
}
/**
* 获取指定时间前一个月的时间
*
* @param date 指定时间如果传空为当前时间
* @return
* @Author: 李性禄
*/
public static Date getLastMon(Date date) {
Calendar calendar = Calendar.getInstance();
if (date != null) {
calendar.setTime(date);
}
calendar.add(Calendar.MONTH, -1);
return calendar.getTime();
}
/**
* 获取指定时间前一年的时间
*
* @param date 指定时间如果传空为当前时间
* @return
* @Author: 李性禄
*/
public static Date getLastYear(Date date) {
Calendar calendar = Calendar.getInstance();
if (date != null) {
calendar.setTime(date);
}
calendar.add(Calendar.YEAR, -1);
return calendar.getTime();
}
/**
* 传入两个时间比较两个时间相差年
*
* @param startDate
* @param endxDate
* @return
*/
public static List<String> getTimeList(String startDate, String endxDate) {
SimpleDateFormat sdf;
int calendarType;
switch (startDate.length()) {
case 10:
sdf = new SimpleDateFormat("yyyy-MM-dd");
calendarType = Calendar.DATE;
break;
case 7:
sdf = new SimpleDateFormat("yyyy-MM");
calendarType = Calendar.MONTH;
break;
case 4:
sdf = new SimpleDateFormat("yyyy");
calendarType = Calendar.YEAR;
break;
default:
return null;
}
List<String> result = new ArrayList<>();
Calendar min = Calendar.getInstance();
Calendar max = Calendar.getInstance();
try {
min.setTime(sdf.parse(startDate));
min.add(calendarType, 0);
max.setTime(sdf.parse(endxDate));
max.add(calendarType, 1);
} catch (ParseException e) {
e.printStackTrace();
}
Calendar curr = min;
while (curr.before(max)) {
result.add(sdf.format(min.getTime()));
curr.add(calendarType, 1);
}
return result;
}
/**
* 日期转换字符串
*
* @param date
* @param pattern 转换的类型
* @return
*/
public static String format(Date date, String pattern) {
if (date != null) {
SimpleDateFormat df = new SimpleDateFormat(pattern);
return df.format(date);
}
return null;
}
/**
* 根据相差毫秒值查询相差多少天
*
* @param result
* @return
*/
public static long days(long result) {
return result / (1000 * 60 * 60 * 24);
}
/**
* 根据相差毫秒值查询相差多少个钟
*
* @param result
* @return
*/
public static long hour(long result) {
return (result % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
}
/**
* 根据相差毫秒值查询相差多少分钟
*
* @param result
* @return
*/
public static long minutes(long result) {
return (result % (1000 * 60 * 60)) / (1000 * 60);
}
/**
* 字符串转换成日期
*
* @param strDate 日期字符串
* @param pattern 日期的格式DateUtils.DATE_TIME_PATTERN
*/
public static Date stringToDate(String strDate, String pattern) {
if (StringUtils.isBlank(strDate)) {
return null;
}
DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
return fmt.parseLocalDateTime(strDate).toDate();
}
/**
* 根据传入的时间获取当前月份的所有日期
*
* @param date
* @return
*/
public static List<Date> getAllTheDateOfTheMonth(Date date) {
List<Date> list = new ArrayList<Date>();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.DATE, 1);
int month = cal.get(Calendar.MONTH);
while (cal.get(Calendar.MONTH) == month) {
list.add(cal.getTime());
cal.add(Calendar.DAY_OF_YEAR, 1);
}
return list;
}
/**
* 根据传入的时间获取是当月的第几天
*
* @param date
* @return
*/
public static Integer dayOfMonth(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal.get(Calendar.DAY_OF_MONTH);
}
/**
* 根据当前时间yyyyMMdd 格式判断是否是节假日私人api慎用容易服务挂掉
*
* @param date 请求参数
* @return 返回结果 默认返回 0工作1-5 1周末 2节假日
*/
public static String holidays(String date) {
String httpUrl = "http://tool.bitefu.net/jiari/";
BufferedReader reader = null;
String holidays = null;
StringBuffer sbf = new StringBuffer();
httpUrl = httpUrl + "?d=" + date;
try {
URL url = new URL(httpUrl);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("GET");
connection.connect();
InputStream is = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String strRead = null;
while ((strRead = reader.readLine()) != null) {
sbf.append(strRead);
}
reader.close();
holidays = sbf.toString();
} catch (Exception e) {
e.printStackTrace();
}
return holidays;
}
/**
* 获取两个时间之前的日期
*
* @return
*/
public static List<String> getDatesBetweenTwoDatesForApprove(Date startTime, Date endTime) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String date1 = sdf.format(startTime);
String date2 = sdf.format(endTime);
List<String> dateList = new ArrayList<String>();
try {
Date dateOne = sdf.parse(date1);
Date dateTwo = sdf.parse(date2);
Calendar calendar = Calendar.getInstance();
calendar.setTime(dateOne);
dateList.add(sdf.format(dateOne));
while (calendar.getTime().before(dateTwo)) {
calendar.add(Calendar.DAY_OF_MONTH, +1);
dateList.add(sdf.format(calendar.getTime()));
}
} catch (Exception e) {
e.printStackTrace();
}
return dateList;
}
/**
* 计算两个时间是否为同一周期
*
* @param d1 时间1
* @param d2 时间2
* @param type 周期类型
*/
public static Boolean sameCycle(Date d1, Date d2, int type) {
CycleEnum cycle = CycleEnum.getCycle(type);
assert cycle != null;
if (cycle.equals(CycleEnum.YEAR)) {
return isSameYear(d1, d2);
} else if (cycle.equals(CycleEnum.MONTH)) {
return isSameMonth(d1, d2);
} else if (cycle.equals(CycleEnum.WEEK)) {
return isSameWeek(d1, d2);
} else if (cycle.equals(CycleEnum.DAY)) {
return isSameDate(d1, d2);
}
return false;
}
/**
* 同一年
*
* @param date1
* @param date2
*/
public static Boolean isSameYear(Date date1, Date date2) {
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date1);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
}
/**
* 同一月
*
* @param date1
* @param date2
* @return
*/
public static Boolean isSameMonth(Date date1, Date date2) {
if (!isSameYear(date1, date2)) {
return false;
}
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date1);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
return cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);
}
/**
* 同一周
*
* @param date1
* @param date2
* @return
*/
public static Boolean isSameWeek(Date date1, Date date2) {
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
//西方周日为一周的第一天咱得将周一设为一周第一天
cal1.setFirstDayOfWeek(Calendar.MONDAY);
cal1.setTime(date1);
cal2.setTime(date2);
return cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR);
}
/**
* 同一天
*
* @param date1
* @param date2
* @return
*/
public static Boolean isSameDate(Date date1, Date date2) {
if (!isSameMonth(date1, date2)) {
return false;
}
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date1);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
return cal1.get(Calendar.DAY_OF_MONTH) == cal2.get(Calendar.DAY_OF_MONTH);
}
/**
* 查看两个时间之间的日期(包含结束那一天)
*
* @param startTime
* @param endTime
* @return
*/
public static List<String> getDatesBetweenTwoDatesT(Date startTime, Date endTime) {
List<String> days = new ArrayList<>();
Calendar startCal = Calendar.getInstance();
startCal.setTime(startTime);
Calendar endCal = Calendar.getInstance();
endCal.setTime(endTime);
endCal.add(Calendar.DATE, 1);
while (startCal.before(endCal)) {
days.add(DateUtils.format(startCal.getTime(), DateUtils.YYYY_MM_DD));
startCal.add(Calendar.DAY_OF_YEAR, 1);
}
return days;
}
/**
* 获取指定时间内所有时间所有天数转为字符串集合
*
* @param startTime 开始时间
* * @param endTime 结束时间
* *@Author: 李性禄
* @return
*/
public static List<String> getDateList(Date startTime, Date endTime, String format) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
List<String> list = new ArrayList<>();
list.add(simpleDateFormat.format(startTime));
String endDay = simpleDateFormat.format(endTime);
String end = null;
Date date = startTime;
while (!endDay.equals(end)) {
if ("yyyy-MM-dd".equals(format)) {
date = getLasDate(date);
}
if ("yyyy-MM".equals(format)) {
date = getLastMon(date);
}
end = simpleDateFormat.format(date);
list.add(end);
}
return list;
}
public static String setTime(Date date) {
long millis = System.currentTimeMillis();
String endTim = "";
if (date != null) {
long time = date.getTime();
long end = (millis - time) / 1000;
if (end < 60L) {
endTim = end + "秒前";
} else if (end < 3600L) {
endTim = (end / 60) + "分前";
} else if (end < (long) (60 * 60 * 24)) {
endTim = (end / (60 * 60)) + "小时前";
} else if (end < (long) (60 * 60 * 24 * 30)) {
endTim = (end / (60 * 60 * 24)) + "天前";
} else if (end < (long) (60 * 60 * 24 * 30 * 12)) {
endTim = (end / (60 * 60 * 24)) + "月前";
} else {
endTim = (end / (60 * 60 * 24 * 30 * 12)) + "年前";
}
}
return endTim;
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Union</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
<relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>Cpop-Core</artifactId>
@ -14,45 +14,20 @@
<packaging>jar</packaging>
<dependencies>
<!--Cpop公共包-->
<!-- Sa-Token 权限认证在线文档https://sa-token.cc -->
<dependency>
<groupId>com.cpop</groupId>
<artifactId>Cpop-Common</artifactId>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-starter</artifactId>
</dependency>
<!--AOP-->
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId>
</dependency>
<!--Mybatis-flex-->
<!-- 提供Redis连接池 -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
</dependency>
<!--Security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- jwt 相关依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!--Redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
@ -67,54 +42,85 @@
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-redis</artifactId>
</dependency>
<!--easyExcel-->
<!-- Sa-Token 整合 jwt -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
<!--Mysql-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!--HikariCP-->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<!--knife4j-Swagger-->
<!--Mybatis-flex-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
</dependency>
<!-- 自定义验证注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
<!--https://mvnrepository.com/artifact/commons-io/commons-io-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!--easyExcel-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<!-- okhttp3 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<!--quartz-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!-- 腾讯云-->
<!-- Sa-Token 整合 SpringAOP 实现注解鉴权 -->
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-aop</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<!-- 自定义验证注解 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--knife4j-Swagger-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<!--mongo-plus-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<groupId>com.gitee.anwena</groupId>
<artifactId>mongo-plus-boot-starter</artifactId>
</dependency>
</dependencies>

View File

@ -1,4 +1,4 @@
package com.cpop.core.annontation;
package com.cpop.core.anno;
import com.cpop.core.base.enums.OperationLogEnum;

View File

@ -1,4 +1,4 @@
package com.cpop.core.annontation;
package com.cpop.core.anno;
import java.lang.annotation.*;

View File

@ -1,4 +1,4 @@
package com.cpop.core.annontation;
package com.cpop.core.anno;
import java.lang.annotation.*;

View File

@ -1,4 +1,4 @@
package com.cpop.core.annontation;
package com.cpop.core.anno;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

View File

@ -1,15 +1,16 @@
package com.cpop.core.aspect;
import com.cpop.common.constant.HttpStatus;
import com.cpop.common.enums.ErrorCodeEnum;
import com.cpop.core.base.R;
import com.cpop.core.base.entity.LoginUser;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import com.cpop.core.base.entity.R;
import com.cpop.core.base.enums.ErrorCodeEnum;
import com.cpop.core.base.enums.OperationLogEnum;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.base.table.SysOperationLog;
import com.cpop.core.base.table.OperationLog;
import com.cpop.core.constant.HttpStatus;
import com.cpop.core.event.OperationLogEvent;
import com.cpop.core.utils.MessageUtils;
import com.cpop.core.utils.SecurityUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
@ -29,7 +30,7 @@ import org.springframework.stereotype.Component;
@Component
public class OperationLogAspect {
private final SysOperationLog operationLog = new SysOperationLog();
private final OperationLog operationLog = new OperationLog();
private OperationLogEnum operationLogEnum;
@ -42,7 +43,7 @@ public class OperationLogAspect {
/**
* 定义controller切入点拦截规则拦截SysLog注解的方法
*/
@Pointcut("@annotation(com.cpop.core.annontation.OperationLog)")
@Pointcut("@annotation(com.cpop.core.anno.OperationLog)")
public void operationLogAspect() {
}
@ -57,18 +58,16 @@ public class OperationLogAspect {
public void recordLog(JoinPoint joinPoint) {
//设置枚举信息
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
com.cpop.core.annontation.OperationLog annotation = signature.getMethod().getAnnotation(com.cpop.core.annontation.OperationLog.class);
com.cpop.core.anno.OperationLog annotation = signature.getMethod().getAnnotation(com.cpop.core.anno.OperationLog.class);
operationLogEnum = annotation.operationLogEnumType();
try {
LoginUser loginUser = SecurityUtils.getInstance().getLoginUser();
operationLog.setOperationUserName(loginUser.getUsername())
.setOperationUserId(loginUser.getUserId())
.setOperationUserType(loginUser.getUserType())
.setDevIp(loginUser.getIpAddr())
SaSession session = StpUtil.getSession();
operationLog.setOperationUserName(session.getString("username"))
.setOperationUserId(session.getString("userId"))
.setOperationUserType((UserType) session.get("userType"))
.setDevIp(session.getString("loginIp"))
.setCode(operationLogEnum.getCode())
.setInfo(MessageUtils.message(operationLogEnum.getInfo()))
.setCreateUserId(loginUser.getUserId());
operationLog.setUpdateUserId(loginUser.getUserId());
.setInfo(MessageUtils.message(operationLogEnum.getInfo()));
} catch (Exception e) {
throw new ServiceException(ErrorCodeEnum.OPERATION_LOG_EXCEPTION.getInfo(), ErrorCodeEnum.OPERATION_LOG_EXCEPTION.getCode());
}

View File

@ -1,10 +1,10 @@
package com.cpop.core.aspect;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.R;
import com.cpop.core.base.entity.R;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.base.exception.UtilException;
import com.cpop.core.utils.RsaUtils;
import com.cpop.core.utils.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
@ -15,16 +15,7 @@ import org.springframework.util.DigestUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Key;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -50,7 +41,7 @@ public class SignatureCheckAspect {
put("1688842965582499840", new String[]{"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmsFHkB4iIdVSgaz8u8QG66wiZupgSbu2T/ml/kdPm2vemsKgvEqUqp1gR6ulfHcPF8otjVbjiE8q8oR70XfxFIREbomTUmpsOzurLFrAmVhyvu6/tY23/txjQoeeH/tlCy7Lq/TL1AqPKyBcGzsQ4yInpIgRWpXz7fmJCTRw07tyE+4lpXBqiaLdWrkkGG00LnHQAOfcUoXf0TdxFPSfRHiBikfbkmgeVoU66RGlUEXU2esTY2nYGvFn+FqWsNkGEnn2YxIqgbQQ1zNX33+FWBlba1WdQtc8mTJAleaPGXmFnQiEMb55b7xVPjyyCWt6aRwl97KQgtCmfsoPZUWwQQIDAQAB", "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCawUeQHiIh1VKBrPy7xAbrrCJm6mBJu7ZP+aX+R0+ba96awqC8SpSqnWBHq6V8dw8Xyi2NVuOITyryhHvRd/EUhERuiZNSamw7O6ssWsCZWHK+7r+1jbf+3GNCh54f+2ULLsur9MvUCo8rIFwbOxDjIiekiBFalfPt+YkJNHDTu3IT7iWlcGqJot1auSQYbTQucdAA59xShd/RN3EU9J9EeIGKR9uSaB5WhTrpEaVQRdTZ6xNjadga8Wf4Wpaw2QYSefZjEiqBtBDXM1fff4VYGVtrVZ1C1zyZMkCV5o8ZeYWdCIQxvnlvvFU+PLIJa3ppHCX3spCC0KZ+yg9lRbBBAgMBAAECggEAdstPp+25vccHYsvr5icAOQEWF3JrH66csJ+vMJaFIYWYh6xHvsJxhNbyBZJZokWyrExi01CTsRs0mJ3iflVYFqvB7ChnkqhnFMElERNJLW2cB702JKP5TgbXm0aHt30/f2oYppNvtAG3DR/2FGEvAWxCiiZ5S9Q4P8GB1DMROTZBpYQgVlN9vOxqgcy8SsJyruy0xsEP3RIKko9UQ7Y9y/b6TbNOJDx/ZpC9KcOUmI8Or73IMdG1ZucumzHNO3dS2XKL7qeTQ8AWMwwAk2ZsCRx9g05QLiW3+7ZrpmOMwI3wCeJOoxhUQKijCXI3B8Rh1cU++CMk4LdyPOe78PYEEQKBgQDnyOL69Ck6+xe1EJ2HAEDPla5ujCexv6ctYvSernhI6OsMVCWa1D5rCqzC4L0IvRW7/m5lUSWlSzpfIGhSGc+PNyIaYsyYMbaIV5e8LKRp8SxUDrTA4IfYmxoXdYyq2l0PSkBPKMJ2ZyWlRoGGEC432IsiY+GBaznvHwIYFvkYHwKBgQCq7DkJYT6du/bQ2uoZv6hYYIGTY4A9TzjJ0Kp5O00BUz5zNpgBUfb1SmuISHwGyN1hOWFntR0uwfj/BUDvtG0b07k1Xz+4UWXsDqtS6eEnvUR6q/i2yWWGjCMS74t61FZopV6AxHneJV2S6Tt26MFK0VbrCwXaiYg/3tMYgC2rnwKBgF0kfRIby/XHsV8xrhvyHhlNLSt/ZvQm8Cds/KBHvE6QSuRJbFMrt2mMgKBPb6dzVKiXNgXA9j/WWz6e500W0jHbFflEerMuRwvDJ1aXGfr4z7d3sWtQz0ZcDcAfnMeLuJnMXMtytbKfAKHKE4KsPeZzPnYzbQt063MMIutLUA5BAoGBAIduFONxwgOJY8+pJcSxL9qW3RTDymDJ3N1MEUdtzV43b0wq/dZN87f396xMgrl9fqwCo0NhJnZeC8VFjGZiN/HMmPvJNNv+4xtfpDBWUKkENrZcfP2YJnGtqDzgwUvZ432XSoINK+LxCGvXkd5uHnoB1TT3zvOR9ftluy22onlRAoGBAKkIZmwW/2H/86ILrCDyARK4obULB4op8IyrunZ+lH14DksxbL7fmTsSbLyRX7oD/QvGJIuc0EDkgONztsAn5vrETv8Z6RqyKdoZZI3sAQWIBc0om6nH2zqJDIs+mep96DOg/jJAcgiVhyIoFP91IvHY7pvKwy5MTttdZLvvS2XB"});
}};
@Pointcut("@annotation(com.cpop.core.annontation.SignatureCheck)")
@Pointcut("@annotation(com.cpop.core.anno.SignatureCheck)")
public void signatureCheck() {}
/**

View File

@ -1,10 +1,10 @@
package com.cpop.core.aspect;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.R;
import com.cpop.core.base.entity.R;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.base.exception.UtilException;
import com.cpop.core.utils.RsaUtils;
import com.cpop.core.utils.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
@ -15,19 +15,11 @@ import org.springframework.util.DigestUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.crypto.Cipher;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
@ -53,7 +45,7 @@ public class SimpleSignatureCheckAspect {
put("1688842965582499840", new String[]{"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmsFHkB4iIdVSgaz8u8QG66wiZupgSbu2T/ml/kdPm2vemsKgvEqUqp1gR6ulfHcPF8otjVbjiE8q8oR70XfxFIREbomTUmpsOzurLFrAmVhyvu6/tY23/txjQoeeH/tlCy7Lq/TL1AqPKyBcGzsQ4yInpIgRWpXz7fmJCTRw07tyE+4lpXBqiaLdWrkkGG00LnHQAOfcUoXf0TdxFPSfRHiBikfbkmgeVoU66RGlUEXU2esTY2nYGvFn+FqWsNkGEnn2YxIqgbQQ1zNX33+FWBlba1WdQtc8mTJAleaPGXmFnQiEMb55b7xVPjyyCWt6aRwl97KQgtCmfsoPZUWwQQIDAQAB", "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCawUeQHiIh1VKBrPy7xAbrrCJm6mBJu7ZP+aX+R0+ba96awqC8SpSqnWBHq6V8dw8Xyi2NVuOITyryhHvRd/EUhERuiZNSamw7O6ssWsCZWHK+7r+1jbf+3GNCh54f+2ULLsur9MvUCo8rIFwbOxDjIiekiBFalfPt+YkJNHDTu3IT7iWlcGqJot1auSQYbTQucdAA59xShd/RN3EU9J9EeIGKR9uSaB5WhTrpEaVQRdTZ6xNjadga8Wf4Wpaw2QYSefZjEiqBtBDXM1fff4VYGVtrVZ1C1zyZMkCV5o8ZeYWdCIQxvnlvvFU+PLIJa3ppHCX3spCC0KZ+yg9lRbBBAgMBAAECggEAdstPp+25vccHYsvr5icAOQEWF3JrH66csJ+vMJaFIYWYh6xHvsJxhNbyBZJZokWyrExi01CTsRs0mJ3iflVYFqvB7ChnkqhnFMElERNJLW2cB702JKP5TgbXm0aHt30/f2oYppNvtAG3DR/2FGEvAWxCiiZ5S9Q4P8GB1DMROTZBpYQgVlN9vOxqgcy8SsJyruy0xsEP3RIKko9UQ7Y9y/b6TbNOJDx/ZpC9KcOUmI8Or73IMdG1ZucumzHNO3dS2XKL7qeTQ8AWMwwAk2ZsCRx9g05QLiW3+7ZrpmOMwI3wCeJOoxhUQKijCXI3B8Rh1cU++CMk4LdyPOe78PYEEQKBgQDnyOL69Ck6+xe1EJ2HAEDPla5ujCexv6ctYvSernhI6OsMVCWa1D5rCqzC4L0IvRW7/m5lUSWlSzpfIGhSGc+PNyIaYsyYMbaIV5e8LKRp8SxUDrTA4IfYmxoXdYyq2l0PSkBPKMJ2ZyWlRoGGEC432IsiY+GBaznvHwIYFvkYHwKBgQCq7DkJYT6du/bQ2uoZv6hYYIGTY4A9TzjJ0Kp5O00BUz5zNpgBUfb1SmuISHwGyN1hOWFntR0uwfj/BUDvtG0b07k1Xz+4UWXsDqtS6eEnvUR6q/i2yWWGjCMS74t61FZopV6AxHneJV2S6Tt26MFK0VbrCwXaiYg/3tMYgC2rnwKBgF0kfRIby/XHsV8xrhvyHhlNLSt/ZvQm8Cds/KBHvE6QSuRJbFMrt2mMgKBPb6dzVKiXNgXA9j/WWz6e500W0jHbFflEerMuRwvDJ1aXGfr4z7d3sWtQz0ZcDcAfnMeLuJnMXMtytbKfAKHKE4KsPeZzPnYzbQt063MMIutLUA5BAoGBAIduFONxwgOJY8+pJcSxL9qW3RTDymDJ3N1MEUdtzV43b0wq/dZN87f396xMgrl9fqwCo0NhJnZeC8VFjGZiN/HMmPvJNNv+4xtfpDBWUKkENrZcfP2YJnGtqDzgwUvZ432XSoINK+LxCGvXkd5uHnoB1TT3zvOR9ftluy22onlRAoGBAKkIZmwW/2H/86ILrCDyARK4obULB4op8IyrunZ+lH14DksxbL7fmTsSbLyRX7oD/QvGJIuc0EDkgONztsAn5vrETv8Z6RqyKdoZZI3sAQWIBc0om6nH2zqJDIs+mep96DOg/jJAcgiVhyIoFP91IvHY7pvKwy5MTttdZLvvS2XB"});
}};
@Pointcut("@annotation(com.cpop.core.annontation.SimpleSignatureCheck)")
@Pointcut("@annotation(com.cpop.core.anno.SimpleSignatureCheck)")
public void simpleSignatureCheck() {}
/**

View File

@ -1,6 +1,8 @@
package com.cpop.core.base.entity;
import com.cpop.core.utils.SecurityUtils;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.StpUtil;
import com.cpop.core.constant.Constants;
import com.mybatisflex.annotation.InsertListener;
import java.time.LocalDateTime;
@ -15,11 +17,16 @@ public class BaseInsertListener implements InsertListener {
@Override
public void onInsert(Object entity) {
BaseEntity baseEntity = (BaseEntity) entity;
LoginUser loginUser = SecurityUtils.getInstance().getLoginUser();
//设置 account 被新增时的一些默认数据
String userId;
try {
userId = StpUtil.getLoginIdDefaultNull() == null ? Constants.SUPER_ADMIN_ID : StpUtil.getLoginIdDefaultNull().toString();
} catch (SaTokenException e) {
userId = Constants.SUPER_ADMIN_ID;
}
baseEntity.setCreateTime(LocalDateTime.now());
baseEntity.setCreateUserId(null == loginUser ? "1" : loginUser.getUserId());
baseEntity.setCreateUserId(userId);
baseEntity.setUpdateTime(LocalDateTime.now());
baseEntity.setUpdateUserId(null == loginUser ? "1" : loginUser.getUserId());
baseEntity.setUpdateUserId(userId);
}
}

View File

@ -1,6 +1,8 @@
package com.cpop.core.base.entity;
import com.cpop.core.utils.SecurityUtils;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.StpUtil;
import com.cpop.core.constant.Constants;
import com.mybatisflex.annotation.UpdateListener;
import java.time.LocalDateTime;
@ -15,9 +17,14 @@ public class BaseUpdateListener implements UpdateListener {
@Override
public void onUpdate(Object entity) {
BaseEntity baseEntity = (BaseEntity) entity;
LoginUser loginUser = SecurityUtils.getInstance().getLoginUser();
String userId;
try {
userId = StpUtil.getLoginIdDefaultNull() == null ? Constants.SUPER_ADMIN_ID : StpUtil.getLoginIdDefaultNull().toString();
} catch (SaTokenException e) {
userId = Constants.SUPER_ADMIN_ID;
}
//设置 account 被更新时的一些默认数据
baseEntity.setUpdateTime(LocalDateTime.now());
baseEntity.setUpdateUserId(null == loginUser ? "1" : loginUser.getUserId());
baseEntity.setUpdateUserId(userId);
}
}

View File

@ -1,8 +1,9 @@
package com.cpop.core.base.entity;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
@ -19,42 +20,52 @@ import java.nio.charset.StandardCharsets;
* @Author: DB
*/
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
private ObjectMapper objectMapper = new ObjectMapper();
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
private final Class<T> clazz;
static {
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
//如果遇到反序列化autoType is not support错误请添加并修改一下包名到bean文件路径
// ParserConfig.getGlobalInstance().addAccept("com.xxxxx.xxx");
}
/**
* 构造器.
*
* @param clazz cls
*/
public FastJson2JsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
/**
* 序列化.
*
* @param t object to serialize. Can be {@literal null}.
* @return es
* @throws SerializationException e
*/
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
return com.alibaba.fastjson2.JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(StandardCharsets.UTF_8);
}
/**
* 反序列化.
*
* @param bytes object binary representation. Can be {@literal null}.
* @return es
* @throws SerializationException e
*/
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
String str = new String(bytes, StandardCharsets.UTF_8);
return JSON.parseObject(str, clazz);
}
public void setObjectMapper(ObjectMapper objectMapper) {
Assert.notNull(objectMapper, "'objectMapper' must not be null");
this.objectMapper = objectMapper;
}
protected JavaType getJavaType(Class<?> clazz) {

View File

@ -1,35 +0,0 @@
package com.cpop.core.base.entity;
import lombok.Data;
import java.io.Serializable;
/**
* @author DB
* @create 2023-04-05 17:53
*/
@Data
public class LoginForm implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 验证码
*/
private String code;
/**
* 单次标识
*/
private String userKey;
}

View File

@ -3,6 +3,7 @@ package com.cpop.core.base.entity;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
import java.util.Set;
@ -15,6 +16,7 @@ import java.util.Set;
@Accessors(chain = true)
public class LoginSuccess implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**

View File

@ -1,156 +0,0 @@
package com.cpop.core.base.entity;
import com.alibaba.fastjson.annotation.JSONField;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.table.SysUser;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Set;
/**
* 登录用户身份权限
*
* @author DB
*/
@Data
@Accessors(chain = true)
public class LoginUser implements UserDetails {
/**
* 用户ID
*/
private String userId;
/**
* 用户名
*/
private String userName;
/**
* 用户唯一标识
*/
private String identification;
/**
* 登录时间
*/
private Long loginTime = System.currentTimeMillis();
/**
* 过期时间
*/
private Long expireTime;
/**
* 登录IP地址
*/
private String ipAddr;
/**
* 登录地点
*/
private String loginLocation;
/**
* 权限列表
*/
private Set<String> permissions;
/**
* 用户信息
*/
private SysUser user;
/**
* 消息
*/
private String msg;
/**
* 登录状态
*/
private Boolean status;
/**
* 用户类型
*/
private UserType userType = UserType.OAM_USER;
public LoginUser() {
}
public LoginUser(SysUser user,String identification, Set<String> permissions) {
this.user = user;
this.identification = identification;
this.permissions = permissions;
}
public LoginUser(String userId, SysUser user, Set<String> permissions) {
this.userId = userId;
this.user = user;
this.permissions = permissions;
}
@JSONField(serialize = false)
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
if (StringUtils.isBlank(this.userName)){
return user.getUserName();
}else {
return this.userName;
}
}
/**
* 账户是否未过期,过期无法验证
*/
@JSONField(serialize = false)
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
* 指定用户是否解锁,锁定的用户无法进行身份验证
*/
@JSONField(serialize = false)
@Override
public boolean isAccountNonLocked() {
return true;
}
/**
* 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
*/
@JSONField(serialize = false)
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/**
* 是否可用 ,禁用的用户不能身份验证
*/
@JSONField(serialize = false)
@Override
public boolean isEnabled() {
return true;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
//根据自定义逻辑来返回用户权限如果用户权限返回空或者和拦截路径对应权限不同验证不通过;自定义权限注解此处设定为null
return null;
}
}

View File

@ -1,115 +0,0 @@
package com.cpop.core.base.entity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
/**
* @author DB
* @since 2023-12-10 9:35
* @version 1.0.0
*
* 负责将InputStream转换MultipartFile,可以少引一个jar包,本来用的是spring-test-4.3.9中的MockMultipartFile,直接提取出来使用
*/
public class MultipartFileDto implements MultipartFile {
private final String name;
private String originalFilename;
private String contentType;
private final byte[] content;
/**
* Create a new MultipartFileDto with the given content.
* @param name the name of the file
* @param content the content of the file
*/
public MultipartFileDto(String name, byte[] content) {
this(name, "", null, content);
}
/**
* Create a new MultipartFileDto with the given content.
* @param name the name of the file
* @param contentStream the content of the file as stream
* @throws IOException if reading from the stream failed
*/
public MultipartFileDto(String name, InputStream contentStream) throws IOException {
this(name, "", null, FileCopyUtils.copyToByteArray(contentStream));
}
/**
* Create a new MultipartFileDto with the given content.
* @param name the name of the file
* @param originalFilename the original filename (as on the client's machine)
* @param contentType the content type (if known)
* @param content the content of the file
*/
public MultipartFileDto(String name, String originalFilename, String contentType, byte[] content) {
this.name = name;
this.originalFilename = (originalFilename != null ? originalFilename : "");
this.contentType = contentType;
this.content = (content != null ? content : new byte[0]);
}
/**
* Create a new MultipartFileDto with the given content.
* @param name the name of the file
* @param originalFilename the original filename (as on the client's machine)
* @param contentType the content type (if known)
* @param contentStream the content of the file as stream
* @throws IOException if reading from the stream failed
*/
public MultipartFileDto(String name, String originalFilename, String contentType, InputStream contentStream)
throws IOException {
this(name, originalFilename, contentType, FileCopyUtils.copyToByteArray(contentStream));
}
@Override
public String getName() {
return this.name;
}
@Override
public String getOriginalFilename() {
return this.originalFilename;
}
@Override
public String getContentType() {
return this.contentType;
}
@Override
public boolean isEmpty() {
return (this.content.length == 0);
}
@Override
public long getSize() {
return this.content.length;
}
@Override
public byte[] getBytes() throws IOException {
return this.content;
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(this.content);
}
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
FileCopyUtils.copy(this.content, dest);
}
}

View File

@ -1,6 +1,7 @@
package com.cpop.core.base.entity;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.utils.StringUtils;
/**
* 分页数据

View File

@ -1,8 +1,11 @@
package com.cpop.core.base.entity;
import lombok.Getter;
/**
* 权限组
*/
@Getter
public class Permission {
/**
@ -10,10 +13,6 @@ public class Permission {
*/
private String permission;
public String getPermission() {
return permission;
}
public void setPermission(String permission) {
this.permission = permission;
}

View File

@ -1,7 +1,9 @@
package com.cpop.core.base;
package com.cpop.core.base.entity;
import com.cpop.common.constant.Constants;
import com.cpop.core.constant.Constants;
import java.io.Serial;
import java.io.Serializable;
/**
@ -11,6 +13,7 @@ import java.io.Serializable;
*/
public class R<T> implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**

View File

@ -1,48 +0,0 @@
package com.cpop.core.base.entity.loginInfo;
import com.cpop.core.base.enums.SourceType;
import com.cpop.core.base.table.SysUser;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @author DB
* @createTime 2023/10/19 13:10
* @description 商城管理员工登陆信息
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class MallStaffLoginInfo extends SysUser {
/**
* 员工id(mallStaffId)
*/
private String id;
/**
* 姓名
*/
private String name;
/**
* 用户id
*/
private String userId;
/**
* 角色id
*/
private String roleId;
/**
* 品牌id
*/
private String brandId;
/**
* 用户来源
*/
private SourceType sourceType;
}

View File

@ -1,58 +0,0 @@
package com.cpop.core.base.entity.loginInfo;
import com.cpop.core.base.enums.SourceType;
import com.cpop.core.base.table.SysUser;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @author DB
* @createTime 2023/10/24 9:16
* @description 小程序登陆用户信息
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class MiniUserLoginInfo extends SysUser {
/**
* 小程序用户id
*/
private String id;
/**
* 小程序openId
*/
private String openId;
/**
* 小程序appid
*/
private String appId;
/**
* 用户id
*/
private String userId;
/**
* 品牌id
*/
private String brandId;
/**
* 昵称
*/
private String nickName;
/**
* 头像
*/
private String avatar;
/**
* 小程序用户来源
*/
private SourceType sourceType;
}

View File

@ -1,47 +0,0 @@
package com.cpop.core.base.entity.loginInfo;
import com.cpop.core.base.table.SysUser;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @author DB
* @createTime 2023/09/10 13:02
* @description 系统员工登陆信息
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class OamStaffLoginInfo extends SysUser {
/**
* 员工id(staffId)
*/
private String id;
/**
* 姓名
*/
private String name;
/**
* 部门id
*/
private String deptId;
/**
* 用户id
*/
private String userId;
/**
* 员工类型(0:技术人员;1:售后人员;2:管理人员)
*/
private Integer staffType;
/**
* 角色id
*/
private String roleId;
}

View File

@ -1,4 +1,4 @@
package com.cpop.common.enums;
package com.cpop.core.base.enums;
/**
* @author DB

View File

@ -1,8 +1,11 @@
package com.cpop.common.enums;
package com.cpop.core.base.enums;
import lombok.Getter;
/**
* @author LOST.yuan
*/
@Getter
public enum ErrorCodeEnum {
/** jwt凭据已过期 */
@ -67,14 +70,6 @@ public enum ErrorCodeEnum {
this.info = info;
}
public Integer getCode() {
return code;
}
public String getInfo() {
return info;
}
public static ErrorCodeEnum codeOf(Integer code) {
for (ErrorCodeEnum value : values()) {
if (value.getCode().equals(code)) {

View File

@ -1,27 +0,0 @@
package com.cpop.core.base.enums;
import lombok.Getter;
@Getter
public enum SourceType {
/**
* 通用
*/
COMMON("Common"),
/**
* 果酱
*/
JAMBOX("Jambox");
private String name;
SourceType(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -1,10 +1,5 @@
package com.cpop.core.base.enums;
import com.cpop.core.strategy.login.LoginStrategy;
import com.cpop.core.strategy.login.MallLoginStrategy;
import com.cpop.core.strategy.login.MiniLoginStrategy;
import com.cpop.core.strategy.login.OamLoginStrategy;
import com.cpop.core.utils.SpringUtils;
import lombok.Getter;
/**
@ -17,15 +12,15 @@ public enum UserType {
/**
* oam系统员工
*/
OAM_USER(0, "oam:loginUser:", SpringUtils.getBean(OamLoginStrategy.class)),
OAM_USER(0, "oam:loginUser:"),
/**
* 小程序用户
*/
MINI_USER(1, "mini:loginUser:", SpringUtils.getBean(MiniLoginStrategy.class)),
MINI_USER(1, "mini:loginUser:"),
/**
* 商城系统员工
*/
MALL_USER(2, "mall:loginUser:",SpringUtils.getBean(MallLoginStrategy.class));
MALL_USER(2, "mall:loginUser:");
/**
* code
@ -37,12 +32,9 @@ public enum UserType {
*/
private final String key;
private final LoginStrategy strategy;
UserType(Integer code, String key, LoginStrategy strategy) {
UserType(Integer code, String key) {
this.code = code;
this.key = key;
this.strategy = strategy;
}
}

View File

@ -1,15 +1,20 @@
package com.cpop.core.base.exception;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.utils.MessageUtils;
import lombok.Getter;
import java.io.Serial;
/**
* 基础异常
*
* @author DB
*/
@Getter
public class BaseException extends RuntimeException {
@Serial
private static final long serialVersionUID = 1L;
/**
@ -67,19 +72,4 @@ public class BaseException extends RuntimeException {
return message;
}
public String getModule() {
return module;
}
public String getCode() {
return code;
}
public Object[] getArgs() {
return args;
}
public String getDefaultMessage() {
return defaultMessage;
}
}

View File

@ -1,26 +0,0 @@
package com.cpop.core.base.exception;
import org.springframework.security.core.AuthenticationException;
/**
* @author: DB
* @Date: 2023/08/24/18:10
* @Description: 自定义认证失败异常
*/
public class CpopAuthenticationException extends AuthenticationException {
private Object params;
public CpopAuthenticationException(String msg) {
super(msg);
}
public CpopAuthenticationException(String msg, Object params) {
super(msg);
this.params = params;
}
public Object getParams() {
return params;
}
}

View File

@ -23,7 +23,7 @@ import java.io.Serializable;
@AllArgsConstructor
@Accessors(chain = true)
@Table(value = "cp_sys_config", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false)
public class SysConfig extends BaseEntity implements Serializable {
public class Config extends BaseEntity implements Serializable {
/**
* 参数键

View File

@ -24,7 +24,7 @@ import java.io.Serializable;
@AllArgsConstructor
@Accessors(chain = true)
@Table(value = "cp_sys_operation_log", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false)
public class SysOperationLog extends BaseEntity implements Serializable {
public class OperationLog extends BaseEntity implements Serializable {
/**
* ID

View File

@ -25,7 +25,7 @@ import java.io.Serializable;
@AllArgsConstructor
@Accessors(chain = true)
@Table(value = "cp_sys_user", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false)
public class SysUser extends BaseEntity implements Serializable {
public class User extends BaseEntity implements Serializable {
/**
* 主键

View File

@ -45,18 +45,16 @@ public class AsyncScheduledTaskConfig {
executor.setWaitForTasksToCompleteOnShutdown(false);
//设置线程池中任务的等待时间如果超过这个时候还没有销毁就强制销毁以确保应用最后能够被关闭而不是阻塞住
executor.setAwaitTerminationSeconds(config.getAwaitTerminationSeconds());
/**
* 拒绝处理策略
* CallerRunsPolicy()交由调用方线程运行比如 main 线程
* AbortPolicy()直接抛出异常
* DiscardPolicy()直接丢弃
* DiscardOldestPolicy()丢弃队列中最老的任务
* 特殊说明
* 1. 这里演示环境拒绝策略咱们采用抛出异常
* 2.真实业务场景会把缓存队列的大小会设置大一些
* 如果提交的任务数量超过最大线程数量或将任务环缓存到本地redismysql中,保证消息不丢失
* 3.如果项目比较大的话异步通知种类很多的话建议采用MQ做异步通知方案
*/
//拒绝处理策略
//CallerRunsPolicy()交由调用方线程运行比如 main 线程
//AbortPolicy()直接抛出异常
//DiscardPolicy()直接丢弃
//DiscardOldestPolicy()丢弃队列中最老的任务
//特殊说明
//1. 这里演示环境拒绝策略咱们采用抛出异常
//2.真实业务场景会把缓存队列的大小会设置大一些
//如果提交的任务数量超过最大线程数量或将任务环缓存到本地redismysql中,保证消息不丢失
//3.如果项目比较大的话异步通知种类很多的话建议采用MQ做异步通知方案
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
//线程初始化
executor.initialize();

View File

@ -0,0 +1,29 @@
package com.cpop.core.config;
import com.cpop.core.service.ConfigService;
import com.cpop.core.strategy.dataSourceSharding.CpopDataSourceShardingStrategy;
import com.cpop.core.utils.SpringUtils;
import com.mybatisflex.core.datasource.DataSourceManager;
import jakarta.annotation.PostConstruct;
import org.springframework.context.annotation.Configuration;
/**
* 核心初始化文件
* @author DB
* @version 1.0.0
* @since 2024-02-05 9:39
*/
@Configuration
public class CoreInitConfig {
/**
* 初始化
*/
@PostConstruct
public void init() {
//设置数据源分片策略
DataSourceManager.setDataSourceShardingStrategy(new CpopDataSourceShardingStrategy());
//初始化系统配置信息
SpringUtils.getBean(ConfigService.class).loadingConfigCache();
}
}

View File

@ -1,5 +1,6 @@
package com.cpop.core.config;
import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ -8,6 +9,7 @@ import org.springframework.stereotype.Component;
*
* @author DB
*/
@Getter
@Component
@ConfigurationProperties(prefix = "cpop")
public class CpopConfig {
@ -29,20 +31,13 @@ public class CpopConfig {
/**
* 验证码类型
*/
@Getter
private static String captchaType;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
@ -55,10 +50,6 @@ public class CpopConfig {
CpopConfig.profile = profile;
}
public static String getCaptchaType() {
return captchaType;
}
public void setCaptchaType(String captchaType) {
CpopConfig.captchaType = captchaType;
}

View File

@ -1,7 +1,8 @@
package com.cpop.core.config;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.filter.XssFilter;
import com.cpop.core.utils.StringUtils;
import jakarta.servlet.DispatcherType;
import lombok.Data;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ -9,7 +10,6 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.DispatcherType;
import java.util.HashMap;
import java.util.Map;
@ -34,11 +34,10 @@ public class FilterConfig {
private String urlPatterns;
/**
* @Description: xss过滤器
* @param
* @return: FilterRegistrationBean
* @Author: DB
* @Date: 2023/4/17 9:17
* xss过滤器
* @return FilterRegistrationBean
* @author DB
* @since 2023/4/17 9:17
**/
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean

View File

@ -1,15 +1,28 @@
package com.cpop.core.config;
import com.cpop.core.base.entity.FastJson2JsonRedisSerializer;
import com.cpop.core.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.util.Arrays;
/**
* redis配置
*
@ -19,9 +32,24 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
@Autowired
private RedisProperties redisProperties;
@Primary
@Bean(name = "redisConnectionFactory")
public RedisConnectionFactory wxOpenRedisConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(redisProperties.getHost(), redisProperties.getPort());
configuration.setDatabase(redisProperties.getDatabase());
if (StringUtils.isNotBlank(redisProperties.getPassword())) {
configuration.setPassword(redisProperties.getPassword());
}
return new JedisConnectionFactory(configuration);
}
@Bean(name = "redisTemplate")
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(@Qualifier("redisConnectionFactory") RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
@ -35,6 +63,28 @@ public class RedisConfig extends CachingConfigurerSupport {
return template;
}
/**
* 缓存管理器
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager
.RedisCacheManagerBuilder
.fromConnectionFactory(redisConnectionFactory);
return builder.build();
}
@Bean
public KeyGenerator wiselyKeyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
Arrays.stream(params).map(Object::toString).forEach(sb::append);
return sb.toString();
};
}
@Bean
public DefaultRedisScript<Long> limitScript() {
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();

View File

@ -1,10 +1,13 @@
package com.cpop.core.config;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.time.Duration;
/**
* @author DB
* @version 1.0.0
@ -14,15 +17,13 @@ import org.springframework.web.client.RestTemplate;
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
// 创建一个 HttpComponentsClientHttpRequestFactory 客户端请求工厂实例
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
// 设置连接超时时间为 5
requestFactory.setConnectTimeout(5000);
restTemplateBuilder.setConnectTimeout(Duration.ofMillis(5000));
// 设置读取超时时间为 10
requestFactory.setReadTimeout(10000);
restTemplateBuilder.setReadTimeout(Duration.ofMillis(10000));
// 使用 HttpComponentsClientHttpRequestFactory 客户端请求工厂实例创建 RestTemplate 实例
return new RestTemplate(requestFactory);
return restTemplateBuilder.build();
}
}

View File

@ -1,215 +0,0 @@
package com.cpop.core.config;
import com.cpop.common.constant.Constants;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.filter.JwtAuthenticationFilter;
import com.cpop.core.filter.RepeatableFilter;
import com.cpop.core.gateway.miniProgram.MiniProgramAuthenticationFilter;
import com.cpop.core.gateway.miniProgram.MiniProgramAuthenticationProvider;
import com.cpop.core.gateway.sys.SysAuthenticationFilter;
import com.cpop.core.gateway.sys.SysAuthenticationProvider;
import com.cpop.core.handler.*;
import com.cpop.core.utils.JwtUtils;
import com.cpop.core.utils.PasswordEncoder;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Arrays;
import java.util.Collections;
/**
* @author DB
* @Description: Security配置中心
* @since 2023-08-05 8:01
*/
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableMethodSecurity
public class SecurityConfig implements WebMvcConfigurer {
@Autowired
private JwtLogoutSuccessHandler jwtLogoutSuccessHandler;
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private JwtAccessDeniedHandler jwtAccessDeniedHandler;
@Autowired
private RepeatableFilter repeatableFilter;
@Autowired
private LoginSuccessHandler loginSuccessHandler;
@Autowired
private LoginFailureHandler loginFailureHandler;
@Autowired
private CpopConfig cpopConfig;
@Autowired
private JwtUtils jwtUtils;
/**
* Security过滤拦截配置
*
* @param http 请求
* @return SecurityFilterChain 认证过滤链
* @throws Exception 异常
*/
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
//登录配置(多登陆模式自定义成功与失败->现已注释)
/*.formLogin(formLogin -> {
formLogin.successHandler(loginSuccessHandler)
.failureHandler(loginFailureHandler);
})*/
//登出配置
.logout(logout -> logout.logoutSuccessHandler(jwtLogoutSuccessHandler))
//禁用session
.sessionManagement(sessionManagement -> {
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
})
//配置拦截规则
.authorizeHttpRequests(authorizeHttpRequests -> {
authorizeHttpRequests.antMatchers(StringUtils.split(jwtUtils.getWhiteList(), ",")).permitAll()
.anyRequest().authenticated();
})
//异常处理器
.exceptionHandling(exceptionHandling -> {
exceptionHandling.authenticationEntryPoint(jwtAuthenticationEntryPoint).accessDeniedHandler(jwtAccessDeniedHandler);
})
//自定义认证管理器
.authenticationManager(authenticationManager())
//流重复使用
.addFilterBefore(repeatableFilter, UsernamePasswordAuthenticationFilter.class)
// 添加 JWT 过滤器JWT 过滤器在退出认证过滤器之前
.addFilterBefore(authFilter(), LogoutFilter.class)
//.addFilterAt(oamLoginFilter(http.getSharedObject(AuthenticationManager.class)), UsernamePasswordAuthenticationFilter.class)
//系统登陆
.addFilterAt(sysAuthenticationFilter(http.getSharedObject(AuthenticationManager.class)), UsernamePasswordAuthenticationFilter.class)
//小程序认证
.addFilterAt(miniProgramAuthenticationFilter(http.getSharedObject(AuthenticationManager.class)), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
/**
* @Description: 小程序登陆认证方式(可自定义其他模式)
* @param authenticationManager 认证管理器
* @return MiniProgramAuthenticationFilter
* @author DB
* @Date: 2023/8/24 0024 10:43
*/
@Bean
public SysAuthenticationFilter sysAuthenticationFilter(AuthenticationManager authenticationManager) {
SysAuthenticationFilter filter = new SysAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager);
filter.setAuthenticationSuccessHandler(loginSuccessHandler);
filter.setAuthenticationFailureHandler(loginFailureHandler);
return filter;
}
@Bean
public SysAuthenticationProvider sysAuthenticationProvider() {
return new SysAuthenticationProvider();
}
/**
* @Description: 小程序登陆认证方式(可自定义其他模式)
* @param authenticationManager 认证管理器
* @return MiniProgramAuthenticationFilter
* @author DB
* @Date: 2023/8/24 0024 10:43
*/
@Bean
public MiniProgramAuthenticationFilter miniProgramAuthenticationFilter(AuthenticationManager authenticationManager) {
MiniProgramAuthenticationFilter filter = new MiniProgramAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager);
filter.setAuthenticationSuccessHandler(loginSuccessHandler);
filter.setAuthenticationFailureHandler(loginFailureHandler);
return filter;
}
@Bean
public MiniProgramAuthenticationProvider miniProgramAuthenticationProvider() {
return new MiniProgramAuthenticationProvider();
}
/**
* 获取AuthenticationManager认证管理器登录时认证使用
* @return AuthenticationManager
*/
@Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(Arrays.asList(sysAuthenticationProvider(), miniProgramAuthenticationProvider()));
}
/**
* 密码明文加密方式配置
* @return PasswordEncoder
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new PasswordEncoder();
}
/**
* jwt 校验过滤器 http 头部 Authorization 字段读取 token 并校验
* @return JwtAuthenticationFilter
*/
@Bean
public JwtAuthenticationFilter authFilter() {
return new JwtAuthenticationFilter();
}
/**
* 配置跨源访问(CORS)
* @return CorsConfigurationSource
*/
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Collections.singletonList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
configuration.applyPermitDefaultValues();
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
/**
* @param registry 资源注册
* @Description: 资源映射
* @Author DB
* @Date: 2023/5/27 13:57
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//本地文件上传路径
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
.addResourceLocations("file:" + cpopConfig.getProfile() + "/");
}
}

View File

@ -1,9 +1,9 @@
package com.cpop.core.config;
import com.cpop.common.utils.ServletUtils;
import com.cpop.core.utils.ServletUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* 服务相关配置

View File

@ -1,4 +1,4 @@
package com.cpop.common.constant;
package com.cpop.core.constant;
/**
* 通用常量信息
@ -51,7 +51,7 @@ public interface Constants {
/**
* 通用失败标识
*/
Integer FAIL = 400;
Integer FAIL = 500;
/**
* 登录成功
@ -141,7 +141,7 @@ public interface Constants {
/**
* 参数管理 cache key
*/
String SYS_CONFIG_KEY = "sys_config:";
String CONFIG_KEY = "config:";
/**
* 字典管理 cache key
@ -172,12 +172,17 @@ public interface Constants {
/**
* 超级管理员
*/
String SUPER_ADMIN = "Cpop";
String SUPER_ADMIN = "Jambox";
/**
* 超级管理员ID
*/
String SUPER_ADMIN_ID = "1";
String SUPER_ADMIN_ID = "100";
/**
* 超级身份id
*/
String SUPER_IDENTITY_AUTH_ID = "100";
/**
* 超级管理员
@ -187,12 +192,12 @@ public interface Constants {
/**
* 所有权限
*/
String ALL_PERMISSION = "*:*:*";
String ALL_PERMISSION = "*";
/**
* 隐藏菜单
*/
String HIDE_MENU = "Menu";
String HIDE_MENU = "System,Menu,Dict";
/**
* 用户类型

View File

@ -1,4 +1,4 @@
package com.cpop.common.constant;
package com.cpop.core.constant;
/**
* 返回状态码
@ -85,4 +85,9 @@ public interface HttpStatus {
* 接口未实现
*/
int NOT_IMPLEMENTED = 501;
/**
* 校区过期
*/
int STORE_EXPIRE = 10000;
}

View File

@ -1,4 +1,4 @@
package com.cpop.common.constant;
package com.cpop.core.constant;
/**
* @author DB

View File

@ -1,163 +0,0 @@
package com.cpop.core.filter;
import com.alibaba.fastjson.JSONObject;
import com.cpop.common.constant.Constants;
import com.cpop.common.utils.StringUtils;
import com.cpop.common.utils.ip.IpUtils;
import com.cpop.core.base.R;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.entity.loginInfo.MiniUserLoginInfo;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.gateway.miniProgram.MiniProgramAuthenticationToken;
import com.cpop.core.gateway.sys.SysAuthenticationToken;
import com.cpop.core.service.CoreService;
import com.cpop.core.service.RedisService;
import com.cpop.core.service.impl.OamStaffDetailsServiceImpl;
import com.cpop.core.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.lang.NonNullApi;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @author: DB
* @date: 2022-09-25 16:34
* @Description: jwt认证过滤器
*/
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private OamStaffDetailsServiceImpl oamStaffDetailsService;
@Autowired
private CoreService coreService;
@Autowired
private RedisService redisService;
@Override
protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response,@NonNull FilterChain chain) throws IOException, ServletException {
String jwt = request.getHeader(jwtUtils.getHeader());
// 这里如果没有jwt继续往后走因为后面还有鉴权管理器等去判断是否拥有身份凭证所以是可以放行的
// 没有jwt相当于匿名访问若有一些接口是需要权限的则不能访问这些接口
if (StringUtils.isEmpty(jwt)) {
chain.doFilter(request, response);
return;
}
Jws<Claims> jws = jwtUtils.getClaimsByToken(jwt);
if (jws == null) {
returnJwtException(response,"token 失效");
return;
}
Claims claim = jws.getBody();
if (claim == null) {
returnJwtException(response,"token 异常");
return;
}
if (jwtUtils.isTokenExpired(claim)) {
returnJwtException(response,"token 已过期");
return;
}
//当前用户类型下唯一
String identification = claim.getSubject();
String username = jws.getHeader().get(Constants.USERNAME).toString();
UserType userType = UserType.valueOf(jws.getHeader().get(Constants.USER_TYPE).toString());
//从缓存中获取
JSONObject jsonObject = redisService.getCacheObject(userType.getKey() + identification);
LoginUser loginUser;
if (null == jsonObject){
loginUser = multipleLoadUser(userType, username);
//存入缓存
redisService.setCacheObject(userType.getKey() + loginUser.getIdentification(), loginUser);
} else {
loginUser = jsonObject.toJavaObject(LoginUser.class);
}
//获取当前请求ip
loginUser.setIpAddr(IpUtils.getIpAddr(request));
multipleAuth(loginUser);
chain.doFilter(request, response);
}
/**
* jwt异常直接返回
* @param response 响应
* @param msg 错误信息
*/
private void returnJwtException(HttpServletResponse response,String msg) throws IOException {
response.setContentType("application/json;charset=UTF-8");
response.setStatus(HttpServletResponse.SC_OK);
ServletOutputStream outputStream = response.getOutputStream();
R<String> result = R.fail(401, msg);
outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
outputStream.flush();
outputStream.close();
}
/**
* @descriptions 多种获取用户信息
* @author DB
* @date 2023/09/11 13:49
* @param userType 用户类型
* @param username 用户名
* @return com.pupu.core.base.entity.LoginUser
*/
private LoginUser multipleLoadUser(UserType userType, String username) {
LoginUser loginUser = null;
switch (userType) {
//系统登陆
case OAM_USER:
case MALL_USER:
loginUser = coreService.loadUserByUsername(username, userType);
break;
case MINI_USER:
// 获取用户的权限等信息
loginUser = coreService.loadUserByPhone(username, userType, null);
break;
default:
}
return loginUser;
}
/**
* @Description: 多种认证方式
* @param loginUser 登陆用户信息
* @author DB
* @Date: 2023/8/24 0024 17:12
*/
private void multipleAuth(LoginUser loginUser) {
switch (loginUser.getUserType()) {
case OAM_USER:
case MALL_USER:
//构建通用系统用户登陆
// 构建UsernamePasswordAuthenticationToken,这里密码为null是因为提供了正确的JWT,实现自动登录
SysAuthenticationToken sysAuthenticationToken = new SysAuthenticationToken(loginUser.getIdentification(), loginUser, null);
SecurityContextHolder.getContext().setAuthentication(sysAuthenticationToken);
break;
case MINI_USER:
// MiniProgramAuthenticationToken,实现自动登录
MiniProgramAuthenticationToken miniProgramAuthenticationToken = new MiniProgramAuthenticationToken(loginUser.getIdentification(), loginUser, null);
SecurityContextHolder.getContext().setAuthentication(miniProgramAuthenticationToken);
break;
default:
}
}
}

View File

@ -1,14 +1,13 @@
package com.cpop.core.filter;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.utils.StringUtils;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
;
/**
* Repeatable 过滤器
@ -17,14 +16,14 @@ import java.io.IOException;
*/
@Component
public class RepeatableFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);

View File

@ -1,12 +1,13 @@
package com.cpop.core.filter;
import com.cpop.common.utils.http.HttpHelper;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import com.cpop.core.utils.http.HttpHelper;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;

View File

@ -1,10 +1,10 @@
package com.cpop.core.filter;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.utils.StringUtils;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,15 +1,16 @@
package com.cpop.core.filter;
import com.cpop.common.utils.StringUtils;
import com.cpop.common.utils.html.EscapeUtil;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.utils.html.EscapeUtil;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

View File

@ -1,86 +0,0 @@
package com.cpop.core.gateway.miniProgram;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.enums.UserType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* @author DB
* @Description: 小程序认证过滤器
* @create 2023-08-23 21:03
*/
public class MiniProgramAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public MiniProgramAuthenticationFilter() {
super(new AntPathRequestMatcher("/miniLogin", "POST"));
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!"POST".equals(request.getMethod())) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
ObjectMapper mapper = new ObjectMapper();
InputStream inputStream;
Map authenticationBean;
try {
inputStream = request.getInputStream();
authenticationBean = mapper.readValue(inputStream, Map.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
String principal = (String) authenticationBean.get("phone");
if (StringUtils.isBlank(principal)){
throw new AuthenticationServiceException("登录手机号为空");
}
String openId = (String) authenticationBean.get("openId");
if (StringUtils.isBlank(openId)){
throw new AuthenticationServiceException("登录openId为空");
}
String appId = (String) authenticationBean.get("appId");
if (StringUtils.isBlank(appId)){
throw new AuthenticationServiceException("登录appId为空");
}
String brandId = (String) authenticationBean.get("brandId");
if (StringUtils.isBlank(brandId)){
throw new AuthenticationServiceException("登录brandId为空");
}
String nickName = (String) authenticationBean.get("nickName");
String avatar = (String) authenticationBean.get("avatar");
String sourceType = (String) authenticationBean.get("sourceType");
if (StringUtils.isBlank(sourceType)){
throw new AuthenticationServiceException("登录sourceType为空");
}
UserType userType = UserType.valueOf(authenticationBean.get("userType").toString());//传递信息
HashMap<String, Object> credentials = new HashMap<>(2);
credentials.put("appId", appId);
credentials.put("openId", openId);
credentials.put("userType", userType);
credentials.put("brandId", brandId);
credentials.put("nickName", nickName);
credentials.put("avatar", avatar);
credentials.put("sourceType", sourceType);
principal = principal.trim();
MiniProgramAuthenticationToken authRequest = new MiniProgramAuthenticationToken(principal, credentials);
this.setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
protected void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest) {
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
}
}

View File

@ -1,40 +0,0 @@
package com.cpop.core.gateway.miniProgram;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.service.CoreService;
import com.cpop.core.utils.SpringUtils;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import java.util.Map;
/**
* @author DB
* @Description: 自定义校验过程
* @create 2023-08-23 21:13
*/
public class MiniProgramAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// 这个获取表单输入中返回的用户名;
String phone =(String) authentication.getPrincipal();
// 这个是表单中输入的密码
Map<String,Object> credentials = (Map<String, Object>) authentication.getCredentials();
UserType userType = (UserType) credentials.get("userType");
LoginUser loginUser = SpringUtils.getBean(CoreService.class).loadUserByPhone(phone, userType, credentials);
loginUser.setUserType(UserType.MINI_USER);
MiniProgramAuthenticationToken result = new MiniProgramAuthenticationToken(phone, loginUser);
result.setDetails(loginUser);
return result;
}
@Override
public boolean supports(Class<?> authentication) {
//providerManager会遍历所有;securityConfig中注册的provider集合;根据此方法返回true或false来决定由哪个provider;去校验请求过来的authentication
return (MiniProgramAuthenticationToken.class.isAssignableFrom(authentication));
}
}

View File

@ -1,72 +0,0 @@
package com.cpop.core.gateway.miniProgram;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
/**
* @author DB
* @Description:
* @create 2023-08-23 21:11
*/
public class MiniProgramAuthenticationToken extends AbstractAuthenticationToken {
private final Object principal;
private Object credentials;
/**
* This constructor can be safely used by any code that wishes to create a
* <code>UsernamePasswordAuthenticationToken</code>, as the {@link #isAuthenticated()}
* will return <code>false</code>.
*
*/
public MiniProgramAuthenticationToken(Object principal, Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(false);
}
/**
* This constructor should only be used by <code>AuthenticationManager</code> or
* <code>AuthenticationProvider</code> implementations that are satisfied with
* producing a trusted (i.e. {@link #isAuthenticated()} = <code>true</code>)
* authentication token.
*
* @param principal
* @param credentials
* @param authorities
*/
public MiniProgramAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
// must use super, as we override
super.setAuthenticated(true);
}
@Override
public Object getCredentials() {
return this.credentials;
}
@Override
public Object getPrincipal() {
return this.principal;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
if (isAuthenticated) {
throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
}
super.setAuthenticated(false);
}
@Override
public void eraseCredentials() {
super.eraseCredentials();
credentials = null;
}
}

View File

@ -1,63 +0,0 @@
package com.cpop.core.gateway.sys;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.gateway.miniProgram.MiniProgramAuthenticationToken;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* @author DB
* @createTime 2023/10/19 9:27
* @description
*/
public class SysAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public SysAuthenticationFilter() {
super(new AntPathRequestMatcher("/login", "POST"));
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
if (!"POST".equals(request.getMethod())) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
//读取表单
ObjectMapper mapper = new ObjectMapper();
InputStream inputStream;
Map authenticationBean;
try {
inputStream = request.getInputStream();
authenticationBean = mapper.readValue(inputStream, Map.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
String principal = (String) authenticationBean.get("username");
String password = (String) authenticationBean.get("password");
UserType userType = UserType.valueOf(authenticationBean.get("userType").toString());
principal = principal.trim();
//传递信息
HashMap<String, Object> credentials = new HashMap<>(2);
credentials.put("password", password);
credentials.put("userType", userType);
SysAuthenticationToken authRequest = new SysAuthenticationToken(principal, credentials);
this.setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
protected void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest) {
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
}
}

View File

@ -1,49 +0,0 @@
package com.cpop.core.gateway.sys;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.exception.CpopAuthenticationException;
import com.cpop.core.gateway.miniProgram.MiniProgramAuthenticationToken;
import com.cpop.core.service.CoreService;
import com.cpop.core.utils.PasswordEncoder;
import com.cpop.core.utils.SpringUtils;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Map;
/**
* @author DB
* @createTime 2023/10/19 9:36
* @description
*/
public class SysAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// 这个获取表单输入中返回的用户名;
String principal = (String) authentication.getPrincipal();
// 这个是表单中输入的密码与用户类型
Map<String, Object> credentials = (Map<String, Object>) authentication.getCredentials();
UserType userType = (UserType) credentials.get("userType");
//认证用户名密码
LoginUser loginUser = SpringUtils.getBean(CoreService.class).loadUserByUsername(principal, userType);
//账号密码校验
boolean password = SpringUtils.getBean(PasswordEncoder.class).matches((String) credentials.get("password"), loginUser.getUser().getPassword());
if (!password){
throw new BadCredentialsException("用户名密码错误!");
}
SysAuthenticationToken result = new SysAuthenticationToken(principal, loginUser);
result.setDetails(loginUser);
return result;
}
@Override
public boolean supports(Class<?> authentication) {
//providerManager会遍历所有;securityConfig中注册的provider集合;根据此方法返回true或false来决定由哪个provider;去校验请求过来的authentication
return (SysAuthenticationToken.class.isAssignableFrom(authentication));
}
}

View File

@ -1,72 +0,0 @@
package com.cpop.core.gateway.sys;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
/**
* @author DB
* @createTime 2023/10/19 9:35
* @description
*/
public class SysAuthenticationToken extends AbstractAuthenticationToken {
private final Object principal;
private Object credentials;
/**
* This constructor can be safely used by any code that wishes to create a
* <code>UsernamePasswordAuthenticationToken</code>, as the {@link #isAuthenticated()}
* will return <code>false</code>.
*
*/
public SysAuthenticationToken(Object principal, Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(false);
}
/**
* This constructor should only be used by <code>AuthenticationManager</code> or
* <code>AuthenticationProvider</code> implementations that are satisfied with
* producing a trusted (i.e. {@link #isAuthenticated()} = <code>true</code>)
* authentication token.
*
* @param principal 第一个参数
* @param credentials 第二个参数
* @param authorities 认证
*/
public SysAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
// must use super, as we override
super.setAuthenticated(true);
}
@Override
public Object getCredentials() {
return this.credentials;
}
@Override
public Object getPrincipal() {
return this.principal;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
if (isAuthenticated) {
throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
}
super.setAuthenticated(false);
}
@Override
public void eraseCredentials() {
super.eraseCredentials();
credentials = null;
}
}

View File

@ -1,23 +1,17 @@
package com.cpop.core.handler;
import com.cpop.core.base.R;
import cn.dev33.satoken.exception.SaTokenException;
import com.cpop.core.base.entity.R;
import com.cpop.core.base.enums.ErrorCodeEnum;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.common.enums.ErrorCodeEnum;
import io.jsonwebtoken.JwtException;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
/**
@ -29,23 +23,23 @@ import java.util.Objects;
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 无登录异常
*/
@ExceptionHandler(SaTokenException.class)
public R<Void> handleNotLoginException(SaTokenException e) {
log.error(e.getMessage(), e);
return R.fail(e.getCode(), e.getMessage());
}
/**
* 业务异常
*/
@ExceptionHandler(ServiceException.class)
public R handleServiceException(ServiceException e) {
public R<Void> handleServiceException(ServiceException e) {
log.error(e.getMessage(), e);
Integer code = e.getCode();
return null != code ? R.fail(code, e.getMessage()) : R.fail(e.getMessage());
}
/**
* 权限不足
* @param e 权限不足异常
*/
@ExceptionHandler(AccessDeniedException.class)
public R handleException(AccessDeniedException e) {
return R.fail(ErrorCodeEnum.HTTP_401.getInfo());
return R.fail(e.getMessage());
}
/**
@ -55,45 +49,43 @@ public class GlobalExceptionHandler {
* @return
*/
@ExceptionHandler(RuntimeException.class)
public R handleRuntimeException(RuntimeException e, HttpServletRequest request) {
public R<Void> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
String requestUrl = request.getRequestURI();
log.error("请求地址'{}',发生未知异常.", requestUrl, e);
return R.fail(e.getMessage());
}
/**
* 自定义验证异常
* 系统异常
* @param e
* @param request
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
log.error(e.getMessage(), e);
String message = Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage();
return R.fail(message);
@ExceptionHandler(Exception.class)
public R<Void> handleException(Exception e, HttpServletRequest request) {
String requestUrl = request.getRequestURI();
log.error("请求地址'{}',发生系统异常.", requestUrl, e);
return R.fail(e.getMessage());
}
/**
* 自定义验证异常
*/
@ExceptionHandler(BindException.class)
public R handleBindException(BindException e) {
public R<Void> handleBindException(BindException e) {
log.error(e.getMessage(), e);
String message = e.getAllErrors().get(0).getDefaultMessage();
return R.fail(message);
}
/**
* 系统异常
* @author DB
* @since 2023/12/04
* @param e 异常
* @param request 请求
* @return R
* 自定义验证异常
*/
@ExceptionHandler(Exception.class)
public R handleException(Exception e, HttpServletRequest request) {
String requestUrl = request.getRequestURI();
log.error("请求地址'{}',发生系统异常.", requestUrl, e);
return R.fail(e.getMessage());
@ExceptionHandler(MethodArgumentNotValidException.class)
public R<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
log.error(e.getMessage(), e);
String message = Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage();
return R.fail(message);
}
}

View File

@ -1,33 +0,0 @@
package com.cpop.core.handler;
import com.alibaba.fastjson.JSONObject;
import com.cpop.core.base.R;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @author: DB
* @date: 2022-09-25 16:55
* @Description: 无权限访问处理器
*/
@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException {
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
R<String> result = R.fail(e.getMessage());
outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
outputStream.flush();
outputStream.close();
}
}

View File

@ -1,33 +0,0 @@
package com.cpop.core.handler;
import com.alibaba.fastjson.JSONObject;
import com.cpop.core.base.R;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @author: DB
* @date: 2022-09-25 16:40
* @Description: jwt认证失败处理器
*/
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
R<String> result = R.fail("请先登录");
outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
outputStream.flush();
outputStream.close();
}
}

View File

@ -1,77 +0,0 @@
package com.cpop.core.handler;
import com.alibaba.fastjson.JSONObject;
import com.cpop.common.constant.Constants;
import com.cpop.core.base.R;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.enums.OperationLogEnum;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.service.CoreService;
import com.cpop.core.service.RedisService;
import com.cpop.core.utils.JwtUtils;
import com.cpop.core.utils.MessageUtils;
import com.cpop.core.utils.SpringUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @author: DB
* @date: 2022-09-25 16:56
* @Description: 登出成功处理器
*/
@Component
public class JwtLogoutSuccessHandler implements LogoutSuccessHandler {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private RedisService redisService;
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException {
if (authentication != null) {
new SecurityContextLogoutHandler().logout(httpServletRequest, httpServletResponse, authentication);
}
String jwt = httpServletRequest.getHeader(jwtUtils.getHeader());
//添加退出登录成功日志
Jws<Claims> jws = jwtUtils.getClaimsByToken(jwt);
Claims claim = jws.getBody();
if (claim == null) {
throw new JwtException("token 异常");
}
if (jwtUtils.isTokenExpired(claim)) {
throw new JwtException("token 已过期");
}
String identification = claim.getSubject();
UserType userType = UserType.valueOf(jws.getHeader().get(Constants.USER_TYPE).toString());
//从缓存中获取
JSONObject jsonObject = redisService.getCacheObject(userType.getKey() + identification);
if (null != jsonObject) {
LoginUser loginUser = jsonObject.toJavaObject(LoginUser.class);
SpringUtils.getBean(CoreService.class).insertOperationLog(Constants.SUCCESS, OperationLogEnum.SYSTEM_LOGOUT, loginUser, MessageUtils.message("i18n_operationLog_systemLogout"));
}
//清除缓存
redisService.deleteObject(userType.getKey() + identification);
httpServletResponse.setContentType("application/json;charset=UTF-8");
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
String header = jwtUtils.getHeader();
httpServletResponse.setHeader(header, "");
R<String> result = R.ok(MessageUtils.message("i18n_loginOut_success"));
outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
outputStream.flush();
outputStream.close();
}
}

View File

@ -1,67 +0,0 @@
package com.cpop.core.handler;
import com.alibaba.fastjson.JSONObject;
import com.cpop.common.constant.Constants;
import com.cpop.common.utils.StringUtils;
import com.cpop.common.utils.ip.IpUtils;
import com.cpop.core.base.R;
import com.cpop.core.base.entity.LoginForm;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.enums.OperationLogEnum;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.exception.CpopAuthenticationException;
import com.cpop.core.service.CoreService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
/**
* @author: DB
* @date: 2022-09-25 16:24
* @Description: 登录失败handler
*/
@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {
@Autowired
private CoreService coreService;
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
httpServletResponse.setContentType("application/json;charset=UTF-8");
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
String jsonString = httpServletRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
//映射登录表单
LoginForm loginFormBo = JSONObject.parseObject(jsonString, LoginForm.class);
//构建用户信息
LoginUser loginUser = new LoginUser();
loginUser.setUserName(loginFormBo.getUsername()).setIpAddr(IpUtils.getIpAddr(httpServletRequest));
String errorMessage = "用户名或密码错误";
R<String> result;
//自定义认证异常,可以从这里获取到想要的参数
if(e instanceof CpopAuthenticationException) {
loginUser.setUserType((UserType) ((CpopAuthenticationException) e).getParams());
errorMessage = e.getMessage();
result = R.ok(errorMessage);
}else {
result = R.fail(errorMessage);
}
if (loginUser.getUserType() == UserType.OAM_USER || loginUser.getUserType() == UserType.MINI_USER) {
if (StringUtils.isNotBlank(loginFormBo.getUsername())){
//添加登录失败日志
coreService.insertOperationLog(Constants.FAIL, OperationLogEnum.SYSTEM_LOGIN, loginUser, errorMessage);
}
}
outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
outputStream.flush();
outputStream.close();
}
}

View File

@ -1,90 +0,0 @@
package com.cpop.core.handler;
import com.alibaba.fastjson.JSONObject;
import com.cpop.common.constant.Constants;
import com.cpop.common.utils.ip.IpUtils;
import com.cpop.core.base.R;
import com.cpop.core.base.entity.LoginSuccess;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.entity.loginInfo.MiniUserLoginInfo;
import com.cpop.core.base.enums.OperationLogEnum;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.service.CoreService;
import com.cpop.core.service.RedisService;
import com.cpop.core.utils.JwtUtils;
import com.cpop.core.utils.MessageUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @author: DB
* @date: 2022-09-25 16:19
* @Description: 登录成功handler
*/
@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private CoreService coreService;
@Autowired
private RedisService redisService;
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException{
httpServletResponse.setContentType("application/json;charset=UTF-8");
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
LoginSuccess loginSuccessVo = new LoginSuccess();
LoginUser loginUser;
if (null != authentication.getCredentials()) {
loginUser = (LoginUser) authentication.getCredentials();
} else {
loginUser = (LoginUser) authentication.getDetails();
}
// 生成JWT并放置到请求头中
String jwt = jwtUtils.generateToken(loginUser.getIdentification(), loginUser.getUsername(), loginUser.getUserType());
loginSuccessVo.setToken(jwt).setUserId(loginUser.getUserId()).setRole(loginUser.getPermissions());
String ipAddr = IpUtils.getIpAddr(httpServletRequest);
loginUser.setIpAddr(ipAddr);
//多种登陆方式
multipleLogin(loginUser);
R<LoginSuccess> result = R.ok(loginSuccessVo, MessageUtils.message("i18n_login_success"));
outputStream.write(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
outputStream.flush();
outputStream.close();
}
/**
* @Description: 多种登陆方式
* @param loginUser 登陆用户
* @author DB
* @Date: 2023/8/24 0024 17:12
*/
private void multipleLogin(LoginUser loginUser){
switch (loginUser.getUserType()) {
case OAM_USER:
case MALL_USER:
//更新登录地址
coreService.updateSysUserLoginIp(loginUser.getIpAddr(), loginUser.getUsername(), loginUser.getUserType());
//添加登录成功日志
coreService.insertOperationLog(Constants.SUCCESS, OperationLogEnum.SYSTEM_LOGIN, loginUser, MessageUtils.message("i18n_login_success"));
break;
case MINI_USER:
break;
default:
}
//将登录成功用户存入缓存
redisService.setCacheObject(loginUser.getUserType().getKey() + loginUser.getIdentification(), loginUser);
}
}

View File

@ -0,0 +1,111 @@
package com.cpop.core.listen;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import com.cpop.core.base.enums.OperationLogEnum;
import com.cpop.core.constant.Constants;
import com.cpop.core.service.OperationLogService;
import com.cpop.core.service.UserService;
import com.cpop.core.utils.MessageUtils;
import com.cpop.core.utils.SpringUtils;
import org.springframework.stereotype.Component;
import static com.cpop.core.base.table.table.UserTableDef.USER;
/**
* @author DB
* @version 1.0.0
* @since 2024-03-20 14:27
*/
@Component
public class JamboxSaTokenListener implements SaTokenListener {
/**
* 每次登录时触发
* @author DB
* @since 2024/3/20
* @param loginType 登录类型
* @param loginId 登录id
* @param tokenValue token
* @param loginModel 登录模块
*/
@Override
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
//添加登录成功日志
SaSession session = StpUtil.getSessionByLoginId(loginId);
SpringUtils.getBean(OperationLogService.class).insertOperationLog(Constants.SUCCESS, OperationLogEnum.SYSTEM_LOGIN, session, MessageUtils.message("i18n_login_success"));
//更新登录记录
SpringUtils.getBean(UserService.class).updateChain()
.set(USER.LOGIN_IP, session.getString("loginIp"))
.where(USER.USER_NAME.eq(session.getString("username")))
.update();
}
/**
* 每次注销时触发
* @author DB
* @since 2024/3/20
* @param loginType 登录类型
* @param loginId 登录id
* @param tokenValue token
*/
@Override
public void doLogout(String loginType, Object loginId, String tokenValue) {
}
/** 每次被踢下线时触发 */
@Override
public void doKickout(String loginType, Object loginId, String tokenValue) {
System.out.println("---------- 自定义侦听器实现 doKickout");
}
/** 每次被顶下线时触发 */
@Override
public void doReplaced(String loginType, Object loginId, String tokenValue) {
System.out.println("---------- 自定义侦听器实现 doReplaced");
}
/** 每次被封禁时触发 */
@Override
public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) {
System.out.println("---------- 自定义侦听器实现 doDisable");
}
/** 每次被解封时触发 */
@Override
public void doUntieDisable(String loginType, Object loginId, String service) {
System.out.println("---------- 自定义侦听器实现 doUntieDisable");
}
/** 每次二级认证时触发 */
@Override
public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) {
System.out.println("---------- 自定义侦听器实现 doOpenSafe");
}
/** 每次退出二级认证时触发 */
@Override
public void doCloseSafe(String loginType, String tokenValue, String service) {
System.out.println("---------- 自定义侦听器实现 doCloseSafe");
}
/** 每次创建Session时触发 */
@Override
public void doCreateSession(String id) {
System.out.println("---------- 自定义侦听器实现 doCreateSession");
}
/** 每次注销Session时触发 */
@Override
public void doLogoutSession(String id) {
System.out.println("---------- 自定义侦听器实现 doLogoutSession");
}
/** 每次Token续期时触发 */
@Override
public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
System.out.println("---------- 自定义侦听器实现 doRenewTimeout");
}
}

View File

@ -1,11 +1,10 @@
package com.cpop.core.listen;
import com.cpop.core.base.table.SysOperationLog;
import com.cpop.core.base.table.OperationLog;
import com.cpop.core.event.OperationLogEvent;
import com.cpop.core.utils.uuid.IdUtils;
import com.cpop.core.service.CoreService;
import com.cpop.core.service.OperationLogService;
import com.cpop.core.utils.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
@ -18,19 +17,15 @@ import org.springframework.stereotype.Component;
*/
@Slf4j
@Component
public class SysOperationLogListen {
@Autowired
private CoreService coreService;
public class OperationLogListen {
@Async
@Order
@EventListener(OperationLogEvent.class)
public void saveSysOperationLog(OperationLogEvent event) {
SysOperationLog operationLog = (SysOperationLog) event.getSource();
OperationLog operationLog = (OperationLog) event.getSource();
// 保存日志
operationLog.setId(IdUtils.fastSimpleUUID());
if (coreService.saveOperationLog(operationLog)) {
if (SpringUtils.getBean(OperationLogService.class).save(operationLog)) {
}
}
}

View File

@ -0,0 +1,14 @@
package com.cpop.core.mapper;
import com.cpop.core.base.table.Config;
import com.mybatisflex.core.BaseMapper;
/**
* 系统配置表 映射层
*
* @author DB
* @since 2024-02-01
*/
public interface ConfigMapper extends BaseMapper<Config> {
}

View File

@ -1,133 +0,0 @@
package com.cpop.core.mapper;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.table.SysConfig;
import com.cpop.core.base.table.SysOperationLog;
import com.cpop.core.base.table.SysUser;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author DB
* @Description:
* @create 2023-08-27 10:54
*/
public interface CoreMapper {
/**
* @Description: 插入操作日志
* @param log
* @return Integer
* @Author DB
* @Date: 2023/8/27 10:56
*/
Boolean insertOperationLog(SysOperationLog log);
/**
* @Description: 根据用户名获取用户信息
* @param username 用户名
* @param userType 用户类型
* @return SysUser
* @Author DB
* @Date: 2023/8/27 23:39
*/
SysUser getSysUserByUsername(@Param("username") String username, @Param("userType") String userType);
/**
* @Description: 更新登录地址
* @param ipAddr
* @param username
* @return
* @author DB
* @Date: 2023/8/28 0028 13:49
*/
void updateSysUserLoginIp(String ipAddr, String username, String userType);
/**
* @Description: 加载参数缓存数据
* @param
* @return List<SysConfig>
* @Author DB
* @Date: 2023/8/28 22:33
*/
List<SysConfig> loadingConfigCache();
/**
* @Description: 根据键名查询参数配置信息
* @param configKey
* @return SysConfig
* @Author DB
* @Date: 2023/8/28 22:49
*/
SysConfig selectConfigByKey(String configKey);
/**
* @Description: 新增参数配置
* @param config
* @return boolean
* @Author DB
* @Date: 2023/8/28 23:03
*/
boolean insertConfig(SysConfig config);
/**
* @Description: 修改参数配置
* @param config
* @return boolean
* @Author DB
* @Date: 2023/8/28 23:17
*/
boolean updateConfig(SysConfig config);
/**
* @Description: 根据键查询配置
* @param list
* @return List<SysConfig>
* @Author DB
* @Date: 2023/8/28 23:25
*/
List<SysConfig> selectConfigByKeys(List<String> list);
/**
* @Description: 需要删除的参数ID
* @param list
* @return
* @Author DB
* @Date: 2023/8/28 23:29
*/
void deleteConfigByKeys(List<String> list);
/**
* @descriptions 新增系统用户
* @author DB
* @date 2023/09/08 15:04
* @param sysUser 系统用户参数
*/
void insertSysUser(SysUser sysUser);
/**
* @descriptions 修改系统用户
* @author DB
* @date 2023/09/08 17:21
* @param sysUser 系统用户参数d
*/
void updateSysUser(SysUser sysUser);
/**
* @descriptions 根据主键删除用户(逻辑删除)
* @author DB
* @date 2023/09/08 17:50
* @param id 主键
*/
void removeSysUserById(String id);
/**
* @Description: 根据用户名获取用户信息
* @param phoneNumber 手机号
* @return SysUser
* @Author: DB
* @Date: 2023/8/27 23:37
*/
SysUser getSysUserByPhone(@Param("phoneNumber") String phoneNumber, @Param("userType") String userType);
}

View File

@ -0,0 +1,14 @@
package com.cpop.core.mapper;
import com.cpop.core.base.table.OperationLog;
import com.mybatisflex.core.BaseMapper;
/**
* 操作日志表 映射层
*
* @author DB
* @since 2024-02-01
*/
public interface OperationLogMapper extends BaseMapper<OperationLog> {
}

View File

@ -0,0 +1,14 @@
package com.cpop.core.mapper;
import com.cpop.core.base.table.User;
import com.mybatisflex.core.BaseMapper;
/**
* 系统用户 映射层
*
* @author DB
* @since 2024-02-01
*/
public interface UserMapper extends BaseMapper<User> {
}

View File

@ -0,0 +1,18 @@
package com.cpop.core.service;
import com.cpop.core.base.table.Config;
import com.mybatisflex.core.service.IService;
/**
* 系统配置表 服务层
*
* @author DB
* @since 2024-02-01
*/
public interface ConfigService extends IService<Config> {
/**
* 加载参数缓存数据
*/
void loadingConfigCache();
}

View File

@ -1,164 +0,0 @@
package com.cpop.core.service;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.enums.OperationLogEnum;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.table.SysConfig;
import com.cpop.core.base.table.SysOperationLog;
import com.cpop.core.base.table.SysUser;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Map;
/**
* @author DB
* @Description:
* @create: 2023-08-27 11:04
*/
public interface CoreService {
/**
* @Description: 添加操作日志
* @param status 状态
* @param loginUser 登陆用户
* @param failReason 失败原因
* @return String
* @Author: DB
* @Date: 2023/8/27 11:08
*/
String insertOperationLog(Integer status, OperationLogEnum operationLogEnum, LoginUser loginUser, String failReason);
/**
* @Description: 添加操作日志
* @param operationLog 日志
* @return boolean
* @Author: DB
* @Date: 2023/8/29 23:46
*/
boolean saveOperationLog(SysOperationLog operationLog);
/**
* @Description: 根据用户名获取用户信息
* @param username 用户名
* @return SysUser
* @Author: DB
* @Date: 2023/8/27 23:37
*/
SysUser getSysUserByUsername(String username, UserType userType);
/**
* @Description: 更新登录地址
* @param ipAddr ip地址
* @param username 用户名
* @author DB
* @Date: 2023/8/28 0028 13:48
*/
void updateSysUserLoginIp(String ipAddr, String username, UserType userType);
/**
* 根据键名查询参数配置信息
*
* @param configKey 参数键名
* @return 参数键值
*/
SysConfig selectConfigByKey(String configKey);
/**
* @Description: 新增参数配置
* @param config
* @author DB
* @Date: 2023/6/7 0007 16:17
*/
void insertConfig(SysConfig config);
/**
* @Description: 修改参数配置
* @param config
* @author DB
* @Date: 2023/6/7 0007 16:19
*/
void updateConfig(SysConfig config);
/**
* @Description: 批量删除参数信息
* @param keys
* @author DB
* @Date: 2023/6/8 0008 9:58
*/
void deleteConfigByKeys(String[] keys);
/**
* @descriptions 新增系统用户
* @author DB
* @date 2023/09/08 15:04
* @param sysUser 系统用户参数
*/
void insertSysUser(SysUser sysUser);
/**
* @descriptions 修改系统用户
* @author DB
* @date 2023/09/08 17:20
* @param sysUser 系统用户参数
*/
void updateSysUser(SysUser sysUser);
/**
* @descriptions 根据主键删除用户
* @author DB
* @date 2023/09/08 17:49
* @param id 主键
* @return void
*/
void removeSysUserById(String id);
/**
* @descriptions 根据用户名与用户类型获取用户信息
* @author DB
* @date 2023/10/19 9:57
* @param userName 用户名
* @param userType 用户类型
* @return 登陆用户
*/
LoginUser loadUserByUsername(String userName, UserType userType);
/**
* @descriptions 根据手机号与用户类型获取用户信息
* @author DB
* @date 2023/10/19 9:57
* @param phoneNumber 手机号
* @param userType 用户类型
* @return 登陆用户
*/
LoginUser loadUserByPhone(String phoneNumber, UserType userType);
/**
* @descriptions 根据手机号与用户类型获取用户信息
* @author DB
* @date 2023/10/19 9:57
* @param phoneNumber 手机号
* @param userType 用户类型
* @return 登陆用户
*/
LoginUser loadUserByPhone(String phoneNumber, UserType userType, Map<String, Object> credentials);
/**
* @Description: 根据用户名获取用户信息
* @param phoneNumber 手机号
* @return SysUser
* @Author: DB
* @Date: 2023/8/27 23:37
*/
SysUser getSysUserByPhone(String phoneNumber, UserType userType);
/**
* @descriptions 检查用户是否存在
* @author DB
* @date 2023/11/10 11:57
* @param username 用户名
* @param id 主键
* @param userType 用户类型
* @return: void
*/
void isAccountExist(String username, String id, String userType);
}

View File

@ -0,0 +1,27 @@
package com.cpop.core.service;
import cn.dev33.satoken.session.SaSession;
import com.cpop.core.base.enums.OperationLogEnum;
import com.cpop.core.base.table.OperationLog;
import com.mybatisflex.core.service.IService;
/**
* 操作日志表 服务层
*
* @author DB
* @since 2024-02-01
*/
public interface OperationLogService extends IService<OperationLog> {
/**
* 插入操作日志
* @author DB
* @since 2024/2/2
* @param status 状态
* @param operationLogEnum 日志枚举
* @param session 登陆用户session
* @param failReason 失败原因
* @return String 主键
*/
String insertOperationLog(Integer status, OperationLogEnum operationLogEnum, SaSession session, String failReason);
}

View File

@ -0,0 +1,14 @@
package com.cpop.core.service;
import com.cpop.core.base.table.User;
import com.mybatisflex.core.service.IService;
/**
* 系统用户 服务层
*
* @author DB
* @since 2024-02-01
*/
public interface UserService extends IService<User> {
}

View File

@ -1,39 +0,0 @@
package com.cpop.core.service.impl;
import com.cpop.common.constant.Constants;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Set;
/**
* @author: DB
* @date: 2022-10-20 15:15
* @Description:
* AuthorityPermissionService自定义access表达式鉴权验证
* 可以将自定义的access添加到配置类中http.anyRequest.access(aps.hasPermission(xxx,xxx));
* 也可以直接使用注解@PreAuthorize@PreAuthorize(aps.hasPermission(xxx));
*/
@Service("aps")
public class AuthorityPermissionService {
public boolean hasPermission(String permissions) {
if (StringUtils.isEmpty(permissions)) {
return false;
}
// 用户信息对象
LoginUser loginUser = SecurityUtils.getInstance().getLoginUser();
if (loginUser == null || CollectionUtils.isEmpty(loginUser.getPermissions())) {
return false;
}
Set<String> authorities = loginUser.getPermissions();
return StringUtils.isNotEmpty(permissions) && hasPermissions(authorities, permissions);
}
private boolean hasPermissions(Set<String> authorities, String permission) {
return authorities.contains(Constants.ALL_PERMISSION) || authorities.contains(permission.trim());
}
}

View File

@ -0,0 +1,49 @@
package com.cpop.core.service.impl;
import com.cpop.core.base.table.Config;
import com.cpop.core.constant.Constants;
import com.cpop.core.mapper.ConfigMapper;
import com.cpop.core.service.ConfigService;
import com.cpop.core.service.RedisService;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 系统配置表 服务层实现
*
* @author DB
* @since 2024-02-01
*/
@Service("configService")
public class ConfigServiceImpl extends ServiceImpl<ConfigMapper, Config> implements ConfigService {
@Autowired
private RedisService redisService;
/**
* 加载参数缓存数据
*/
@Override
public void loadingConfigCache() {
//获取所有配置(可自定义)
List<Config> configsList = this.list();
if (!configsList.isEmpty()) {
for (Config config : configsList) {
redisService.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
}
}
}
/**
* 设置cache key
*
* @param configKey 参数键
* @return 缓存键key
*/
private String getCacheKey(String configKey) {
return Constants.CONFIG_KEY + configKey;
}
}

View File

@ -1,302 +0,0 @@
package com.cpop.core.service.impl;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.enums.OperationLogEnum;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.base.table.SysConfig;
import com.cpop.core.base.table.SysOperationLog;
import com.cpop.core.base.table.SysUser;
import com.cpop.core.mapper.CoreMapper;
import com.cpop.core.service.CoreService;
import com.cpop.core.utils.MessageUtils;
import com.cpop.core.utils.SecurityUtils;
import com.cpop.core.utils.uuid.IdUtils;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.DbChain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static com.cpop.core.base.table.table.SysUserTableDef.SYS_USER;
/**
* @author DB
* @Description:
* @create: 2023-08-27 11:04
*/
@Service("coreService")
public class CoreServiceImpl implements CoreService {
@Autowired
private CoreMapper coreMapper;
/**
* @Description: 添加操作日志
* @param status 状态
* @param operationLogEnum 日志枚举
* @param loginUser 登陆用户
* @param failReason 失败原因
* @return String
* @Author: DB
* @Date: 2023/8/27 11:08
*/
@Override
public String insertOperationLog(Integer status, OperationLogEnum operationLogEnum, LoginUser loginUser, String failReason) {
SysOperationLog operationLog = new SysOperationLog();
operationLog.setId(IdUtils.fastSimpleUUID())
.setCode(operationLogEnum.getCode())
.setInfo(MessageUtils.message(operationLogEnum.getInfo()))
.setDevIp(loginUser.getIpAddr())
.setOperationUserType(loginUser.getUserType())
.setOperationUserName(loginUser.getUsername());
if (200 == status) {
operationLog.setOperationUserId(loginUser.getUserId())
.setLevel(operationLogEnum.getSuccessLevel())
.setDescription(MessageUtils.message(operationLogEnum.getInfo()) + MessageUtils.message("i18n_baseInfo_success"))
.setResult(true)
.setActionType(1);
} else {
operationLog.setLevel(operationLogEnum.getExceptionLevel())
.setDescription(MessageUtils.message(operationLogEnum.getInfo()) + MessageUtils.message("i18n_baseInfo_failed"))
.setFailReason(failReason)
.setResult(false)
.setActionType(2);
}
operationLog.setCreateUserId(loginUser.getUserId());
operationLog.setUpdateUserId(loginUser.getUserId());
if (coreMapper.insertOperationLog(operationLog)) {
}
return operationLog.getId();
}
/**
* @Description: 添加操作日志
* @param operationLog 操作日志
* @return boolean
* @Author DB
* @Date: 2023/8/29 23:46
*/
@Override
public boolean saveOperationLog(SysOperationLog operationLog) {
return coreMapper.insertOperationLog(operationLog);
}
/**
* @Description: 根据用户名获取用户信息
* @param username 用户名
* @return SysUser
* @Author DB
* @Date: 2023/8/27 23:37
*/
@Override
public SysUser getSysUserByUsername(String username, UserType userType) {
return coreMapper.getSysUserByUsername(username, userType.toString());
}
/**
* @Description: 更新登录地址
* @param ipAddr 地址
* @param username 用户名
* @author DB
* @Date: 2023/8/28 0028 13:48
*/
@Override
public void updateSysUserLoginIp(String ipAddr, String username, UserType userType) {
coreMapper.updateSysUserLoginIp(ipAddr, username, userType.toString());
}
/**
* @Description: 根据键名查询参数配置信息
* @param configKey
* @return String
* @author DB
* @Date: 2023/6/7 0007 15:59
*/
@Override
public SysConfig selectConfigByKey(String configKey) {
return coreMapper.selectConfigByKey(configKey);
}
/**
* 新增参数配置
*
* @param config 参数配置信息
*/
@Override
public void insertConfig(SysConfig config) {
LoginUser loginUser = SecurityUtils.getInstance().getLoginUser();
config.setCreateUserId(null == loginUser ? "1" : loginUser.getUserId());
config.setUpdateUserId(null == loginUser ? "1" : loginUser.getUserId());
coreMapper.insertConfig(config);
}
/**
* 修改参数配置
*
* @param config 参数配置信息
*/
@Override
public void updateConfig(SysConfig config) {
LoginUser loginUser = SecurityUtils.getInstance().getLoginUser();
config.setUpdateUserId(null == loginUser ? "1" : loginUser.getUserId());
coreMapper.updateConfig(config);
}
/**
* 批量删除参数信息
*
* @param keys 需要删除的参数ID
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteConfigByKeys(String[] keys) {
List<String> keyList = Arrays.asList(keys);
List<SysConfig> sysConfigList = coreMapper.selectConfigByKeys(keyList);
sysConfigList.forEach(item -> {
if (item.getConfigType()) {
throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", item.getConfigKey()));
}
});
coreMapper.deleteConfigByKeys(keyList);
}
/**
* @descriptions 新增系统用户
* @author DB
* @date 2023/09/08 15:04
* @param sysUser 系统用户参数
*/
@Override
public void insertSysUser(SysUser sysUser) {
coreMapper.insertSysUser(sysUser);
}
/**
* @descriptions 修改系统用户
* @author DB
* @date 2023/09/08 17:20
* @param sysUser 系统用户参数
*/
@Override
public void updateSysUser(SysUser sysUser) {
coreMapper.updateSysUser(sysUser);
}
/**
* @descriptions 根据主键删除用户
* @author DB
* @date 2023/09/08 17:50
* @param id 主键
*/
@Override
public void removeSysUserById(String id) {
coreMapper.removeSysUserById(id);
}
/**
* @descriptions 根据用户名与用户类型获取用户信息
* @author DB
* @date 2023/10/19 9:57
* @param username 用户名
* @param userType 用户类型
* @return 登陆用户
*/
@Override
public LoginUser loadUserByUsername(String username, UserType userType) {
//统一获取系统用户信息
SysUser sysUser = this.getSysUserByUsername(username, userType);
if (sysUser == null) {
throw new UsernameNotFoundException(MessageUtils.message("i18n_alert_accountOrPwdError"));
}
return userType.getStrategy().getLoginUserInfo(sysUser, null);
}
/**
* @descriptions 可能存在用户手机号登陆的情况
* @author DB
* @date 2023/11/21 10:05
* @param phoneNumber 手机号
* @param userType 用户类型
* @return: com.cpop.core.base.entity.LoginUser
*/
@Override
public LoginUser loadUserByPhone(String phoneNumber, UserType userType) {
//统一获取系统用户信息
SysUser sysUser = this.getSysUserByPhone(phoneNumber, userType);
return userType.getStrategy().getLoginUserInfo(sysUser, null);
}
/**
* @descriptions 根据手机号与用户类型获取用户信息
* @author DB
* @date 2023/10/19 9:57
* @param phoneNumber 手机号
* @param userType 用户类型
* @return 登陆用户
*/
@Override
@Transactional(rollbackFor = Exception.class)
public LoginUser loadUserByPhone(String phoneNumber, UserType userType, Map<String, Object> credentials) {
//统一获取系统用户信息
SysUser sysUser = this.getSysUserByPhone(phoneNumber, userType);
if (sysUser == null) {
//如果是小程序自动注册用户信息
if (userType == UserType.MINI_USER) {
sysUser = new SysUser();
sysUser.setId(IdUtils.fastSimpleUUID())
.setUserName(phoneNumber)
.setPhoneNumber(phoneNumber)
.setStatus(true)
.setUserType(userType.toString())
.setCreateUserId("1");
sysUser.setUpdateUserId("1");
this.coreMapper.insertSysUser(sysUser);
} else {
throw new UsernameNotFoundException("获取用户信息失败");
}
}
//构建登陆用户信息
return userType.getStrategy().getLoginUserInfo(sysUser, credentials);
}
/**
* @Description: 根据用户名获取用户信息
* @param phoneNumber 手机号
* @return SysUser
* @Author: DB
* @Date: 2023/8/27 23:37
*/
@Override
public SysUser getSysUserByPhone(String phoneNumber, UserType userType) {
return coreMapper.getSysUserByPhone(phoneNumber, userType.toString());
}
/**
* @descriptions 检查用户是否存在
* @author DB
* @date 2023/11/10 11:57
* @param username 用户名
* @param id 主键
* @param userType 用户类型
* @return: void
*/
@Override
public void isAccountExist(String username, String id, String userType) {
if (StringUtils.isBlank(username)) {
return;
}
if (DbChain.table(SYS_USER).where(SYS_USER.USER_NAME.eq(username))
.and(SYS_USER.USER_TYPE.eq(userType))
.and(SYS_USER.ID.ne(id)).count() > 0) {
throw new ServiceException(MessageUtils.message("i18n_alert_userIsExist"));
}
}
}

View File

@ -1,96 +0,0 @@
package com.cpop.core.service.impl;
import com.cpop.common.constant.Constants;
import com.cpop.common.utils.bean.BeanUtils;
import com.cpop.core.base.entity.LoginUser;
import com.cpop.core.base.entity.Permission;
import com.cpop.core.base.entity.loginInfo.OamStaffLoginInfo;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.table.SysUser;
import com.cpop.core.service.CoreService;
import com.cpop.core.utils.MessageUtils;
import com.mybatisflex.core.row.DbChain;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.row.RowUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author DB
* @createTime 2023/09/11 10:56
* @description oam员工登陆信息
*/
@Service("oamStaffDetailsService")
public class OamStaffDetailsServiceImpl implements UserDetailsService {
@Autowired
private CoreService coreService;
/**
* @descriptions 加载员工信息
* @author DB
* @date 2023/09/11 10:57
* @param username 用户名
* @return org.springframework.security.core.user.details.UserDetails
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//统一获取系统用户信息
SysUser sysUser = coreService.getSysUserByUsername(username, UserType.OAM_USER);
if (sysUser == null) {
throw new UsernameNotFoundException(MessageUtils.message("i18n_alert_accountOrPwdError"));
}
//构建登陆员工信息
OamStaffLoginInfo staffLoginInfo = BeanUtils.mapToClass(sysUser, OamStaffLoginInfo.class);
staffLoginInfo.setUserId(sysUser.getId());
//员工
if (!staffLoginInfo.getUserName().equals(Constants.SUPER_ADMIN)) {
Row row = DbChain.table("cp_oam_staff")
.select()
.where("user_id = ?", staffLoginInfo.getUserId())
.one();
staffLoginInfo.setDeptId(row.getString("deptId"));
staffLoginInfo.setRoleId(row.getString("roleId"));
staffLoginInfo.setName(row.getString("name"));
staffLoginInfo.setStaffType(row.getInt("staffType"));
staffLoginInfo.setId(row.getString("id"));
}
//获取权限
Set<String> permissionSet = new HashSet<>();
if (Constants.SUPER_ADMIN.equals(username)) {
permissionSet.add(Constants.ALL_PERMISSION);
staffLoginInfo.setName(Constants.SUPER_ADMIN);
}
else {
//查询员工信息
List<Row> list = DbChain.table("oam_menu")
.select("pom.permission")
.from("cp_oam_menu").as("pom")
.leftJoin("cp_oam_role_menu").as("porm").on("porm.menu_id = pom.id")
.where("pom.type in (1,2)")
.and("porm.role_id = ?", staffLoginInfo.getRoleId())
.and("pom.permission is not null")
.list();
if (list.isEmpty()) {
permissionSet = new HashSet<>();
} else {
List<Permission> permissions = RowUtil.toEntityList(list, Permission.class);
permissionSet = permissions.stream().map(Permission::getPermission).collect(Collectors.toSet());
}
}
LoginUser loginUser = new LoginUser(sysUser.getId(), staffLoginInfo, permissionSet);
loginUser.setUserName(username)
.setLoginTime(System.currentTimeMillis())
.setStatus(sysUser.getStatus());
return loginUser;
}
}

Some files were not shown because too many files have changed in this diff Show More