Browse Source

Merge remote-tracking branch 'origin/master'

master
PoffyZhang 1 year ago
parent
commit
9bdd42b2f9
29 changed files with 517 additions and 68 deletions
  1. +3
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/common/handler/GlobalResponseHandler.java
  2. +1
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/expert/entity/ExpertUserFullInfo.java
  3. +5
    -5
      pmapi/src/main/java/com/ningdatech/pmapi/expert/manage/ExpertManage.java
  4. +1
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/expert/manage/ExpertReviewManage.java
  5. +3
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/expert/model/entity/ExpertReview.java
  6. +4
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/expert/model/req/ExpertReviewDetailReq.java
  7. +51
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/irs/config/IrsSealPlatformProperties.java
  8. +8
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingController.java
  9. +21
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/MeetingOptionProjectReq.java
  10. +3
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/ExpertInviteManage.java
  11. +48
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java
  12. +2
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/task/ExpertInviteTask.java
  13. +9
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/vo/ProjectLibListItemVO.java
  14. +4
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/sms/manage/SmsManage.java
  15. +2
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/sms/model/po/ReqVerificationCodePO.java
  16. +29
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/sms/task/YxtPollingTask.java
  17. +5
    -3
      pmapi/src/main/java/com/ningdatech/pmapi/sms/utils/SmsRedisKeyUtils.java
  18. +7
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/controller/UserAuthController.java
  19. +0
    -6
      pmapi/src/main/java/com/ningdatech/pmapi/user/controller/UserInfoController.java
  20. +5
    -38
      pmapi/src/main/java/com/ningdatech/pmapi/user/manage/UserInfoManage.java
  21. +5
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/AuthProperties.java
  22. +6
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/WebSecurityConfig.java
  23. +74
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/agent/AgentAuthFilter.java
  24. +40
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/agent/AgentAuthProvider.java
  25. +55
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/agent/AgentAuthSecurityConfig.java
  26. +76
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/agent/AgentAuthToken.java
  27. +48
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/agent/AgentLoginUserDetailService.java
  28. +1
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/handler/DefaultLoginSuccessHandler.java
  29. +1
    -0
      pmapi/src/main/resources/security/auth-dev.yml

+ 3
- 2
pmapi/src/main/java/com/ningdatech/pmapi/common/handler/GlobalResponseHandler.java View File

@@ -1,6 +1,5 @@
package com.ningdatech.pmapi.common.handler;

