[0718] DRF - JS 계정관리 기능

nikevapormax·2022년 7월 18일
0

TIL

목록 보기
76/116
post-custom-banner

계정관리 기능

백앤드

class UserVerifyView(APIView):
    authentication_classes = [JWTAuthentication]

    # 계정관리 페이지 접근 권한 확인
    def post(self, request):
        correct_password = re.compile(
            "^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$")
        password_input = correct_password.match(request.data["password"])

        if request.data["username"] == "" or request.data["password"] == "":
            return Response({"message": "아이디 또는 비밀번호 값을 제대로 입력해주세요."}, status=status.HTTP_400_BAD_REQUEST)
        else:
            if password_input == None:
                return Response({"message": "비밀번호 형식에 맞게 작성해주세요."}, status=status.HTTP_400_BAD_REQUEST)
            else:
                user = authenticate(username=request.data["username"], password=request.data["password"])

                if request.user == user:
                    user = UserModel.objects.get(username=request.data["username"])
                    user_data = UserSerializer(user)

                    return Response(user_data.data, status=status.HTTP_200_OK)
                else:
                    return Response({"message": "존재하지 않는 사용자입니다."}, status=status.HTTP_404_NOT_FOUND)
  • 비밀번호 정규표현식은 회원가입을 할 때 정규표현식을 사용해 받고 있지만, 해당 기능을 사용하면서 사용자가 어떤 부분이 틀렸는지 최대한 상세히 알 수 있도록 하고 싶어 사용하였다.
  • authenticate를 사용해 현재 로그인한 사용자가 계정관리 페이지에서 입력한 아이디와 비밀번호를 가진 사용자와 일치하는지 확인하였다.
  • 만약 현재 로그인한 사용자가 인증한 사용자와 일치한다면 쿼리를 날려 데이터를 찾아 프론트로 보내주었다.
class accountUpdateSerializer(serializers.ModelSerializer):

    class Meta:
        model = UserModel
        fields = ["username", "password", "fullname", "email",
                  "phone", "birthday", "region", "join_date"]

        extra_kwargs = {
            "password": {"write_only": True},
        }

    def validate(self, data):
        correct_phone = re.compile("(010)-\d{4}-\d{4}")

        phone_input = correct_phone.match(data.get("phone", ""))

        if data.get("username"):
            if not len(data.get("username", "")) >= 6:
                raise serializers.ValidationError(
                    detail={"error": "username의 길이는 6자리 이상이어야 합니다."})

        if not data.get("email", "").endswith(EMAIL):
            raise serializers.ValidationError(
                detail={"error": "네이버, 구글, 카카오, 다음, 네이트, 아웃룩 이메일만 가입할 수 있습니다."})

        if phone_input == None:
            raise serializers.ValidationError(
                detail={"error": "전화번호는 010-0000-0000 형식으로 작성해주시기 바랍니다."})

        return data

    def update(self, instance, validated_data):
        for key, value in validated_data.items():
            if key == "password":
                instance.set_password(value)
                continue
            setattr(instance, key, value)
        instance.save()

        return instance
  • 원래는 회원가입에서 쓰던 시리얼라이저를 같이 쓸 계획이었다. 하지만 비밀번호 정규식이 적용되어 있었고, 정보 수정을 위해 지울 수는 없었다. 정규식이 없으면 비밀번호를 1234로 쳐도 회원가입이 되기 때문이다.
  • 프론트 화면에 비밀번호에 대한 요구사항이 있긴 하지만 사용자가 꼭 그 값에 따라 입력한다는 보장이 없었기 때문이다.
  • 회원정보 수정 view에는 수정할 정보를 partial=True로 받아 수정하고 싶은 값만 수정할 수 있다.
  • 그것에 맞게 새로운 시리얼라이저를 만들고 비밀번호에 대한 정규표현식을 없애주어 비밀번호 데이터가 넘어오지 않더라도 수정할 수 있도록 해주었다.

프론트앤드

