본문 바로가기
카테고리 없음

TIL (2023/09/06) Wednesday

by 0to1ton 2023. 9. 6.
  • Lv3 과제 시작 
  • Joi에 error message를 다양하게 변경해서 출력하는 법을 공부하고 익혔음.
/* 사용자 회원가입 API Logic */
/* Joi유효성 검사 */
// - 닉네임은 `최소 3자 이상, 알파벳 대소문자(a~z, A~Z), 숫자(0~9)`로 구성하기
// - 비밀번호는 `최소 4자 이상이며, 닉네임과 같은 값이 포함된 경우 회원가입에 실패`로 만들기
const nickname_pattern = /^[a-z|A-Z|0-9]+$/;
const postUserSchema = joi.object({
  nickname: joi.string().min(3).pattern(new RegExp(nickname_pattern)).required().messages({
    'string.pattern.base': '닉네임은 알파벳 대소문자(a~z, A~Z), 숫자(0~9)`로 구성되어야합니다.',
    'string.min': '닉네임은 최소 3자 이상이여야합니다.',
  }),
  password: joi
    .string()
    .min(4)
    .custom((value, helpers) => {
      if (value.includes(helpers.state.ancestors[0].nickname)) {
        return helpers.error('password.nicknameInPassword');
      }
      return value;
    })
    .required()
    .messages({
      'password.nicknameInPassword': '비밀번호에 닉네임이 포함되어 있습니다.',
      'string.min': '비밀번호는 최소 4자 이상이여야합니다.',
    }),
  confirm: joi.string().valid(joi.ref('password')).required().messages({
    'any.only': '비밀번호와 비밀번호 확인이 일치하지 않습니다.',
  }),
});

/* 회원가입 */
// - 닉네임, 비밀번호, 비밀번호 확인을 **request**에서 전달받기
// - 닉네임은 `최소 3자 이상, 알파벳 대소문자(a~z, A~Z), 숫자(0~9)`로 구성하기
// - 비밀번호는 `최소 4자 이상이며, 닉네임과 같은 값이 포함된 경우 회원가입에 실패`로 만들기
// - 비밀번호 확인은 비밀번호와 정확하게 일치하기
// {  "nickname": "Developer",  "password": "1234",  "confirm": "1234"}
// - 데이터베이스에 존재하는 닉네임을 입력한 채 회원가입 버튼을 누른 경우 "중복된 닉네임입니다." 라는 에러메세지를 **response**에 포함하기
// # 201 회원가입에 성공한 경우
// {  "message": "회원 가입에 성공하였습니다."}
router.post('/signup', async (req, res, next) => {
  try {
    const { nickname, password, confirm } = req.body;

    // req.body에 nickname, password, confirm이 없는 경우
    if (!nickname || !password || !confirm) {
      res.status(400).json({ message: '데이터 형식이 올바르지 않습니다.' });
    }

    // 닉네임, 패스워드 validate using joi
    // const value = await postUserSchema.validateAsync(req.body);
    const { error, value } = postUserSchema.validate(req.body);

    // Joi 유효성 검사 실패시 실패한 메시지 전달
    // *TODO*: message를 한국어로 전달하기 //
    if (error) {
      console.log(error);
      res.status(400).json({ error: error.details[0].message });
    } else {
      if (!value) {
        return res.status(400).json({ errorMessage: '검증할 데이터가 존재하지 않습니다.' });
      }

      // 회원가입 로직
      // 이미 존재하는 유저인지 확인
      const isExistUser = await prisma.users.findFirst({
        where: { nickname },
      });
      if (isExistUser) {
        return res.status(409).json({ message: '중복된 닉네임입니다.' });
      } else {
        // bcrypt를 이용한 암호화
        const hashedPassword = await bcrypt.hash(password, 10);
        // 회원가입 성공 시 Users 테이블에 사용자 생성
        const createdUser = await prisma.users.create({
          data: {
            nickname,
            password: hashedPassword,
          },
        });

        // 회원가입 성공 시 UserInfos 테이블에 사용자 정보를 생성
        const createdUserInfo = await prisma.userInfos.create({
          data: {
            UserId: createdUser.userId,
          },
        });
        return res.status(201).json({ message: '회원 가입에 성공하였습니다.' });
      }
    }
  } catch (error) {
    console.error(error);
    next(error);
  }
});