Skip to content

Commit

Permalink
Merge pull request #611 from Ilhasoft/feature/classifier-endpoints
Browse files Browse the repository at this point in the history
Classifiers endpoints
  • Loading branch information
dyohan9 committed Jul 2, 2021
2 parents 23f5e18 + fd3775e commit f632e5a
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 1 deletion.
33 changes: 32 additions & 1 deletion bothub/api/grpc/connect_grpc_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ def list_classifiers(self, project_uuid: str) -> List[Dict[str, str]]:
result = []
try:
stub = project_pb2_grpc.ProjectControllerStub(self.channel)

for project in stub.Classifier(
project_pb2.ClassifierListRequest(project_uuid=project_uuid)
):
Expand All @@ -30,6 +29,8 @@ def list_classifiers(self, project_uuid: str) -> List[Dict[str, str]]:
"authorization_uuid": project.authorization_uuid,
"classifier_type": project.classifier_type,
"name": project.name,
"is_active": project.is_active,
"uuid": project.uuid,
}
)
except grpc.RpcError as e:
Expand All @@ -41,3 +42,33 @@ def list_authorizations(self, project_uuid: str) -> List[str]:
classifiers = self.list_classifiers(project_uuid=project_uuid)

return [classifier.get("authorization_uuid") for classifier in classifiers]

def get_authorization_classifier(
self, project_uuid: str, authorization_uuid: str
) -> str:
"""
Recives a authorization UUID and returns the respective classifier UUID
"""
classifiers = self.list_classifiers(project_uuid)
classifier = filter(
lambda classifier: classifier["authorization_uuid"] == authorization_uuid,
classifiers,
)

return next(classifier).get("uuid")

def remove_authorization(self, project_uuid: str, authorization_uuid: str):
classifier_uuid = self.get_authorization_classifier(
project_uuid, authorization_uuid
)

stub = project_pb2_grpc.ProjectControllerStub(self.channel)
stub.DestroyClassifier(
project_pb2.ClassifierDestroyRequest(uuid=classifier_uuid)
)

def create_classifier(self, **kwargs):
stub = project_pb2_grpc.ProjectControllerStub(self.channel)
return stub.CreateClassifier(
project_pb2.ClassifierCreateRequest(**kwargs, classifier_type="bothub")
)
26 changes: 26 additions & 0 deletions bothub/api/v2/repository/serializers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
from os import access

from django.conf import settings
from django.shortcuts import get_object_or_404
Expand Down Expand Up @@ -1612,3 +1613,28 @@ class Meta:

class RepositoryExampleSuggestionSerializer(serializers.Serializer):
pass


class RemoveRepositoryProject(serializers.Serializer):
pass


class AddRepositoryProjectSerializer(serializers.Serializer):

name = serializers.CharField(required=True)
user = serializers.EmailField(required=True)
access_token = serializers.CharField(required=True)
project_uuid = serializers.CharField(required=True)

def create(self, validated_data):
task = celery_app.send_task(
name="create_repository_project", kwargs=validated_data
)
task.wait()
return validated_data

def to_representation(self, instance):
data = super().to_representation(instance)
if data.get("organization"):
data.pop("organization")
return data
181 changes: 181 additions & 0 deletions bothub/api/v2/repository/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
RepositoryVote,
RequestRepositoryAuthorization,
RepositoryVersionLanguage,
Organization,
)

from ..metadata import Metadata
Expand Down Expand Up @@ -97,6 +98,8 @@
ShortRepositorySerializer,
TrainSerializer,
WordDistributionSerializer,
RemoveRepositoryProject,
AddRepositoryProjectSerializer,
)


Expand Down Expand Up @@ -198,6 +201,184 @@ def auto_translation(self, request, **kwargs):

return Response({"id_queue": task.task_id})

@action(
detail=True,
methods=["GET"],
url_name="project-repository",
lookup_fields=["repository__uuid", "pk"],
)
def projectrepository(self, request, **kwargs):
repository = self.get_object().repository

project_uuid = request.query_params.get("project_uuid")
organization_pk = request.query_params.get("organization")

try:
organization = (
Organization.objects.get(pk=organization_pk)
if organization_pk
else None
)
except Organization.DoesNotExist:
raise ValidationError(_("Organization not found"))

if not project_uuid:
raise ValidationError(_("Need to pass 'project_uuid' in query params"))

authorization = repository.get_user_authorization(request.user)

if not authorization.can_contribute:
raise PermissionDenied()

task = celery_app.send_task(
name="get_project_organization", args=[project_uuid]
)
task.wait()

repositories = repository.authorizations.filter(uuid__in=task.result)

data = dict(in_project=repositories.exists())

if organization:

organization_authorization = organization.organization_authorizations.filter(
uuid__in=task.result
)
data["in_project"] = (
data["in_project"] or organization_authorization.exists()
)

return Response(data)