import cn.hutool.json.JSONUtil;
import com.ningdatech.basic.model.ApiResponse;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
@@ -24,7 +23,9 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
"com.ningdatech.pmapi.sys.controller",
"com.ningdatech.pmapi.todocenter.controller",
"com.ningdatech.pmapi.user.controller",
"com.ningdatech.pmapi.expert.controller"
"com.ningdatech.pmapi.meeting.controller",
"com.ningdatech.pmapi.expert.controller",
"com.ningdatech.pmapi.sms.controller"
})
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> {



+ 1
- 1
pmapi/src/main/java/com/ningdatech/pmapi/expert/entity/ExpertUserFullInfo.java View File

@@ -17,8 +17,8 @@ import java.time.LocalDateTime;
* @author Liuxinxin
* @since 2023-02-22
*/
@TableName("nd_expert_user_full_info")
@Data
@TableName("nd_expert_user_full_info")
@ApiModel(value = "NdExpertUserFullInfo对象", description = "")
public class ExpertUserFullInfo implements Serializable {



+ 5
- 5
pmapi/src/main/java/com/ningdatech/pmapi/expert/manage/ExpertManage.java View File

@@ -60,13 +60,12 @@ public class ExpertManage {
*
* @param request
*/
@Transactional(rollbackFor = Exception.class)
public void expertBasicInfoSubmit(ExpertUserBasicInfoSubmitRequest request) {
// 用户id
// Long userId = LoginUserUtil.getUserId();
ExpertBasicInfo basicInfo = request.getBasicInfo();
Long userId = generateOrGetUserId(basicInfo);


// 校验区域编码合法性 校验履职意向编码合法性
ExpertRegionInfo expertRegionInfo = basicInfo.getExpertRegionInfo();
expertManageHelper.expertRegionInfoCheck(expertRegionInfo);
@@ -99,13 +98,13 @@ public class ExpertManage {
List<DictionaryFieldInfo> recommendedWay = recommendInfo.getRecommendedWay();
// 推荐方式
List<FileBasicInfo> recommendProofFile = recommendInfo.getRecommendationProofFile();
expertRecommendProofSubmit(recommendedWay, recommendProofFile);
expertRecommendProofSubmit(recommendedWay, recommendProofFile, userId);
}


public void expertRecommendProofSubmit(List<DictionaryFieldInfo> recommendedWay, List<FileBasicInfo> recommendProofFile) {
@Transactional(rollbackFor = Exception.class)
public void expertRecommendProofSubmit(List<DictionaryFieldInfo> recommendedWay, List<FileBasicInfo> recommendProofFile, Long expertUserId) {
// 用户id
Long expertUserId = LoginUserUtil.getUserId();
ExpertUserFullInfo expertUserFullInfo = iExpertUserFullInfoService.getByUserId(expertUserId);
// 判断专家状态,是否可以进行证明材料提交
if (Objects.isNull(expertUserFullInfo)
@@ -158,6 +157,7 @@ public class ExpertManage {
.realName(basicInfo.getName())
// .employeeCode(dingEmployeeInfo.getEmployeeCode())
.available(UserAvailableEnum.DISABLE.name())
.mobile(phoneNo)
.createBy(LoginUserUtil.getUserId())
.updateBy(LoginUserUtil.getUserId())
.createOn(LocalDateTime.now())


+ 1
- 0
pmapi/src/main/java/com/ningdatech/pmapi/expert/manage/ExpertReviewManage.java View File

@@ -79,6 +79,7 @@ public class ExpertReviewManage {
review.setContent(JSONUtil.toJsonStr(req.getReviewTemplateOptions()));
review.setProjectId(req.getProjectId());
review.setTemplateId(req.getTemplateId());
review.setMeetingId(req.getMeetingId());
review.setOtherAdvice(req.getOtherAdvice());
review.setAttachFileId(req.getAttachFileId());
review.setIsFinal(req.getIsFinal());


+ 3
- 0
pmapi/src/main/java/com/ningdatech/pmapi/expert/model/entity/ExpertReview.java View File

@@ -30,6 +30,9 @@ public class ExpertReview implements Serializable {
@ApiModelProperty("项目ID")
private Long projectId;

@ApiModelProperty("会议ID")
private Long meetingId;

@ApiModelProperty("评审模版配置ID")
private Long templateId;



+ 4
- 0
pmapi/src/main/java/com/ningdatech/pmapi/expert/model/req/ExpertReviewDetailReq.java View File

@@ -28,6 +28,10 @@ public class ExpertReviewDetailReq {
@NotNull(message = "项目ID不能为空")
private Long projectId;

@ApiModelProperty("会议ID")
@NotNull(message = "会议ID不能为空")
private Long meetingId;

@Valid
@ApiModelProperty("配置模版")
@NotEmpty(message = "配置不能为空")


+ 51
- 0
pmapi/src/main/java/com/ningdatech/pmapi/irs/config/IrsSealPlatformProperties.java View File

@@ -0,0 +1,51 @@
package com.ningdatech.pmapi.irs.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
* @author liuxinxin
* @date 2023/3/16 下午6:03
*/

@Component
@Data
public class IrsSealPlatformProperties {
public static String projectId;

public static String projectSecret;

public static String accessKey;

public static String secretKey;

public static String apiUrl;


@Value("${irs.seal-platform.project-id}")
public void setProjectId(String projectId) {
IrsSealPlatformProperties.projectId = projectId;
}

@Value("${irs.seal-platform.project-secret}")
public void setProjectSecret(String projectSecret) {
IrsSealPlatformProperties.projectSecret = projectSecret;
}

@Value("${irs.seal-platform.access-key}")
public void setAccessKey(String accessKey) {
IrsSealPlatformProperties.accessKey = accessKey;
}

@Value("${irs.seal-platform.secret-key}")
public void setSecretKey(String secretKey) {
IrsSealPlatformProperties.secretKey = secretKey;
}

@Value("${irs.seal-platform.api-url}")
public void setApiUrl(String apiUrl) {
IrsSealPlatformProperties.apiUrl = apiUrl;
}

}

+ 8
- 1
pmapi/src/main/java/com/ningdatech/pmapi/meeting/controller/MeetingController.java View File

@@ -8,6 +8,7 @@ import com.ningdatech.pmapi.meeting.entity.dto.ReviewProjectDTO;
import com.ningdatech.pmapi.meeting.entity.req.*;
import com.ningdatech.pmapi.meeting.entity.vo.*;
import com.ningdatech.pmapi.meeting.manage.MeetingManage;
import com.ningdatech.pmapi.projectlib.model.vo.ProjectLibListItemVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
@@ -168,8 +169,14 @@ public class MeetingController {

@GetMapping("/listReviewProject")
@ApiOperation("评审会议列表")
public PageVo<ReviewProjectDTO> listReviewProject(ReviewProjectListReq req){
public PageVo<ReviewProjectDTO> listReviewProject(ReviewProjectListReq req) {
return meetingManage.pageReviewProject(req);
}

@GetMapping("/option/project")
@ApiOperation("项目列表(创建会议添加项目)")
public PageVo<ProjectLibListItemVO> projectList(MeetingOptionProjectReq req) {
return meetingManage.optionProject(req);
}

}

+ 21
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/entity/req/MeetingOptionProjectReq.java View File

@@ -0,0 +1,21 @@
package com.ningdatech.pmapi.meeting.entity.req;

import com.ningdatech.basic.model.PagePo;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
* <p>
* MeetingOptionProjectReq
* </p>
*
* @author WendyYang
* @since 11:50 2023/3/16
*/
@Data
@EqualsAndHashCode
public class MeetingOptionProjectReq extends PagePo {

private String meetingType;

}

+ 3
- 2
pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/ExpertInviteManage.java View File

@@ -77,6 +77,7 @@ public class ExpertInviteManage {
.select(ExpertUserFullInfo::getUserId,
ExpertUserFullInfo::getId,
ExpertUserFullInfo::getCompany,
ExpertUserFullInfo::getExpertName,
ExpertUserFullInfo::getPhoneNo)
.eq(ExpertUserFullInfo::getExpertAccountStatus, ExpertAccountStatusEnum.AVAILABLE.getKey());
}
@@ -281,7 +282,7 @@ public class ExpertInviteManage {
LambdaQueryWrapper<ExpertUserFullInfo> query = buildBaseExpertQuery();
query.notIn(!tmpAvoidCompany.isEmpty(), ExpertUserFullInfo::getCompany, tmpAvoidCompany);
if (avoidCompany) {
query.notExists("select 1 from expert_avoid_company eac where eac.user_id = expert_user_full_info.user_id" +
query.notExists("select 1 from expert_avoid_company eac where eac.user_id = nd_expert_user_full_info.user_id" +
" and company_name in ({0})", CollUtils.joinByComma(avoidRule.getAvoidUnitIdList()));
}
// 处理专家层级
@@ -357,7 +358,7 @@ public class ExpertInviteManage {
}
LambdaQueryWrapper<ExpertUserFullInfo> query = buildBaseExpertQuery();
query.notIn(ExpertUserFullInfo::getCompany, avoidRule.getAvoidUnitIdList());
query.notExists("select 1 from expert_avoid_company eac where eac.user_id = expert_user_full_info.user_id" +
query.notExists("select 1 from expert_avoid_company eac where eac.user_id = nd_expert_user_full_info.user_id" +
" and company_name in ({0})", CollUtils.joinByComma(avoidRule.getAvoidOrgIdList()));

// 处理专家层级


+ 48
- 0
pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java View File

@@ -25,6 +25,7 @@ import com.ningdatech.pmapi.meeting.entity.domain.*;
import com.ningdatech.pmapi.meeting.entity.dto.*;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.ningdatech.pmapi.meeting.entity.enumeration.ExpertInviteTypeEnum;
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingReviewTypeEnum;
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatusEnum;
import com.ningdatech.pmapi.meeting.entity.req.*;
import com.ningdatech.pmapi.meeting.entity.vo.*;
@@ -35,7 +36,9 @@ import com.ningdatech.pmapi.meeting.service.*;
import com.ningdatech.pmapi.meeting.task.ExpertInviteTask;
import com.ningdatech.pmapi.meta.helper.DictionaryCache;
import com.ningdatech.pmapi.meta.helper.TagCache;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.model.vo.ProjectLibListItemVO;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import com.ningdatech.pmapi.sys.model.dto.RegionDTO;
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails;
@@ -702,4 +705,49 @@ public class MeetingManage {
return PageVo.of(page.getRecords(), page.getTotal());
}

public PageVo<ProjectLibListItemVO> optionProject(MeetingOptionProjectReq req) {
String meetingType = req.getMeetingType();
LambdaQueryWrapper<Project> query = Wrappers.lambdaQuery(Project.class);
switch (MeetingReviewTypeEnum.getByCode(meetingType)) {
case PRELIMINARY_SCHEME_REVIEW:
buildOptionProjectQuery(query, meetingType, ProjectStatusEnum.PRE_APPLYING);
break;
case CONSTRUCTION_SCHEME_REVIEW:
buildOptionProjectQuery(query, meetingType, ProjectStatusEnum.SCHEME_UNDER_REVIEW);
break;
case ACCEPTANCE_SCHEME_REVIEW:
query.eq(Project::getStatus, ProjectStatusEnum.FINAL_ACCEPTANCE_IS_UNDER_REVIEW);
break;
case DEPT_JOIN_REVIEW:
query.eq(Project::getStatus, ProjectStatusEnum.DEPARTMENT_JOINT_REVIEW);
break;
default:
return PageVo.empty();
}
Page<Project> page = projectService.page(req.page(), query);
PageVo<ProjectLibListItemVO> result = PageVo.of(null, page.getTotal());
if (result.getTotal() > 0) {
List<ProjectLibListItemVO> projects = CollUtils.convert(page.getRecords(),
w -> ProjectLibListItemVO
.builder()
.id(w.getId())
.projectName(w.getProjectName())
.declaredAmount(w.getDeclareAmount())
.projectType(w.getProjectType())
.projectYear(w.getProjectYear())
.buildOrg(w.getBuildOrgName())
.build());
result.setRecords(projects);
}
return result;
}

private void buildOptionProjectQuery(LambdaQueryWrapper<Project> query, String meetingType, ProjectStatusEnum status) {
String sql = String.format("select 1 from meeting m inner join meeting_inner_project mip on" +
" m.is_inner_project = true and m.id = mip.meeting_id and m.type = %s and m.status != 3", meetingType);
query.eq(Project::getStatus, status.getCode());
query.and(q1 -> q1.notExists(sql)).or(q2 -> q2.exists(sql + " inner join nd_expert_review ner " +
"on ner.meeting_id = m.id and ner.is_final = true and review_result in (2, 3)"));
}

}

+ 2
- 1
pmapi/src/main/java/com/ningdatech/pmapi/meeting/task/ExpertInviteTask.java View File

@@ -87,7 +87,8 @@ public class ExpertInviteTask {
}

private CacheHashKey getCacheKey(Long meetingId) {
return new CacheHashKey(MEETING_ID_INVITE_RANDOM, meetingId, EXPIRE_TIME);
String meetingIdStr = meetingId == null ? null : meetingId.toString();
return new CacheHashKey(MEETING_ID_INVITE_RANDOM, meetingIdStr, EXPIRE_TIME);
}

@PostConstruct


+ 9
- 2
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/vo/ProjectLibListItemVO.java View File

@@ -4,7 +4,9 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectTypeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Tolerate;

import java.math.BigDecimal;
import java.time.LocalDateTime;
@@ -20,9 +22,14 @@ import java.util.Optional;
* @since 15:13 2023/2/1
*/
@Data
@Builder
@ApiModel("项目库列表视图")
public class ProjectLibListItemVO {

@Tolerate
public ProjectLibListItemVO() {
}

@ApiModelProperty("项目ID")
private Long id;

@@ -67,8 +74,8 @@ public class ProjectLibListItemVO {

private String projectTypeName;

public String getProjectTypeName(){
if(Objects.nonNull(this.projectType)){
public String getProjectTypeName() {
if (Objects.nonNull(this.projectType)) {
Optional.ofNullable(ProjectTypeEnum.getDesc(this.projectType))
.ifPresent(desc -> this.projectTypeName = desc);
}


+ 4
- 2
pmapi/src/main/java/com/ningdatech/pmapi/sms/manage/SmsManage.java View File

@@ -23,6 +23,7 @@ import org.springframework.util.Assert;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Objects;

/**
* @author liuxinxin
@@ -81,8 +82,9 @@ public class SmsManage {

cachePlusOps.set(new CacheKey(cacheKey, Duration.ofMinutes(verificationCodeTypeEnum.getExpireTime())), cache);
String limitKey = SmsRedisKeyUtils.smsSendLimitKey(verificationCodeTypeEnum, request.getMobile());
if (StringUtils.isNotBlank(cachePlusOps.get(limitKey))) {
long limitCount = cachePlusOps.incr(new CacheKey(limitKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())));
if (Objects.nonNull(cachePlusOps.get(limitKey))) {
Integer limitCount = cachePlusOps.get(limitKey);
cachePlusOps.set(new CacheKey(limitKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())), limitCount++);
// 超出单日发送次数之后直接锁定
if (limitCount >= verificationCodeTypeEnum.getSendTimesByDay().longValue()) {
cachePlusOps.set(new CacheKey(lockKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())), request.getMobile());


+ 2
- 2
pmapi/src/main/java/com/ningdatech/pmapi/sms/model/po/ReqVerificationCodePO.java View File

@@ -19,8 +19,8 @@ public class ReqVerificationCodePO implements Serializable {
@NotBlank(message = "手机号不能为空")
private String mobile;

@ApiModelProperty(value = "短信类型", allowableValues = "LOGIN,RECOMMENDATION_PROOF_FILE_SUBMIT")
@ApiModelProperty(value = "短信类型", allowableValues = "LOGIN")
@NotBlank(message = "短信类型不能为空")
private String verificationType;

}
}

+ 29
- 0
pmapi/src/main/java/com/ningdatech/pmapi/sms/task/YxtPollingTask.java View File

@@ -0,0 +1,29 @@
package com.ningdatech.pmapi.sms.task;

import com.ningdatech.yxt.client.YxtContext;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
* @author liuxinxin
* @date 2022/8/9 下午3:58
* 音信通定时检查电话结果
*/
@Component
@RequiredArgsConstructor
public class YxtPollingTask {


private final YxtContext yxtContext;

/**
* 校验音信通结果数据
* 每5分钟执行一次
*/
@Scheduled(cron = "0 */1 * * * ?")
// @Scheduled(cron = "${cron-expression.sms-msg-result-check-cron}")
public void smsMsgResultCheck() {
yxtContext.smsMsgResultCheck();
}
}

+ 5
- 3
pmapi/src/main/java/com/ningdatech/pmapi/sms/utils/SmsRedisKeyUtils.java View File

@@ -16,20 +16,22 @@ public class SmsRedisKeyUtils {
private SmsRedisKeyUtils() {
}

private static final String PROJECT_NAME = "ls_pm:";

private static final String SMS_CODE_VERIFY_PREFIX = "sms:verify:";
private static final String SMS_SEND_LIMIT = "sms:limit:";
private static final String SMS_SEND_LOCK = "sms:lock:";

public static String smsCodeVerifyKey(VerificationCodeType type, String mobile) {
return SMS_CODE_VERIFY_PREFIX + StrPool.COLON + type.name() + StrPool.COLON + mobile;
return PROJECT_NAME + SMS_CODE_VERIFY_PREFIX + StrPool.COLON + type.name() + StrPool.COLON + mobile;
}

public static String smsSendLimitKey(VerificationCodeType type, String mobile) {
return SMS_SEND_LIMIT + StrPool.COLON + type.name() + StrPool.COLON + mobile;
return PROJECT_NAME + SMS_SEND_LIMIT + StrPool.COLON + type.name() + StrPool.COLON + mobile;
}

public static String smsSendLockKey(VerificationCodeType type, String mobile) {
return SMS_SEND_LOCK + StrPool.COLON + type.name() + StrPool.COLON + mobile;
return PROJECT_NAME + SMS_SEND_LOCK + StrPool.COLON + type.name() + StrPool.COLON + mobile;
}

}

+ 7
- 0
pmapi/src/main/java/com/ningdatech/pmapi/user/controller/UserAuthController.java View File

@@ -81,4 +81,11 @@ public class UserAuthController {
response.getWriter().write(objectMapper.writeValueAsString(BizConst.UNAUTHENTICATED));
}

@PostMapping(value = "/agent-login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ApiOperation(value = "代登陆")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "账号", required = true, paramType = "form", dataType = "String")})
public void agentLogin(@RequestParam(value = "userId", required = true) String userId) {
// 不实现任何内容,只是为了出api文档
}
}

+ 0
- 6
pmapi/src/main/java/com/ningdatech/pmapi/user/controller/UserInfoController.java View File

@@ -59,10 +59,4 @@ public class UserInfoController {
return userInfoManage.currentUserInfo();
}

@ApiOperation(value = "代登陆", notes = "代登陆")
@PostMapping("/generation-login")
public void generationLogin(@Valid @RequestBody ReqGenerationLoginPO reqGenerationLoginPO, HttpServletRequest httpServletRequest) {
userInfoManage.generationLogin(reqGenerationLoginPO);
}

}

+ 5
- 38
pmapi/src/main/java/com/ningdatech/pmapi/user/manage/UserInfoManage.java View File

@@ -17,7 +17,10 @@ import com.ningdatech.pmapi.sys.service.IRoleService;
import com.ningdatech.pmapi.sys.service.IUserRoleService;
import com.ningdatech.pmapi.user.constant.UserAvailableEnum;
import com.ningdatech.pmapi.user.entity.UserInfo;
import com.ningdatech.pmapi.user.model.po.*;
import com.ningdatech.pmapi.user.model.po.ReqUserDetailEditPO;
import com.ningdatech.pmapi.user.model.po.ReqUserDetailPO;
import com.ningdatech.pmapi.user.model.po.ReqUserDisableOrEnablePO;
import com.ningdatech.pmapi.user.model.po.ReqUserInfoListPO;
import com.ningdatech.pmapi.user.model.vo.ResUserDetailVO;
import com.ningdatech.pmapi.user.model.vo.ResUserInfoListVO;
import com.ningdatech.pmapi.user.model.vo.UserRoleVO;
@@ -25,7 +28,6 @@ import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO;
import com.ningdatech.pmapi.user.service.IUserInfoService;
import com.ningdatech.pmapi.user.util.LoginUserUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@@ -250,7 +252,7 @@ public class UserInfoManage {
}
resUserDetailVO.setUserRoleInfoList(userRoleInfoList);
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId);
if(Objects.nonNull(userFullInfo)){
if (Objects.nonNull(userFullInfo)) {
resUserDetailVO.setOrgCode(userFullInfo.getOrganizationCode());
resUserDetailVO.setOrgName(userFullInfo.getOrganizationName());
resUserDetailVO.setRegionCode(userFullInfo.getRegionCode());
@@ -258,39 +260,4 @@ public class UserInfoManage {
return resUserDetailVO;
}

public void generationLogin(ReqGenerationLoginPO reqGenerationLoginPO) {
Long userId = reqGenerationLoginPO.getUserId();
UserInfo userInfo = iUserInfoService.getById(userId);
if (Objects.isNull(userInfo)) {
throw new BizException("该员工账号处于禁用状态中,无法使用");
}
if (!UserAvailableEnum.ENABLE.name().equals(userInfo.getAvailable())) {
throw new BizException("该员工账号处于禁用状态中,无法使用");
}
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId);


// ReqGenerationLoginPO reqGenerationLoginPO
}

// public void autoLogin(Long userId){
// userDetailsService.loadUserByUsername(userId + UserDeatilsServiceConstant.USER_DETAILS_SERVICE_SEPARATOR + LoginTypeEnum.USERNAME_PASSWORD_LOGIN.name());
//
// CredentialAuthToken token = new CredentialAuthToken(email, password);
// try {
// token.setDetails(new WebAuthenticationDetails(httpServletRequest));
// UsernamePasswordAuthToken authenticatedUser = (UsernamePasswordAuthToken)usernamePasswordAuthSecurityConfig
// .getAuthenticationManager().authenticate(token);
// SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
// httpServletRequest.getSession().setAttribute(
// HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
// String sessionId = httpServletRequest.getSession().getId();
// putSessionIdToCache(LoginUserUtil.getUserId(), sessionId);
// } catch (
// AuthenticationException e) {
// throw new RuntimeException("autoLogIn Authentication failed!", e);
// }
// }


}

+ 5
- 0
pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/AuthProperties.java View File

@@ -29,6 +29,11 @@ public class AuthProperties {

private String passwordLoginUrl;

/**
* 代登陆接口
*/
private String agentLoginUrl;

private String logoutUrl;

private List<String> ignoreAuthUrls;


+ 6
- 2
pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/WebSecurityConfig.java View File

@@ -4,8 +4,9 @@ import com.ningdatech.basic.util.NdJsonUtil;
import com.ningdatech.basic.util.StrPool;
import com.ningdatech.pmapi.common.constant.BizConst;
import com.ningdatech.pmapi.common.constant.CommonConst;
import com.ningdatech.pmapi.user.security.auth.handler.DefaultExpiredSessionStrategy;
import com.ningdatech.pmapi.user.security.auth.agent.AgentAuthSecurityConfig;
import com.ningdatech.pmapi.user.security.auth.credential.CredentialAuthSecurityConfig;
import com.ningdatech.pmapi.user.security.auth.handler.DefaultExpiredSessionStrategy;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
@@ -31,13 +32,16 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final CredentialAuthSecurityConfig credentialAuthSecurityConfig;
private final LogoutSuccessHandler logoutSuccessHandler;
private final DefaultExpiredSessionStrategy defaultExpiredSessionStrategy;
private final AgentAuthSecurityConfig agentAuthSecurityConfig;

public WebSecurityConfig(AuthProperties authProperties,
CredentialAuthSecurityConfig credentialAuthSecurityConfig,
AgentAuthSecurityConfig agentAuthSecurityConfig,
@Qualifier(value = "defaultLogoutSuccessHandler") LogoutSuccessHandler logoutSuccessHandler,
DefaultExpiredSessionStrategy defaultExpiredSessionStrategy) {
this.authProperties = authProperties;
this.credentialAuthSecurityConfig = credentialAuthSecurityConfig;
this.agentAuthSecurityConfig = agentAuthSecurityConfig;
this.logoutSuccessHandler = logoutSuccessHandler;
this.defaultExpiredSessionStrategy = defaultExpiredSessionStrategy;
}
@@ -47,7 +51,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
assemblerPreAuthUrls(http);
http.formLogin()
.loginPage(authProperties.getAuthRequireUrl())
.and().apply(credentialAuthSecurityConfig)
.and().apply(credentialAuthSecurityConfig).and().apply(agentAuthSecurityConfig)
.and()
.authorizeRequests().antMatchers(authProperties.getIgnoreAuthUrlsArray()).permitAll().anyRequest()
.authenticated().and()


+ 74
- 0
pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/agent/AgentAuthFilter.java View File

@@ -0,0 +1,74 @@
package com.ningdatech.pmapi.user.security.auth.agent;

import com.ningdatech.basic.exception.BizException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
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;

/**
* @Author LiuXinXin
* @Date 2020/8/3 8:46 下午
* @Version 1.0
**/
public class AgentAuthFilter extends AbstractAuthenticationProcessingFilter {

private boolean postOnly = true;

private static final String USER_ID_PARAMETER = "userId";

// ~ Constructors
// ===================================================================================================

public AgentAuthFilter(String processingUrl) {
super(new AntPathRequestMatcher(processingUrl, HttpMethod.POST.name()));
}

// ~ Methods
// ========================================================================================================

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) {
throw new AuthenticationServiceException("请求方法错误");
}
String userId = request.getParameter(USER_ID_PARAMETER);
if (StringUtils.isBlank(userId)) {
throw new BadCredentialsException("用户id 不能为空");
}

userId = trim(userId);
try {
AgentAuthToken authRequest = new AgentAuthToken(userId, userId);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
} catch (AuthenticationException e) {
throw new BadCredentialsException("账号或密码错误");
} catch (BizException e) {
throw new BadCredentialsException(e.getMessage());
} catch (Exception e) {
throw new InternalAuthenticationServiceException("授权失败:", e);
}
}

protected void setDetails(HttpServletRequest request, AgentAuthToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}

private String trim(String trimStr) {
if (StringUtils.isNotBlank(trimStr)) {
return trimStr.trim();
}
return null;
}
}

+ 40
- 0
pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/agent/AgentAuthProvider.java View File

@@ -0,0 +1,40 @@
package com.ningdatech.pmapi.user.security.auth.agent;

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

/**
* @Author LiuXinXin
* @Date 2020/8/3 8:55 下午
* @Version 1.0
**/
public class AgentAuthProvider implements AuthenticationProvider {

private UserDetailsService userDetailsService;

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (!(authentication instanceof AgentAuthToken)) {
throw new RuntimeException("CustomAuthProvider 只支持 CustomAuthToken");
}
AgentAuthToken authenticationToken = (AgentAuthToken) authentication;
String principal = (String) authenticationToken.getPrincipal();

UserDetails user = userDetailsService.loadUserByUsername(principal);
// 将用户定义的user放入token中,这样可以在session中查询到所有自定义的用户信息
return new AgentAuthToken(user, user.getPassword(), user.getAuthorities());
}

@Override
public boolean supports(Class<?> authentication) {
return AgentAuthToken.class.isAssignableFrom(authentication);
}

public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}

}

+ 55
- 0
pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/agent/AgentAuthSecurityConfig.java View File

@@ -0,0 +1,55 @@
package com.ningdatech.pmapi.user.security.auth.agent;

import com.ningdatech.pmapi.user.security.auth.AuthProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;

/**
* 账号密码登陆的认证配置
*/
@Component
public class AgentAuthSecurityConfig
extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

@Autowired
@Qualifier(value = "defaultLoginSuccessHandler")
protected AuthenticationSuccessHandler defaultLoginSuccessHandler;

@Autowired
@Qualifier(value = "defaultLoginFailureHandler")
protected AuthenticationFailureHandler defaultLoginFailureHandler;

@Autowired
@Qualifier(value = "agentLoginUserDetailService")
private UserDetailsService agentLoginUserDetailService;

@Autowired
private AuthProperties authProperties;

private AuthenticationManager authenticationManager;

@Override
public void configure(HttpSecurity http) throws Exception {
AgentAuthFilter agentAuthFilter =
new AgentAuthFilter(authProperties.getAgentLoginUrl());
authenticationManager = http.getSharedObject(AuthenticationManager.class);
agentAuthFilter.setAuthenticationManager(authenticationManager);
agentAuthFilter.setAuthenticationSuccessHandler(defaultLoginSuccessHandler);
agentAuthFilter.setAuthenticationFailureHandler(defaultLoginFailureHandler);

AgentAuthProvider authenticationProvider = new AgentAuthProvider();
authenticationProvider.setUserDetailsService(agentLoginUserDetailService);

http.authenticationProvider(authenticationProvider).addFilterAfter(agentAuthFilter,
UsernamePasswordAuthenticationFilter.class);
}
}

+ 76
- 0
pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/agent/AgentAuthToken.java View File

@@ -0,0 +1,76 @@
package com.ningdatech.pmapi.user.security.auth.agent;

import com.ningdatech.pmapi.user.constant.LoginTypeEnum;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;

import java.util.Collection;

/**
* @Author LiuXinXin
* @Date 2020/8/3 8:52 下午
* @Version 1.0
**/
public class AgentAuthToken extends AbstractAuthenticationToken {

private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

private final Object principal;

private final 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 AgentAuthToken(String principal, String 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 authorities
*/
public AgentAuthToken(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();
}

}

+ 48
- 0
pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/agent/AgentLoginUserDetailService.java View File

@@ -0,0 +1,48 @@
package com.ningdatech.pmapi.user.security.auth.agent;


import com.ningdatech.pmapi.user.manage.UserAuthLoginManage;
import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO;
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
* @author LiuXinXin
* @date 2022/9/30 上午9:49
*/

@Service("agentLoginUserDetailService")
@RequiredArgsConstructor
public class AgentLoginUserDetailService implements UserDetailsService {

private final UserAuthLoginManage userAuthLoginManage;

@Override
public UserInfoDetails loadUserByUsername(String username) throws UsernameNotFoundException {

final Long userId = Long.parseLong(username);

UserFullInfoDTO userFullInfoDTO = userAuthLoginManage.getUserFullInfo(userId);

if (Objects.isNull(userFullInfoDTO)) {
throw new UsernameNotFoundException(String.format("%s user not exist", username));
}
UserInfoDetails userInfoDetails = new UserInfoDetails();
userInfoDetails.setUserId(userFullInfoDTO.getUserId());
userInfoDetails.setUsername(userFullInfoDTO.getUsername());
userInfoDetails.setRealName(userFullInfoDTO.getRealName());
userInfoDetails.setUserRoleList(userFullInfoDTO.getUserRoleList());
userInfoDetails.setRegionCode(userFullInfoDTO.getRegionCode());
userInfoDetails.setIdentifier(userFullInfoDTO.getIdentifier());
userInfoDetails.setPassword(userFullInfoDTO.getCredential());

userInfoDetails.setOrganizationCode(userFullInfoDTO.getOrganizationCode());
userInfoDetails.setOrganizationName(userFullInfoDTO.getOrganizationName());
return userInfoDetails;
}
}

+ 1
- 1
pmapi/src/main/java/com/ningdatech/pmapi/user/security/auth/handler/DefaultLoginSuccessHandler.java View File

@@ -29,7 +29,7 @@ public class DefaultLoginSuccessHandler extends SavedRequestAwareAuthenticationS
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException {
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.getWriter().write(objectMapper.writeValueAsString(ApiResponse.ofSuccess()));
response.getWriter().write(objectMapper.writeValueAsString(ApiResponse.ofMessage(ApiResponse.SUCCESS_MSG)));
}

}

+ 1
- 0
pmapi/src/main/resources/security/auth-dev.yml View File

@@ -3,6 +3,7 @@ security:
auth-require-url: /api/v1/user/auth/auth-require
invalid-session-url: /api/v1/user/auth/invalid-session
password-login-url: /api/v1/user/auth/login
agent-login-url: /api/v1/user/auth/agent-login
logout-url: /api/v1/user/auth/logout
ignore-auth-urls:
- /v2/api-docs


Loading…
Cancel
Save