Search in sources :

Example 1 with StatusFailException

use of top.hcode.hoj.common.exception.StatusFailException in project HOJ by HimitZH.

the class AccountManager method getUserCalendarHeatmap.

/**
 * @param uid
 * @param username
 * @return
 * @Description 获取用户最近一年的提交热力图数据
 */
public UserCalendarHeatmapVo getUserCalendarHeatmap(String uid, String username) throws StatusFailException {
    org.apache.shiro.session.Session session = SecurityUtils.getSubject().getSession();
    UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
    if (StringUtils.isEmpty(uid) && StringUtils.isEmpty(username)) {
        if (userRolesVo != null) {
            uid = userRolesVo.getUid();
        } else {
            throw new StatusFailException("请求参数错误:uid和username不能都为空!");
        }
    }
    UserCalendarHeatmapVo userCalendarHeatmapVo = new UserCalendarHeatmapVo();
    userCalendarHeatmapVo.setEndDate(DateUtil.format(new Date(), "yyyy-MM-dd"));
    List<Judge> lastYearUserJudgeList = userRecordEntityService.getLastYearUserJudgeList(uid, username);
    if (CollectionUtils.isEmpty(lastYearUserJudgeList)) {
        userCalendarHeatmapVo.setDataList(new ArrayList<>());
        return userCalendarHeatmapVo;
    }
    HashMap<String, Integer> tmpRecordMap = new HashMap<>();
    for (Judge judge : lastYearUserJudgeList) {
        Date submitTime = judge.getSubmitTime();
        String dateStr = DateUtil.format(submitTime, "yyyy-MM-dd");
        tmpRecordMap.merge(dateStr, 1, Integer::sum);
    }
    List<HashMap<String, Object>> dataList = new ArrayList<>();
    for (Map.Entry<String, Integer> record : tmpRecordMap.entrySet()) {
        HashMap<String, Object> tmp = new HashMap<>(2);
        tmp.put("date", record.getKey());
        tmp.put("count", record.getValue());
        dataList.add(tmp);
    }
    userCalendarHeatmapVo.setDataList(dataList);
    return userCalendarHeatmapVo;
}
Also used : StatusFailException(top.hcode.hoj.common.exception.StatusFailException) Judge(top.hcode.hoj.pojo.entity.judge.Judge)

Example 2 with StatusFailException

use of top.hcode.hoj.common.exception.StatusFailException in project HOJ by HimitZH.

the class AccountManager method changePassword.

/**
 * @MethodName changePassword
 * @Description 修改密码的操作,连续半小时内修改密码错误5次,则需要半个小时后才可以再次尝试修改密码
 * @Return
 * @Since 2021/1/8
 */
public ChangeAccountVo changePassword(ChangePasswordDto changePasswordDto) throws StatusSystemErrorException, StatusFailException {
    String oldPassword = changePasswordDto.getOldPassword();
    String newPassword = changePasswordDto.getNewPassword();
    // 数据可用性判断
    if (StringUtils.isEmpty(oldPassword) || StringUtils.isEmpty(newPassword)) {
        throw new StatusFailException("错误:原始密码或新密码不能为空!");
    }
    if (newPassword.length() < 6 || newPassword.length() > 20) {
        throw new StatusFailException("新密码长度应该为6~20位!");
    }
    // 获取当前登录的用户
    org.apache.shiro.session.Session session = SecurityUtils.getSubject().getSession();
    UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
    // 如果已经被锁定半小时不能修改
    String lockKey = Constants.Account.CODE_CHANGE_PASSWORD_LOCK + userRolesVo.getUid();
    // 统计失败的key
    String countKey = Constants.Account.CODE_CHANGE_PASSWORD_FAIL + userRolesVo.getUid();
    ChangeAccountVo resp = new ChangeAccountVo();
    if (redisUtils.hasKey(lockKey)) {
        long expire = redisUtils.getExpire(lockKey);
        Date now = new Date();
        long minute = expire / 60;
        long second = expire % 60;
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        resp.setCode(403);
        Date afterDate = new Date(now.getTime() + expire * 1000);
        String msg = "由于您多次修改密码失败,修改密码功能已锁定,请在" + minute + "分" + second + "秒后(" + formatter.format(afterDate) + ")再进行尝试!";
        resp.setMsg(msg);
        return resp;
    }
    // 与当前登录用户的密码进行比较判断
    if (userRolesVo.getPassword().equals(SecureUtil.md5(oldPassword))) {
        // 如果相同,则进行修改密码操作
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
        // 数据库用户密码全部用md5加密
        updateWrapper.set("password", SecureUtil.md5(newPassword)).eq("uuid", userRolesVo.getUid());
        boolean isOk = userInfoEntityService.update(updateWrapper);
        if (isOk) {
            resp.setCode(200);
            resp.setMsg("修改密码成功!您将于5秒钟后退出进行重新登录操作!");
            // 清空记录
            redisUtils.del(countKey);
            // 更新session
            userRolesVo.setPassword(SecureUtil.md5(newPassword));
            session.setAttribute("userInfo", userRolesVo);
            return resp;
        } else {
            throw new StatusSystemErrorException("系统错误:修改密码失败!");
        }
    } else {
        // 如果不同,则进行记录,当失败次数达到5次,半个小时后才可重试
        Integer count = (Integer) redisUtils.get(countKey);
        if (count == null) {
            // 三十分钟不尝试,该限制会自动清空消失
            redisUtils.set(countKey, 1, 60 * 30);
            count = 0;
        } else if (count < 5) {
            redisUtils.incr(countKey, 1);
        }
        count++;
        if (count == 5) {
            // 清空统计
            redisUtils.del(countKey);
            // 设置锁定更改
            redisUtils.set(lockKey, "lock", 60 * 30);
        }
        resp.setCode(400);
        resp.setMsg("原始密码错误!您已累计修改密码失败" + count + "次...");
        return resp;
    }
}
Also used : UpdateWrapper(com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper) StatusFailException(top.hcode.hoj.common.exception.StatusFailException) StatusSystemErrorException(top.hcode.hoj.common.exception.StatusSystemErrorException) SimpleDateFormat(java.text.SimpleDateFormat)

