Skip to content

Commit

Permalink
Merge pull request #1733 from doccano/fix/projectStaff
Browse files Browse the repository at this point in the history
Enable to view dataset page for project staffs
  • Loading branch information
Hironsan committed Mar 14, 2022
2 parents eae3c46 + 5494398 commit 9e4692c
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 13 deletions.
18 changes: 18 additions & 0 deletions backend/projects/tests/test_member.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,24 @@ def test_filter_role_by_user_id(self):
self.assertEqual(len(response.data), 1)


class TestMyRole(CRUDMixin):
def setUp(self):
self.project = prepare_project()
self.url = reverse(viewname="my_role", args=[self.project.item.id])

def test_admin(self):
response = self.assert_fetch(self.project.admin, status.HTTP_200_OK)
self.assertEqual(response.data["rolename"], settings.ROLE_PROJECT_ADMIN)

def test_approver(self):
response = self.assert_fetch(self.project.approver, status.HTTP_200_OK)
self.assertEqual(response.data["rolename"], settings.ROLE_ANNOTATION_APPROVER)

def test_annotator(self):
response = self.assert_fetch(self.project.annotator, status.HTTP_200_OK)
self.assertEqual(response.data["rolename"], settings.ROLE_ANNOTATOR)


class TestMemberManager(CRUDMixin):
def test_has_role(self):
project = prepare_project()
Expand Down
3 changes: 2 additions & 1 deletion backend/projects/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from django.urls import path

from .views.member import MemberDetail, MemberList
from .views.member import MemberDetail, MemberList, MyRole
from .views.project import ProjectDetail, ProjectList
from .views.tag import TagDetail, TagList

urlpatterns = [
path(route="projects", view=ProjectList.as_view(), name="project_list"),
path(route="projects/<int:project_id>", view=ProjectDetail.as_view(), name="project_detail"),
path(route="projects/<int:project_id>/my-role", view=MyRole.as_view(), name="my_role"),
path(route="projects/<int:project_id>/tags", view=TagList.as_view(), name="tag_list"),
path(route="projects/<int:project_id>/tags/<int:tag_id>", view=TagDetail.as_view(), name="tag_detail"),
path(route="projects/<int:project_id>/members", view=MemberList.as_view(), name="member_list"),
Expand Down
13 changes: 12 additions & 1 deletion backend/projects/views/member.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from django.db import IntegrityError
from django.shortcuts import get_object_or_404
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import generics, status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from projects.exceptions import RoleAlreadyAssignedException, RoleConstraintException
from projects.models import Member
from projects.permissions import IsProjectAdmin
from projects.permissions import IsProjectAdmin, IsProjectMember
from projects.serializers import MemberSerializer


Expand Down Expand Up @@ -51,3 +52,13 @@ def perform_update(self, serializer):
super().perform_update(serializer)
except IntegrityError:
raise RoleAlreadyAssignedException


class MyRole(generics.RetrieveAPIView):
queryset = Member.objects.all()
serializer_class = MemberSerializer
permission_classes = [IsAuthenticated & IsProjectMember]

def get_object(self):
kwargs = {"user": self.request.user, "project_id": self.kwargs["project_id"]}
return get_object_or_404(self.queryset, **kwargs)
2 changes: 2 additions & 0 deletions frontend/domain/models/member/memberRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ export interface MemberRepository {
update(projectId: string, item: MemberItem): Promise<MemberItem>

bulkDelete(projectId: string, memberIds: number[]): Promise<void>

fetchMyRole(projectId: string): Promise<MemberItem>
}
3 changes: 1 addition & 2 deletions frontend/layouts/project.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,10 @@ export default {
computed: {
...mapGetters('projects', ['getLink', 'currentProject']),
...mapGetters('auth', ['getUserId'])
},
async created() {
this.isProjectAdmin = await this.$services.member.isProjectAdmin(this.$route.params.id, this.getUserId)
this.isProjectAdmin = await this.$services.member.isProjectAdmin(this.$route.params.id)
}
}
</script>
3 changes: 1 addition & 2 deletions frontend/layouts/workspace.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export default {
computed: {
...mapGetters('projects', ['getLink', 'currentProject']),
...mapGetters('auth', ['getUserId'])
},
watch: {
Expand All @@ -56,7 +55,7 @@ export default {
},
async created() {
this.isProjectAdmin = await this.$services.member.isProjectAdmin(this.$route.params.id, this.getUserId)
this.isProjectAdmin = await this.$services.member.isProjectAdmin(this.$route.params.id)
}
}
</script>
2 changes: 1 addition & 1 deletion frontend/middleware/check-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default _.debounce(async function({ app, store, route, redirect }) {
redirect('/projects')
}
const userId = store.getters['auth/getUserId']
const isProjectAdmin = await app.$services.member.isProjectAdmin(route.params.id, userId)
const isProjectAdmin = await app.$services.member.isProjectAdmin(route.params.id)
const projectRoot = app.localePath('/projects/' + route.params.id)
const path = route.fullPath.replace(/\/$/g, '')

Expand Down
4 changes: 1 addition & 3 deletions frontend/pages/projects/_id/dataset/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@

<script lang="ts">
import Vue from 'vue'
import { mapGetters } from 'vuex'
import _ from 'lodash'
import DocumentList from '@/components/example/DocumentList.vue'
import FormDelete from '@/components/example/FormDelete.vue'
Expand Down Expand Up @@ -136,7 +135,6 @@ export default Vue.extend({
return 'text'
}
},
...mapGetters('auth', ['getUserId'])
},
watch: {
Expand All @@ -149,7 +147,7 @@ export default Vue.extend({
async created() {
this.project = await this.$services.project.findById(this.projectId)
this.isProjectAdmin = await this.$services.member.isProjectAdmin(this.projectId, this.getUserId)
this.isProjectAdmin = await this.$services.member.isProjectAdmin(this.projectId)
},
methods: {
Expand Down
6 changes: 6 additions & 0 deletions frontend/repositories/member/apiMemberRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,10 @@ export class APIMemberRepository implements MemberRepository {
const url = `/projects/${projectId}/members`
await this.request.delete(url, { ids: memberIds })
}

async fetchMyRole(projectId: string): Promise<MemberItem> {
const url = `/projects/${projectId}/my-role`
const response = await this.request.get(url)
return plainToInstance(MemberItem, response.data)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ export class MemberApplicationService {
return this.repository.bulkDelete(projectId, ids)
}

public async isProjectAdmin(projectId: string, userId: number): Promise<boolean> {
const items = await this.repository.list(projectId)
return items.some((item) => item.user === userId && item.isProjectAdmin)
public async isProjectAdmin(projectId: string): Promise<boolean> {
const item = await this.repository.fetchMyRole(projectId)
return item.isProjectAdmin
}
}

0 comments on commit 9e4692c

Please sign in to comment.