@action(
detail=True,
methods=["POST"],
permission_classes=[RepositoryAdminManagerAuthorization],
url_name="remove-repository-project",
serializer_class=RemoveRepositoryProject,
)
def remove_repository_project(self, request, **kwargs):

repository_version = self.get_object()
repository = repository_version.repository

user_authorization = repository_version.repository.get_user_authorization(
request.user
)

if not user_authorization.is_admin:
raise PermissionDenied()

project_uuid = request.data.get("project_uuid")
organization_pk = request.data.get("organization")

if not project_uuid:
raise ValidationError(_("Need to pass 'project_uuid' in query params"))

try:
organization = (
Organization.objects.get(pk=organization_pk)
if organization_pk
else None
)
except Organization.DoesNotExist:
raise ValidationError(_("Organization not found"))

project_organization = celery_app.send_task(
name="get_project_organization", args=[project_uuid]
)
project_organization.wait()

authorizations = list(
repository.authorizations.filter(
uuid__in=project_organization.result
).values_list("uuid", flat=True)
)

if organization:
organization_authorization = organization.get_organization_authorization(
request.user
)
if not organization_authorization.is_admin:
raise PermissionDenied()

authorizations += list(
organization.organization_authorizations.filter(
uuid__in=project_organization.result
).values_list("uuid", flat=True)
)

if not len(authorizations):
raise ValidationError(
_("Repository or organization is not be included on project")
)

authorizations_uuids = map(
lambda authorization: str(authorization), authorizations
)

task = celery_app.send_task(
name="remove_authorizations_project",
args=[project_uuid, list(authorizations_uuids)],
)
task.wait()

return Response(status=status.HTTP_204_NO_CONTENT)

@action(
detail=True,
methods=["POST"],
url_name="add-repository-project",
serializer_class=AddRepositoryProjectSerializer,
)
def add_repository_project(self, request, **kwargs):

repository = self.get_object().repository
organization_pk = request.data.get("organization")

try:
organization = Organization.objects.get(pk=organization_pk)
except Organization.DoesNotExist:
raise ValidationError(_("Organization not found"))

organization_authorization = organization.get_organization_authorization(
request.user
)
user_authorization = repository.get_user_authorization(request.user)

if (
not organization_authorization.can_contribute
or not user_authorization.can_contribute
):
raise PermissionDenied()

serializer_data = dict(
user=request.user.email,
access_token=str(organization_authorization.uuid),
**request.data,
)

serializer = AddRepositoryProjectSerializer(data=serializer_data)
serializer.is_valid(raise_exception=True)

project_uuid = serializer.validated_data.get("project_uuid")

task = celery_app.send_task(
name="get_project_organization", args=[project_uuid]
)
task.wait()

organization_authorization = organization.organization_authorizations.filter(
uuid__in=task.result
)

if organization_authorization.exists():
raise ValidationError(_("Repository already added"))

data = serializer.save()

return Response(data)


class RepositoryTrainInfoViewSet(
MultipleFieldLookupMixin, mixins.RetrieveModelMixin, GenericViewSet
Expand Down
14 changes: 14 additions & 0 deletions bothub/common/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,3 +540,17 @@ def get_project_organization(project_uuid: str): # pragma: no cover
grpc_client = ConnectGRPCClient()
authorizations = grpc_client.list_authorizations(project_uuid=project_uuid)
return authorizations


@app.task(name="remove_authorizations_project")
def remove_authorizations_project(project_uuid: str, authorizations_uuids: list):
grpc_client = ConnectGRPCClient()
for authorization_uuid in authorizations_uuids:
grpc_client.remove_authorization(project_uuid, authorization_uuid)


@app.task(name="create_repository_project")
def create_repository_project(**kwargs):
grpc_client = ConnectGRPCClient()
grpc_client.create_classifier(**kwargs)
return kwargs
23 changes: 23 additions & 0 deletions bothub/protos/project.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,39 @@ syntax = "proto3";

package weni.connect.project;

import "google/protobuf/empty.proto";

service ProjectController {
rpc Classifier(ClassifierListRequest) returns (stream ClassifierResponse) {}
rpc CreateClassifier(ClassifierCreateRequest) returns (ClassifierResponse) {}
rpc RetrieveClassifier(ClassifierRetrieveRequest) returns (ClassifierResponse) {}
rpc DestroyClassifier(ClassifierDestroyRequest) returns (google.protobuf.Empty) {}
}

message ClassifierResponse {
string authorization_uuid = 1;
string classifier_type = 2;
string name = 3;
bool is_active = 4;
string uuid = 5;
}

message ClassifierListRequest {
string project_uuid = 1;
}

message ClassifierCreateRequest {
string project_uuid = 1;
string user = 2;
string classifier_type = 3;
string name = 4;
string access_token = 5;
}

message ClassifierRetrieveRequest {
string uuid = 1;
}

message ClassifierDestroyRequest {
string uuid = 1;
}

0 comments on commit f632e5a

Please sign in to comment.