Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
45026e8
Merge pull request #70 from ThinLineIT/th-69-fix-cors-error
TaeHyoungKwon Jul 27, 2021
346a91e
Merge remote-tracking branch 'origin/main' into code-review
TaeHyoungKwon Jul 27, 2021
fbfce84
Merge branch 'code-review' of https://github.com/ThinLineIT/CSWIKI_Ba…
TaeHyoungKwon Jul 27, 2021
b693f83
Merge remote-tracking branch 'origin/main' into code-review
TaeHyoungKwon Jul 29, 2021
f16d9e0
Merge pull request #78 from ThinLineIT/th-77-add-admin-related-code
TaeHyoungKwon Jul 29, 2021
7ec20dd
Merge pull request #80 from ThinLineIT/th-79-add-note-list-in-mock-api
TaeHyoungKwon Jul 29, 2021
02eb703
Merge pull request #82 from ThinLineIT/th-81-add-temp-deleting-email-api
TaeHyoungKwon Jul 29, 2021
fa6199f
Merge remote-tracking branch 'origin/jh-18-check-nickname-duplicate-a…
TaeHyoungKwon Jul 29, 2021
e23b1b6
Merge remote-tracking branch 'origin/main' into code-review
TaeHyoungKwon Jul 30, 2021
50e8835
Merge pull request #84 from ThinLineIT/th-83-add-mock-api-about-check…
TaeHyoungKwon Jul 30, 2021
fda74b4
Merge branch 'main' into code-review
TaeHyoungKwon Jul 31, 2021
d5b652b
Merge branch 'code-review' of https://github.com/ThinLineIT/CSWIKI_Ba…
TaeHyoungKwon Jul 31, 2021
a47edcd
Merge remote-tracking branch 'origin/sh-19-check-email-duplicate' int…
TaeHyoungKwon Jul 31, 2021
16c0dc5
Merge remote-tracking branch 'origin/jh-75-check-nickname-validation'…
TaeHyoungKwon Jul 31, 2021
68f7b47
Merge branch 'main' into code-review
TaeHyoungKwon Jul 31, 2021
fdfb52c
Merge pull request #89 from ThinLineIT/th-73-add-note-model
TaeHyoungKwon Jul 31, 2021
91ebce1
Merge pull request #90 from ThinLineIT/th-73-add-note-model
TaeHyoungKwon Jul 31, 2021
52d756f
Merge pull request #91 from ThinLineIT/th-85-mock-api-fix-note-status…
TaeHyoungKwon Jul 31, 2021
9eb0052
Merge pull request #93 from ThinLineIT/th-92-add-mock-api-about-note-…
TaeHyoungKwon Jul 31, 2021
7412b8c
Merge pull request #95 from ThinLineIT/th-24-add-jwt-authentication-m…
TaeHyoungKwon Aug 2, 2021
bcc5977
Merge pull request #98 from ThinLineIT/th-24-add-jwt-authentication-m…
TaeHyoungKwon Aug 7, 2021
b8c8680
Merge remote-tracking branch 'origin/main' into code-review
TaeHyoungKwon Aug 7, 2021
eb2c911
Merge branch 'code-review' of https://github.com/ThinLineIT/CSWIKI_Ba…
TaeHyoungKwon Aug 7, 2021
7313133
Merge remote-tracking branch 'origin/main' into code-review
TaeHyoungKwon Aug 7, 2021
53a4e44
Merge remote-tracking branch 'origin/main' into code-review
TaeHyoungKwon Aug 7, 2021
4dc8bd3
Merge pull request #96 from ThinLineIT/sh-94-check-verification-code
TaeHyoungKwon Aug 7, 2021
ed3b168
Merge pull request #101 from ThinLineIT/th-100-add-model-first-version
TaeHyoungKwon Aug 9, 2021
f81d1f1
Merge pull request #107 from ThinLineIT/th-103-add-user-id-in-login-a…
TaeHyoungKwon Aug 9, 2021
0c3612b
Merge pull request #110 from ThinLineIT/th-109-add-mock-apis-on-issue…
TaeHyoungKwon Aug 11, 2021
b76cdcf
Merge remote-tracking branch 'origin/main' into code-review
TaeHyoungKwon Aug 11, 2021
000f420
Merge branch 'code-review' of https://github.com/ThinLineIT/CtrlF_Bac…
TaeHyoungKwon Aug 11, 2021
5af0c3c
TH-103 feat: add retrieve_page_list api
TaeHyoungKwon Aug 12, 2021
dc61206
Merge pull request #114 from ThinLineIT/th-113-add-page-list-api
TaeHyoungKwon Aug 12, 2021
b04f144
Merge remote-tracking branch 'origin/th-113-add-page-list-api' into c…
TaeHyoungKwon Aug 12, 2021
9176ca1
Merge branch 'code-review' of https://github.com/ThinLineIT/CSWIKI_Ba…
TaeHyoungKwon Aug 12, 2021
734f7c7
Merge pull request #112 from ThinLineIT/sh-104-Note-detail
TaeHyoungKwon Aug 13, 2021
5a6748f
Merge remote-tracking branch 'origin/sh-108-topic-list' into code-review
TaeHyoungKwon Aug 13, 2021
bec1437
Merge pull request #116 from ThinLineIT/sh-108-topic-list
TaeHyoungKwon Aug 13, 2021
cad3e78
Merge remote-tracking branch 'origin/th-99-add-celery-and-change-sync…
TaeHyoungKwon Aug 14, 2021
ca75aa4
Merge pull request #119 from ThinLineIT/th-87-add-commit-hook
TaeHyoungKwon Aug 15, 2021
2636663
Update prlint.json
TaeHyoungKwon Aug 15, 2021
65351b2
Merge remote-tracking branch 'origin/main' into code-review
TaeHyoungKwon Aug 15, 2021
a57b072
Merge branch 'code-review' of https://github.com/ThinLineIT/CSWIKI_Ba…
TaeHyoungKwon Aug 15, 2021
cdf53e3
Merge remote-tracking branch 'origin/main' into code-review
TaeHyoungKwon Aug 15, 2021
c6be894
Merge remote-tracking branch 'origin/jh-97-add-note-list-api' into co…
TaeHyoungKwon Aug 16, 2021
e6eda05
SH-111 refactor: replace proper word for readability
TaeHyoungKwon Aug 16, 2021
4b871a5
Merge remote-tracking branch 'origin/th-88-refactor-all-codes' into c…
TaeHyoungKwon Aug 16, 2021
eea8b7b
JG-105 Add issue List API
wlsrn3684 Aug 16, 2021
f7e5273
Merge remote-tracking branch 'origin/main' into code-review
TaeHyoungKwon Aug 16, 2021
aced391
Merge pull request #127 from ThinLineIT/sh-126-page-detail-mock-api
jrhong95 Aug 19, 2021
1c1d305
Merge remote-tracking branch 'origin/sh-130-topic-detail-api' into co…
TaeHyoungKwon Aug 30, 2021
0adb5cc
Merge remote-tracking branch 'origin/sh-131-page-detail-api' into cod…
TaeHyoungKwon Aug 30, 2021
5b4fd59
Merge pull request #134 from ThinLineIT/jh-23-add-note-create-api
TaeHyoungKwon Aug 30, 2021
8cf57d0
Merge branch 'main' of https://github.com/ThinLineIT/CtrlF_Backend in…
wlsrn3684 Aug 31, 2021
8753e4e
fix merge error
wlsrn3684 Aug 31, 2021
1a01161
finish issue list api
wlsrn3684 Sep 1, 2021
6dc5963
fix test code auth error
wlsrn3684 Sep 1, 2021
5828e71
Merge remote-tracking branch 'origin/code-review' into jg-105-issue-list
wlsrn3684 Sep 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .github/prlint.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{
"title": [
{
"pattern": "^(TH-|JH-|SH-|JG-)\\d+: .+$",
"message": "{personal initial above}-{issue number}: {pr title} - ex) TH-150: add test prlint.json"
}
]
"title": [{
"pattern": "^(TH-|JH-|SH-|JG-)\\d+: .+$",
"message": "{personal initial above}-{issue number}: {pr title} - ex) TH-150: add test prlint.json"
}]
}
1 change: 1 addition & 0 deletions v2/src/config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@
path("api/auth/", include("ctrlf_auth.urls"), name="auth"),
path("api/notes/", include("ctrlfbe.note_urls"), name="notes"),
path("api/topics/", include("ctrlfbe.topic_urls"), name="topics"),
path("api/issues/", include("ctrlfbe.issue_urls"), name="issues"),
path("api/pages/", include("ctrlfbe.page_urls"), name="pages"),
]
1 change: 1 addition & 0 deletions v2/src/ctrlfbe/constants.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
MAX_PRINTABLE_NOTE_COUNT = 30
MAX_PRINTABLE_ISSUE_COUNT = 30
ERR_NOTE_NOT_FOUND = "노트를 찾을 수 없습니다."
ERR_TOPIC_NOT_FOUND = "토픽을 찾을 수 없습니다."
ERR_PAGE_NOT_FOUND = "페이지를 찾을 수 없습니다."
Expand Down
9 changes: 9 additions & 0 deletions v2/src/ctrlfbe/issue_urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.urls import path