Example 3 with StatusFailException

use of top.hcode.hoj.common.exception.StatusFailException in project HOJ by HimitZH.

the class AccountManager method changeEmail.

/**
 * @MethodName changeEmail
 * @Description 修改邮箱的操作,连续半小时内密码错误5次,则需要半个小时后才可以再次尝试修改
 * @Return
 * @Since 2021/1/9
 */
public ChangeAccountVo changeEmail(ChangeEmailDto changeEmailDto) throws StatusSystemErrorException, StatusFailException {
    String password = changeEmailDto.getPassword();
    String newEmail = changeEmailDto.getNewEmail();
    // 数据可用性判断
    if (StringUtils.isEmpty(password) || StringUtils.isEmpty(newEmail)) {
        throw new StatusFailException("错误:密码或新邮箱不能为空!");
    }
    if (!Validator.isEmail(newEmail)) {
        throw new StatusFailException("邮箱格式错误!");
    }
    // 获取当前登录的用户
    org.apache.shiro.session.Session session = SecurityUtils.getSubject().getSession();
    UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
    // 如果已经被锁定半小时不能修改
    String lockKey = Constants.Account.CODE_CHANGE_EMAIL_LOCK + userRolesVo.getUid();
    // 统计失败的key
    String countKey = Constants.Account.CODE_CHANGE_EMAIL_FAIL + userRolesVo.getUid();
    ChangeAccountVo resp = new ChangeAccountVo();
    if (redisUtils.hasKey(lockKey)) {
        long expire = redisUtils.getExpire(lockKey);
        Date now = new Date();
        long minute = expire / 60;
        long second = expire % 60;
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        resp.setCode(403);
        Date afterDate = new Date(now.getTime() + expire * 1000);
        String msg = "由于您多次修改邮箱失败,修改邮箱功能已锁定,请在" + minute + "分" + second + "秒后(" + formatter.format(afterDate) + ")再进行尝试!";
        resp.setMsg(msg);
        return resp;
    }
    // 与当前登录用户的密码进行比较判断
    if (userRolesVo.getPassword().equals(SecureUtil.md5(password))) {
        // 如果相同,则进行修改操作
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("email", newEmail).eq("uuid", userRolesVo.getUid());
        boolean isOk = userInfoEntityService.update(updateWrapper);
        if (isOk) {
            UserInfoVo userInfoVo = new UserInfoVo();
            BeanUtil.copyProperties(userRolesVo, userInfoVo, "roles");
            userInfoVo.setRoleList(userRolesVo.getRoles().stream().map(Role::getRole).collect(Collectors.toList()));
            resp.setCode(200);
            resp.setMsg("修改邮箱成功!");
            resp.setUserInfo(userInfoVo);
            // 清空记录
            redisUtils.del(countKey);
            // 更新session
            userRolesVo.setEmail(newEmail);
            session.setAttribute("userInfo", userRolesVo);
            return resp;
        } else {
            throw new StatusSystemErrorException("系统错误:修改邮箱失败!");
        }
    } else {
        // 如果不同,则进行记录,当失败次数达到5次,半个小时后才可重试
        Integer count = (Integer) redisUtils.get(countKey);
        if (count == null) {
            // 三十分钟不尝试,该限制会自动清空消失
            redisUtils.set(countKey, 1, 60 * 30);
            count = 0;
        } else if (count < 5) {
            redisUtils.incr(countKey, 1);
        }
        count++;
        if (count == 5) {
            // 清空统计
            redisUtils.del(countKey);
            // 设置锁定更改
            redisUtils.set(lockKey, "lock", 60 * 30);
        }
        resp.setCode(400);
        resp.setMsg("密码错误!您已累计修改邮箱失败" + count + "次...");
        return resp;
    }
}
Also used : UpdateWrapper(com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper) StatusFailException(top.hcode.hoj.common.exception.StatusFailException) StatusSystemErrorException(top.hcode.hoj.common.exception.StatusSystemErrorException) SimpleDateFormat(java.text.SimpleDateFormat)

