Skip to content

Accounts

najasinis edited this page Apr 11, 2024 · 2 revisions

Accounts

Accounts 앱은 Safe Eye 프로젝트에서 계정 정보들을 관리하고 권한을 제공하는 앱입니다.

Models

CustomUser 모델
CustomUser 모델은 사용자 정보를 저장하는 모델입니다.

예시 코드

# accounts/models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models
from utils.models import Status, Tag

class CustomUserManager(BaseUserManager):
    def create_user(self, email, password=None, nickname=None, **extra_fields):
        if not email:
            raise ValueError('The Email field must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, nickname=nickname, role='user', **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password=None, nickname=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        return self.create_user(email, password, nickname, **extra_fields)

class CustomUser(AbstractBaseUser, PermissionsMixin):
    ROLE_CHOICES = (
        ('user', 'User'),
        ('admin', 'Admin'),
    )

    email = models.EmailField(unique=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    user_tag = models.ForeignKey(Tag, on_delete=models.SET_NULL, null=True)
    user_status = models.ForeignKey(Status, on_delete=models.SET_NULL, null=True)
    nickname = models.CharField(max_length=255)
    role = models.CharField(max_length=5, choices=ROLE_CHOICES, default='user')
    profile_image = models.ImageField(upload_to='profile_images/', null=True, blank=True)

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['nickname']

    def __str__(self):
        return self.email
  • 코드 설명
    CustomUser 모델은 사용자의 이메일(email), 활성 상태(is_active), 관리자 권한(is_staff), 태그(user_tag), 상태(user_status), 닉네임(nickname), 역할(role), 프로필 이미지(profile_image) 등의 필드를 가지고 있습니다. 또한, AbstractBaseUser와 PermissionsMixin을 상속받아 사용자 인증 및 권한 관련 기능을 구현하였습니다.

CustomUserManager는 사용자 생성을 위한 헬퍼 클래스로, create_user와 create_superuser 메서드를 제공합니다. 이를 통해 일반 사용자와 관리자 계정을 생성할 수 있습니다.

USERNAME_FIELD는 사용자 인증에 사용될 필드를 지정하며, 여기서는 이메일(email)을 사용합니다. REQUIRED_FIELDS는 사용자 생성 시 필수로 입력받을 필드를 지정하며, 여기서는 닉네임(nickname)이 필수 입력 사항입니다.

str 메서드는 사용자 객체를 문자열로 표현할 때 사용되며, 여기서는 사용자의 이메일을 반환하도록 설정되어 있습니다.

Tests

  • Tests.py
    일반 사용자 및 관리자 계정들을 따로 구분지어서 test를 진행했습니다. 테스트 결과 이상은 없었습니다.

테스트 계정 정보 : 일반 사용자 계정 이메일: normaluser@example.com 비밀번호: password123 닉네임: Normal User 권한: is_staff: False is_superuser: False 이 계정은 일반 사용자를 나타내는 테스트 계정입니다. 일반 사용자는 기본적인 기능을 사용할 수 있지만, 관리자 권한은 없습니다.

테스트 계정 정보 : 관리자 계정 이메일: adminuser@example.com 비밀번호: adminpassword 닉네임: Admin User 권한: is_staff: True is_superuser: True 이 계정은 관리자 사용자를 나타내는 테스트 계정입니다. 관리자 사용자는 모든 기능에 접근할 수 있으며, 시스템을 관리하고 설정할 수 있는 권한을 가지고 있습니다.

Views

  • AlarmViewSet
    AlarmViewSet은 Alarm 모델에 대한 CRUD 작업을 수행합니다.

  • 예시 코드

# alarm/views.py
from utils.mixins import Custom404Mixin, IsAuthorOrReadOnly
from utils.views import CustomPageNumberPagination

class AlarmViewSet(Custom404Mixin, viewsets.ModelViewSet):
    queryset = Alarm.objects.order_by("-created_at")
    serializer_class = AlarmSerializer
    permission_classes = [IsAuthorOrReadOnly]
    pagination_class = CustomPageNumberPagination
    filter_fields = ["id", "alarm_type", "user"]
    custom_404_message = "해당 알람을 찾을 수 없습니다."

    def perform_create(self, serializer):
        if self.request.user.is_superuser:
            serializer.save(user=self.request.user)
        else:
            serializer.save()
  • 코드 설명
    AlarmViewSet에서 Custom404Mixin과 IsAuthorOrReadOnly 권한 클래스를 사용하여 404 에러 처리와 권한 관리를 커스터마이징하였습니다. 그리고 perform_create 메서드를 오버라이드하여 슈퍼유저인 경우에만 알람 작성자를 설정할 수 있도록 하였습니다.

API

  • /alarms/ 엔드포인트
    /alarms/ 엔드포인트를 통해 알람 목록을 조회하거나 새로운 알람을 생성할 수 있습니다.

  • 예시 코드

# alarm/serializers.py
from utils.serializers import TagSerializer, StatusSerializer

class AlarmSerializer(serializers.ModelSerializer):
    tags = TagSerializer(many=True, required=False)
    status = StatusSerializer(many=True, required=False)

    class Meta:
        model = Alarm
        fields = ["id", "user", "alarm_type", "alarm_content", "created_at", "updated_at", "tags", "status"]
  • 코드 설명
    AlarmSerializer에서 TagSerializer와 StatusSerializer를 사용하여 알람 데이터와 함께 관련된 태그와 상태 정보를 직렬화할 수 있습니다. 이를 통해 API 응답에 알람 데이터와 태그, 상태 정보를 포함시킬 수 있습니다.

Clone this wiki locally