from .views import IssueListView

app_name = "issues"

urlpatterns = [
path("", IssueListView.as_view(), name="issue_list"),
]
30 changes: 30 additions & 0 deletions v2/src/ctrlfbe/migrations/0006_auto_20210901_1507.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 3.2.5 on 2021-09-01 06:07

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("ctrlfbe", "0005_page_is_approved"),
]

operations = [
migrations.AddField(
model_name="contentrequest",
name="status",
field=models.CharField(
choices=[("PENDING", "보류"), ("REJECTED", "거절"), ("ACCEPTED", "승인")],
default="PENDING",
help_text="Content 상태들",
max_length=30,
),
),
migrations.AlterField(
model_name="issue",
name="status",
field=models.CharField(
choices=[("REQUESTED", "요청"), ("CLOSED", "닫힘")], help_text="Issue 상태들", max_length=30
),
),
]
11 changes: 9 additions & 2 deletions v2/src/ctrlfbe/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,23 @@ class CtrlfActionType(models.TextChoices):

class CtrlfIssueStatus(models.TextChoices):
REQUESTED = "REQUESTED", "요청"
REJECTED = "REJECTED", "거절"
APPROVED = "APPROVED", "승인"
CLOSED = "CLOSED", "닫힘"


class CtrlfContentStatus(models.TextChoices):
PENDING = "PENDING", "보류"
REJECTED = "REJECTED", "거절"
ACCEPTED = "ACCEPTED", "승인"