Example 4 with StatusFailException

use of top.hcode.hoj.common.exception.StatusFailException in project HOJ by HimitZH.

the class BeforeDispatchInitManager method initTrainingSubmission.

@Transactional(rollbackFor = Exception.class)
public void initTrainingSubmission(Long tid, String displayId, UserRolesVo userRolesVo, Judge judge) throws StatusForbiddenException, StatusFailException, StatusAccessDeniedException {
    Training training = trainingEntityService.getById(tid);
    if (training == null || !training.getStatus()) {
        throw new StatusFailException("该训练不存在或不允许显示!");
    }
    trainingValidator.validateTrainingAuth(training, userRolesVo);
    // 查询获取对应的pid和cpid
    QueryWrapper<TrainingProblem> trainingProblemQueryWrapper = new QueryWrapper<>();
    trainingProblemQueryWrapper.eq("tid", tid).eq("display_id", displayId);
    TrainingProblem trainingProblem = trainingProblemEntityService.getOne(trainingProblemQueryWrapper);
    judge.setPid(trainingProblem.getPid());
    Problem problem = problemEntityService.getById(trainingProblem.getPid());
    if (problem.getAuth() == 2) {
        throw new StatusForbiddenException("错误!当前题目不可提交!");
    }
    judge.setDisplayPid(problem.getProblemId()).setGid(training.getGid());
    // 将新提交数据插入数据库
    judgeEntityService.save(judge);
    // 非私有训练不记录
    if (!training.getAuth().equals(Constants.Training.AUTH_PRIVATE.getValue())) {
        return;
    }
    TrainingRecord trainingRecord = new TrainingRecord();
    trainingRecord.setPid(problem.getId()).setTid(tid).setTpid(trainingProblem.getId()).setSubmitId(judge.getSubmitId()).setUid(userRolesVo.getUid());
    trainingRecordEntityService.save(trainingRecord);
}
Also used : Training(top.hcode.hoj.pojo.entity.training.Training) TrainingRecord(top.hcode.hoj.pojo.entity.training.TrainingRecord) StatusForbiddenException(top.hcode.hoj.common.exception.StatusForbiddenException) QueryWrapper(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper) StatusFailException(top.hcode.hoj.common.exception.StatusFailException) TrainingProblem(top.hcode.hoj.pojo.entity.training.TrainingProblem) Problem(top.hcode.hoj.pojo.entity.problem.Problem) TrainingProblem(top.hcode.hoj.pojo.entity.training.TrainingProblem) ContestProblem(top.hcode.hoj.pojo.entity.contest.ContestProblem) Transactional(org.springframework.transaction.annotation.Transactional)

Example 5 with StatusFailException

use of top.hcode.hoj.common.exception.StatusFailException in project HOJ by HimitZH.

the class CommentManager method deleteComment.