// 계정관리 페이지 사용 권한 확인 // 
async function searchUser() {
  const userData = {
    username: document.getElementById("checkUsername").value,
    password: document.getElementById("checkPassword").value
  }

  const response = await fetch(`${backend_base_url}user/verification/`, {
    headers: {
      Accept: "application/json",
      'Content-type': 'application/json',
      'Authorization': 'Bearer ' + localStorage.getItem("access")
    },
    method: "POST",
    body: JSON.stringify(userData)
  })

  verification_json = await response.json()

  if (response.status == 200) {
    const popup = document.getElementById("popup")
    popup.style.visibility = "visible"

    document.getElementById("accountUsername").value = verification_json.username
    document.getElementById("accountFullname").value = verification_json.fullname
    document.getElementById("accountEmail").value = verification_json.email
    document.getElementById("accountPhone").value = verification_json.phone
    document.getElementById("accountBirthday").value = verification_json.birthday
    document.getElementById("accountRegion").value = verification_json.region
  } else {
    alert(verification_json["message"])
    const popup = document.getElementById("popup")
    popup.style.visibility = "hidden"
  }
}
  • 백앤드에서 요구하는 데이터를 찾아와 보내주었다.
  • status code를 사용해 어떤 반응을 보여주어야 하는지 설정하였다. 백앤드에서 작성한 message를 받아와 사용자에게 alert를 통해 보여주어 어떤 조치를 취해야 하는지 알려주었다.
  • response.status == 200에 있는 부분은 사용자가 권한 인증을 마치고 나면 모달을 띄워 정보 수정을 할 수 있게 하고 싶어 작성하였다. 해당 코드들로 인해 사용자가 모달을 볼 때 본인이 작성했던 정보들을 확인할 수 있다.
  • 비밀번호의 값은 제거해 주었다. 왜냐하면 백앤드에서 정보가 넘어올 때 해싱된 값이 넘어오고 해당 부분을 수정하지 않고 넘기면 404 에러가 떴기 때문이다.
// 계정확인 페이지 : 수정된 데이터 송신 //
async function changeAccount() {
  let changedData

  if (document.getElementById("accountPassword").value) {
    changedData = {
      username: document.getElementById("accountUsername").value,
      password: document.getElementById("accountPassword").value,
      fullname: document.getElementById("accountFullname").value,
      email: document.getElementById("accountEmail").value,
      phone: document.getElementById("accountPhone").value,
      birthday: document.getElementById("accountBirthday").value,
      region: document.getElementById("accountRegion").value
    }
  } else {
    changedData = {
      username: document.getElementById("accountUsername").value,
      fullname: document.getElementById("accountFullname").value,
      email: document.getElementById("accountEmail").value,
      phone: document.getElementById("accountPhone").value,
      birthday: document.getElementById("accountBirthday").value,
      region: document.getElementById("accountRegion").value
    }
  }

  const response = await fetch(`${backend_base_url}user/`, {
    headers: {
      Accept: "application/json",
      'Content-type': 'application/json',
      'Authorization': 'Bearer ' + localStorage.getItem("access")
    },
    method: "PUT",
    body: JSON.stringify(changedData)
  })

  account_response = response.json()

  if (response.status == 200) {
    alert("회원정보 수정이 완료되었습니다.")
    window.location.replace(`${frontend_base_url}index.html`)
  } else {
    alert(account_response.data)
  }
}
  • 해당 부분을 작성할 때도 비밀번호가 엄청난 문제였다. 그래서 비밀번호를 비워준 김에 비밀번호를 입력한 값과 아닌 값을 나누어 백앤드로 보내주었다.
  • 사용자가 꼭 비밀번호를 바꾸기 위해서 계정관리 페이지에 들어가는 것은 아니기 때문이다.
  • 해당 부분은 모달에서 수정하기 버튼을 누르게 되면 실행되는 함수이다.
profile
https://github.com/nikevapormax
post-custom-banner

0개의 댓글