class ContentRequest(CommonTimestamp):
user = models.ForeignKey(CtrlfUser, on_delete=models.CASCADE, help_text="수정 혹은 삭제의 주체자")
sub_id = models.IntegerField(help_text="type에 대한 id")
type = models.CharField(max_length=30, choices=CtrlfContentType.choices, help_text="NOTE, TOPIC, PAGE")
action = models.CharField(max_length=30, choices=CtrlfActionType.choices, help_text="CRUD")
status = models.CharField(
max_length=30, choices=CtrlfContentStatus.choices, default=CtrlfContentStatus.PENDING, help_text="Content 상태들"
)
reason = models.TextField(default="", help_text="수정 혹은 삭제 이유")
is_active = models.BooleanField(default=False)

Expand Down
71 changes: 71 additions & 0 deletions v2/src/ctrlfbe/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from .models import (
ContentRequest,
CtrlfActionType,
CtrlfContentStatus,
CtrlfContentType,
Issue,
Note,
Expand All @@ -11,6 +12,75 @@
)


class ContentRequestSerializer(serializers.ModelSerializer):
class Meta:
model = ContentRequest
fields = ["user", "sub_id", "type", "action", "reason", "status"]


class IssueSerializer(serializers.ModelSerializer):
content_request = ContentRequestSerializer()

class Meta:
model = Issue
fields = ["id", "owner", "title", "content", "status", "content_request"]

def to_representation(self, instance):
def get_note_owners(note_id, creator):
note = Note.objects.get(id=note_id)
serializer = NoteSerializer(note)
serializered_note = serializer.data

creator["note"] = serializered_note["owners"]
return creator

def get_topic_owners(topic_id, creator):
topic = Topic.objects.get(id=topic_id)
serializer = TopicSerializer(topic)
serializered_topic = serializer.data
creator["topic"] = serializered_topic["owners"]
return get_note_owners(serializered_topic["note"], creator)

def get_page_owners(page_id, creator):
page = Page.objects.get(id=page_id)
serializer = PageSerializer(page)
serializered_page = serializer.data
creator["page"] = serializered_page["owners"]
return get_topic_owners(serializered_page["topic"], creator)

def make_creator(type, target_id):
creator = {
"note": None,
"topic": None,
"page": None,
}

if type == "NOTE":
creator = get_note_owners(target_id, creator)
elif type == "TOPIC":
creator = get_topic_owners(target_id, creator)
elif type == "PAGE":
creator = get_page_owners(target_id, creator)

return creator

issue = super().to_representation(instance)
creator = make_creator(issue["content_request"]["type"], issue["content_request"]["sub_id"])

return {
"id": issue["id"],
"title": issue["title"],
"content": issue["content"],
"action": issue["content_request"]["action"],
"content_id": issue["content_request"]["sub_id"],
"content_type": issue["content_request"]["type"],
"content_status": issue["content_request"]["status"],
"issue_status": issue["status"],
"reason": issue["content_request"]["reason"],
"creator": creator,
}


class NoteListSerializer(serializers.ListSerializer):
pass