@Transactional(rollbackFor = Exception.class)
public void deleteComment(Comment comment) throws StatusForbiddenException, StatusFailException, AccessException {
    // 获取当前登录的用户
    Session session = SecurityUtils.getSubject().getSession();
    UserRolesVo userRolesVo = (UserRolesVo) session.getAttribute("userInfo");
    boolean isRoot = SecurityUtils.getSubject().hasRole("root");
    boolean isProblemAdmin = SecurityUtils.getSubject().hasRole("problem_admin");
    boolean isAdmin = SecurityUtils.getSubject().hasRole("admin");
    // 如果不是评论本人 或者不是管理员 无权限删除该评论
    Long cid = comment.getCid();
    if (cid == null) {
        QueryWrapper<Discussion> discussionQueryWrapper = new QueryWrapper<>();
        discussionQueryWrapper.select("id", "gid").eq("id", comment.getDid());
        Discussion discussion = discussionEntityService.getOne(discussionQueryWrapper);
        Long gid = discussion.getGid();
        if (gid == null) {
            accessValidator.validateAccess(HOJAccessEnum.PUBLIC_DISCUSSION);
            if (!comment.getFromUid().equals(userRolesVo.getUid()) && !isRoot && !isProblemAdmin && !isAdmin) {
                throw new StatusForbiddenException("无权删除该评论");
            }
        } else {
            accessValidator.validateAccess(HOJAccessEnum.GROUP_DISCUSSION);
            if (!groupValidator.isGroupAdmin(userRolesVo.getUid(), gid) && !comment.getFromUid().equals(userRolesVo.getUid()) && !isRoot) {
                throw new StatusForbiddenException("无权删除该评论");
            }
        }
    } else {
        accessValidator.validateAccess(HOJAccessEnum.CONTEST_COMMENT);
        Contest contest = contestEntityService.getById(cid);
        Long gid = contest.getGid();
        if (!comment.getFromUid().equals(userRolesVo.getUid()) && !isRoot && !contest.getUid().equals(userRolesVo.getUid()) && !(contest.getIsGroup() && groupValidator.isGroupRoot(userRolesVo.getUid(), gid))) {
            throw new StatusForbiddenException("无权删除该评论");
        }
    }
    // 获取需要删除该评论的回复数
    int replyNum = replyEntityService.count(new QueryWrapper<Reply>().eq("comment_id", comment.getId()));
    // 删除该数据 包括关联外键的reply表数据
    boolean isDeleteComment = commentEntityService.removeById(comment.getId());
    // 同时需要删除该评论的回复表数据
    replyEntityService.remove(new UpdateWrapper<Reply>().eq("comment_id", comment.getId()));
    if (isDeleteComment) {
        // 如果是讨论区的回复,删除成功需要减少统计该讨论的回复数
        if (comment.getDid() != null) {
            UpdateWrapper<Discussion> discussionUpdateWrapper = new UpdateWrapper<>();
            discussionUpdateWrapper.eq("id", comment.getDid()).setSql("comment_num=comment_num-" + (replyNum + 1));
            discussionEntityService.update(discussionUpdateWrapper);
        }
    } else {
        throw new StatusFailException("删除失败,请重新尝试");
    }
}
Also used : StatusForbiddenException(top.hcode.hoj.common.exception.StatusForbiddenException) UpdateWrapper(com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper) QueryWrapper(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper) StatusFailException(top.hcode.hoj.common.exception.StatusFailException) Contest(top.hcode.hoj.pojo.entity.contest.Contest) Discussion(top.hcode.hoj.pojo.entity.discussion.Discussion) Session(org.apache.shiro.session.Session) Transactional(org.springframework.transaction.annotation.Transactional)

Aggregations

StatusFailException (top.hcode.hoj.common.exception.StatusFailException)116 Session (org.apache.shiro.session.Session)89 StatusForbiddenException (top.hcode.hoj.common.exception.StatusForbiddenException)83 UserRolesVo (top.hcode.hoj.pojo.vo.UserRolesVo)78 QueryWrapper (com.baomidou.mybatisplus.core.conditions.query.QueryWrapper)60 Group (top.hcode.hoj.pojo.entity.group.Group)42 StatusNotFoundException (top.hcode.hoj.common.exception.StatusNotFoundException)40 Transactional (org.springframework.transaction.annotation.Transactional)29 UpdateWrapper (com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper)28 Problem (top.hcode.hoj.pojo.entity.problem.Problem)26 Contest (top.hcode.hoj.pojo.entity.contest.Contest)25 ContestProblem (top.hcode.hoj.pojo.entity.contest.ContestProblem)14 StatusSystemErrorException (top.hcode.hoj.common.exception.StatusSystemErrorException)10 LinkedList (java.util.LinkedList)8 MultipartFile (org.springframework.web.multipart.MultipartFile)8 JSONObject (cn.hutool.json.JSONObject)7 GroupMember (top.hcode.hoj.pojo.entity.group.GroupMember)7 Judge (top.hcode.hoj.pojo.entity.judge.Judge)7 Training (top.hcode.hoj.pojo.entity.training.Training)7 Discussion (top.hcode.hoj.pojo.entity.discussion.Discussion)6