Expand Down Expand Up @@ -42,6 +112,7 @@ def create(self, validated_data):
"sub_id": note.id,
"type": CtrlfContentType.NOTE,
"action": CtrlfActionType.CREATE,
"status": CtrlfContentStatus.PENDING,
"reason": "create note",
}
content_request = ContentRequest.objects.create(**content_request_data)
Expand Down
8 changes: 8 additions & 0 deletions v2/src/ctrlfbe/swagger.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from ctrlfbe.serializers import (
IssueSerializer,
NoteCreateRequestBodySerializer,
NoteListQuerySerializer,
NoteSerializer,
Expand Down Expand Up @@ -34,6 +35,13 @@
"tags": ["메인 화면"],
}

SWAGGER_ISSUE_LIST_VIEW = {
"responses": {200: IssueSerializer(many=True)},
"operation_summary": "Issue List API",
"operation_description": "모든 issue들의 list를 리턴해줍니다",
"tags": ["이슈 화면"],
}

SWAGGER_NOTE_CREATE_VIEW = {
"operation_summary": "Note Create API",
"operation_description": "비활성화된 Note와 이슈를 생성 합니다.",
Expand Down
56 changes: 53 additions & 3 deletions v2/src/ctrlfbe/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from typing import Optional
import json
from typing import List, Optional

from ctrlfbe.mixins import CtrlfAuthenticationMixin
from ctrlfbe.swagger import (
SWAGGER_ISSUE_LIST_VIEW,
SWAGGER_NOTE_CREATE_VIEW,
SWAGGER_NOTE_DETAIL_VIEW,
SWAGGER_NOTE_LIST_VIEW,
Expand All @@ -16,10 +18,16 @@
from rest_framework.response import Response
from rest_framework.views import APIView

from .constants import ERR_NOT_FOUND_MSG_MAP, ERR_UNEXPECTED, MAX_PRINTABLE_NOTE_COUNT
from .models import CtrlfIssueStatus, Note, Page, Topic
from .constants import (
ERR_NOT_FOUND_MSG_MAP,
ERR_UNEXPECTED,
MAX_PRINTABLE_ISSUE_COUNT,
MAX_PRINTABLE_NOTE_COUNT,
)
from .models import CtrlfIssueStatus, Issue, Note, Page, Topic
from .serializers import (
IssueCreateSerializer,
IssueSerializer,
NoteSerializer,
PageSerializer,
TopicSerializer,
Expand Down Expand Up @@ -128,6 +136,48 @@ def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)


class IssueListView(CtrlfAuthenticationMixin, APIView):
authentication_classes: List[str] = []

@swagger_auto_schema(**SWAGGER_ISSUE_LIST_VIEW)
def get(self, request):
ctrlf_user = self._ctrlf_authentication(request)

current_cursor = int(request.query_params["cursor"])
typeList = json.loads(request.query_params["type"])
mine = request.query_params["mine"]

issues = Issue.objects.all()
filtered_issues = issues

if mine == "true":
temp_list = []
for issue in filtered_issues:
if ctrlf_user.id == issue["owner_id"]:
temp_list.append(issue)
filtered_issues = temp_list

if len(typeList) > 0:
temp_list = []
for issue in filtered_issues:
if typeList in issue["content_type"]:
temp_list.append(issue)
filtered_issues = temp_list

if current_cursor >= len(issues):
return Response({"next_cursor": len(issues), "issues": []}, status.HTTP_200_OK)
elif current_cursor + MAX_PRINTABLE_ISSUE_COUNT > len(issues):
sliced_issues = issues[current_cursor : len(issues)]
next_cursor = len(issues)
else:
sliced_issues = issues[current_cursor : current_cursor + MAX_PRINTABLE_ISSUE_COUNT]
next_cursor = current_cursor + MAX_PRINTABLE_ISSUE_COUNT
serializer = IssueSerializer(data=sliced_issues, many=True)
serializer.is_valid()
serialized_issues = serializer.data
return Response(data={"next_cursor": next_cursor, "issues": serialized_issues}, status=status.HTTP_200_OK)


class PageDetailUpdateDeleteView(BaseContentView):
parent_model = Page
serializer = PageSerializer
Expand Down
60 changes: 30 additions & 30 deletions v2/src/tests/test_content_list_detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,71 +151,71 @@ def test_page_list_should_return_404_by_invalid_topic_id(self):
self.assertEqual(response["message"], "토픽을 찾을 수 없습니다.")


class TestTopicDetail(TestCase):
class TestPageDetail(TestCase):
def setUp(self):
self.c = Client()
self.user = CtrlfUser.objects.create_user(email="test@test.com", password="12345")
self.note = Note.objects.create(title="test note")
self.note.owners.add(self.user)
self.topic = Topic.objects.create(note=self.note, title="test topic")
self.topic.owners.add(self.user)
page_data = {"topic": self.topic, "title": "test page", "content": "test content"}
self.page = Page.objects.create(**page_data)
self.page.owners.add(self.user)

def test_topic_detail_should_return_200(self):
# Given : 유효한 topic id, 이미 저장된 topic
topic_id = self.topic.id
def test_page_detail_should_return_200(self):
# Given : 유효한 page id, 이미 저장된 page
page_id = self.page.id
# When : API 실행
response = self.c.get(reverse("topics:topic_detail", kwargs={"topic_id": topic_id}))
response = self.c.get(reverse("pages:page_detail", kwargs={"page_id": page_id}))
# Then : 상태코드 200
self.assertEqual(response.status_code, status.HTTP_200_OK)
# And : 불러온 정보가 저장된 정보와 일치해야 한다.
response = response.data
self.assertEqual(response["title"], "test topic")
self.assertEqual(response["note"], self.note.id)
self.assertEqual(response["title"], "test page")
self.assertEqual(response["content"], "test content")
self.assertEqual(response["topic"], self.topic.id)

def test_topic_detail_should_return_404_by_invalid_topic_id(self):
# Given : 유효하지 않은 topic id, 이미 저장된 topic
invalid_topic_id = 1234
def test_page_detail_should_return_404_by_invalid_page_id(self):
# Given : 유효하지 않은 page id, 이미 저장된 page
invalid_page_id = 1234
# When : API 실행
response = self.c.get(reverse("topics:topic_detail", kwargs={"topic_id": invalid_topic_id}))
response = self.c.get(reverse("pages:page_detail", kwargs={"page_id": invalid_page_id}))
# Then : 상태코드 404
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
# And : 메세지는 "토픽을 찾을 수 없습니다." 이어야 한다.
# And : 메세지는 "페이지를 찾을 수 없습니다." 이어야 한다.
response = response.data
self.assertEqual(response["message"], "토픽을 찾을 수 없습니다.")
self.assertEqual(response["message"], "페이지를 찾을 수 없습니다.")


class TestPageDetail(TestCase):
class TestTopicDetail(TestCase):
def setUp(self):
self.c = Client()
self.user = CtrlfUser.objects.create_user(email="test@test.com", password="12345")
self.note = Note.objects.create(title="test note")
self.note.owners.add(self.user)
self.topic = Topic.objects.create(note=self.note, title="test topic")
self.topic.owners.add(self.user)
page_data = {"topic": self.topic, "title": "test page", "content": "test content"}
self.page = Page.objects.create(**page_data)
self.page.owners.add(self.user)

def test_page_detail_should_return_200(self):
# Given : 유효한 page id, 이미 저장된 page
page_id = self.page.id
def test_topic_detail_should_return_200(self):
# Given : 유효한 topic id, 이미 저장된 topic
topic_id = self.topic.id
# When : API 실행
response = self.c.get(reverse("pages:page_detail", kwargs={"page_id": page_id}))
response = self.c.get(reverse("topics:topic_detail", kwargs={"topic_id": topic_id}))
# Then : 상태코드 200
self.assertEqual(response.status_code, status.HTTP_200_OK)
# And : 불러온 정보가 저장된 정보와 일치해야 한다.
response = response.data
self.assertEqual(response["title"], "test page")
self.assertEqual(response["content"], "test content")
self.assertEqual(response["topic"], self.topic.id)
self.assertEqual(response["title"], "test topic")
self.assertEqual(response["note"], self.note.id)

def test_page_detail_should_return_404_by_invalid_page_id(self):
# Given : 유효하지 않은 page id, 이미 저장된 page
invalid_page_id = 1234
def test_topic_detail_should_return_404_by_invalid_topic_id(self):
# Given : 유효하지 않은 topic id, 이미 저장된 topic
invalid_topic_id = 1234
# When : API 실행
response = self.c.get(reverse("pages:page_detail", kwargs={"page_id": invalid_page_id}))
response = self.c.get(reverse("topics:topic_detail", kwargs={"topic_id": invalid_topic_id}))
# Then : 상태코드 404
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
# And : 메세지는 "페이지를 찾을 수 없습니다." 이어야 한다.
# And : 메세지는 "토픽을 찾을 수 없습니다." 이어야 한다.
response = response.data
self.assertEqual(response["message"], "페이지를 찾을 수 없습니다.")
self.assertEqual(response["message"], "토픽을 찾을 수 없습니다.")
Loading