Skip to content

Commit

Permalink
Merge branch 'development' of https://github.com/breatheco-de/apiv2 i…
Browse files Browse the repository at this point in the history
…nto fix/hook-error-replication
  • Loading branch information
jefer94 committed Jun 25, 2024
2 parents 4c57f6d + 654e2cc commit 4519beb
Show file tree
Hide file tree
Showing 53 changed files with 2,877 additions and 9,826 deletions.
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ aiodns = "*"
eventlet = "*"
linked-services = {extras = ["django", "aiohttp", "requests"], version = "*"}
celery-task-manager = {extras = ["django"], version = "*"}
django-sql-explorer = {extras = ["xls"], version = "*"}
django-sql-explorer = {extras = ["xls"], version = "==4.3"}
contextlib2 = "*"
google-apps-meet = "*"
google-auth-httplib2 = "*"
Expand Down
278 changes: 139 additions & 139 deletions Pipfile.lock

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions breathecode/admissions/permissions/consumers.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
from django.db.models import Q
from breathecode.utils.decorators import PermissionContextType

from breathecode.utils.decorators import ServiceContext

def cohort_by_url_param(context: PermissionContextType, args: tuple, kwargs: dict) -> tuple[dict, tuple, dict]:

def cohort_by_url_param(context: ServiceContext, args: tuple, kwargs: dict) -> tuple[dict, tuple, dict]:
context['consumables'] = context['consumables'].filter(
Q(cohort__id=kwargs.get('cohort_id'))
| Q(cohort__slug=kwargs.get('cohort_slug')))

return (context, args, kwargs)


def cohort_by_header(context: PermissionContextType, args: tuple, kwargs: dict) -> tuple[dict, tuple, dict]:
def cohort_by_header(context: ServiceContext, args: tuple, kwargs: dict) -> tuple[dict, tuple, dict]:
cohort = context['request'].META.get('HTTP_COHORT', '')
kwargs = {}

Expand Down
9 changes: 6 additions & 3 deletions breathecode/assessment/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,12 +405,15 @@ def get(self, request, assessment_slug, threshold_id=None):
lookup['academy__id'] = int(param)
else:
lookup['academy__slug'] = param
else:
lookup['academy__isnull'] = True

if 'tag' in self.request.GET:
param = self.request.GET.get('tags')
lookup['tags__icontains'] = param

if param != 'all':
lookup['tags__icontains'] = param
else:
lookup['academy__isnull'] = True
lookup['tags__in'] = ['', None]

items = items.filter(**lookup).order_by('-created_at')

Expand Down
7 changes: 4 additions & 3 deletions breathecode/assignments/permissions/consumers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

from breathecode.admissions.actions import is_no_saas_student_up_to_date_in_any_cohort
from breathecode.authenticate.actions import get_user_language
from breathecode.utils.decorators import PermissionContextType
from breathecode.payments.models import Service
from breathecode.utils.decorators import ServiceContext
from breathecode.utils.i18n import translation
from capyc.rest_framework.exceptions import PaymentException

logger = logging.getLogger(__name__)


def code_revision_service(context: PermissionContextType, args: tuple, kwargs: dict) -> tuple[dict, tuple, dict]:
def code_revision_service(context: ServiceContext, args: tuple, kwargs: dict) -> tuple[dict, tuple, dict]:
request = context['request']
lang = get_user_language(request)

Expand All @@ -20,5 +21,5 @@ def code_revision_service(context: PermissionContextType, args: tuple, kwargs: d
es='No puedes acceder a este recurso porque tu estado financiero no está al dia',
slug='cohort-user-status-later'))

context['consumables'] = context['consumables'].filter(service_set__slug='code_revision')
context['consumables'] = context['consumables'].filter(service_item__service__type=Service.Type.VOID)
return (context, args, kwargs)
220 changes: 126 additions & 94 deletions breathecode/assignments/tests/urls/tests_me_coderevision.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@

import pytest
import requests
from aiohttp import ClientSession
from django.urls.base import reverse_lazy
from linked_services.django.actions import reset_app_cache
from linked_services.django.service import Service
from rest_framework import status
from rest_framework.test import APIClient

from ..mixins import AssignmentsTestCase
from breathecode.tests.mixins.breathecode_mixin.breathecode import Breathecode


@pytest.fixture(autouse=True)
Expand All @@ -21,96 +23,126 @@ def setup(db):
yield


class MediaTestSuite(AssignmentsTestCase):

# When: no auth
# Then: response 401
def test_no_auth(self):
url = reverse_lazy('assignments:me_coderevision')
response = self.client.get(url)

json = response.json()
expected = {'detail': 'Authentication credentials were not provided.', 'status_code': 401}

self.assertEqual(json, expected)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
self.assertEqual(self.bc.database.list_of('assignments.Task'), [])

# When: no github account
# Then: response 200
def test__no_github_account(self):
expected = {'data': {'getTask': {'id': random.randint(1, 100)}}}
query = {
self.bc.fake.slug(): self.bc.fake.slug(),
self.bc.fake.slug(): self.bc.fake.slug(),
self.bc.fake.slug(): self.bc.fake.slug(),
}

mock = MagicMock()
mock.raw = iter([json.dumps(expected).encode()])
mock.headers = {'Content-Type': 'application/json'}
code = random.randint(200, 299)
mock.status_code = code
mock.reason = 'OK'

task = {'github_url': self.bc.fake.url()}
model = self.bc.database.create(profile_academy=1, task=task)
self.client.force_authenticate(model.user)

url = reverse_lazy('assignments:me_coderevision') + '?' + self.bc.format.querystring(query)

with patch.multiple('linked_services.core.service.Service',
__init__=MagicMock(return_value=None),
get=MagicMock(return_value=mock)):
response = self.client.get(url)
self.bc.check.calls(Service.get.call_args_list, [])

self.assertEqual(response.getvalue().decode('utf-8'),
'{"detail":"github-account-not-connected","status_code":400}')
self.assertEqual(response.status_code, 400)
self.assertEqual(self.bc.database.list_of('assignments.Task'), [self.bc.format.to_dict(model.task)])

# When: auth in get
# Then: response 200
def test__get__auth(self):
expected = {'data': {'getTask': {'id': random.randint(1, 100)}}}
query = {
self.bc.fake.slug(): self.bc.fake.slug(),
self.bc.fake.slug(): self.bc.fake.slug(),
self.bc.fake.slug(): self.bc.fake.slug(),
}

mock = MagicMock()
mock.raw = iter([json.dumps(expected).encode()])
mock.headers = {'Content-Type': 'application/json'}
code = random.randint(200, 299)
mock.status_code = code
mock.reason = 'OK'

task = {'github_url': self.bc.fake.url()}
credentials_github = {'username': self.bc.fake.slug()}
model = self.bc.database.create(profile_academy=1,
task=task,
credentials_github=credentials_github,
app={'slug': 'rigobot'})
self.client.force_authenticate(model.user)

url = reverse_lazy('assignments:me_coderevision') + '?' + self.bc.format.querystring(query)

token = self.bc.random.string(lower=True, upper=True, symbol=True, number=True, size=20)
with patch('linked_services.django.actions.get_jwt', MagicMock(return_value=token)):
with patch.multiple('requests', get=MagicMock(return_value=mock)):
response = self.client.get(url)
self.bc.check.calls(requests.get.call_args_list, [
call(model.app.app_url + '/v1/finetuning/me/coderevision',
params={
**query,
'github_username': model.credentials_github.username,
},
stream=True,
headers={'Authorization': f'Link App=breathecode,Token={token}'}),
])

self.assertEqual(response.getvalue().decode('utf-8'), json.dumps(expected))
self.assertEqual(response.status_code, code)
self.assertEqual(self.bc.database.list_of('assignments.Task'), [self.bc.format.to_dict(model.task)])
class StreamReaderMock:

def __init__(self, data):
self.data = data

async def read(self):
return self.data


class ResponseMock:

def __init__(self, data, status=200, headers={}):
self.content = data
self.status = status
self.headers = headers

async def __aenter__(self):
return self

async def __aexit__(self, exc_type, exc, tb):
pass

def __enter__(self):
return self

def __exit__(self, exc_type, exc, tb):
pass


@pytest.fixture(autouse=True)
def patch_get(monkeypatch):

def handler(expected, code, headers):

reader = StreamReaderMock(json.dumps(expected).encode())
monkeypatch.setattr('aiohttp.ClientSession.get', MagicMock(return_value=ResponseMock(reader, code, headers)))

yield handler


# When: no auth
# Then: response 401
def test_no_auth(bc: Breathecode, client: APIClient):
url = reverse_lazy('assignments:me_coderevision')
response = client.get(url)

json = response.json()
expected = {'detail': 'Authentication credentials were not provided.', 'status_code': 401}

assert json == expected
assert response.status_code == status.HTTP_401_UNAUTHORIZED
assert bc.database.list_of('assignments.Task') == []


# When: no github account
# Then: response 200
def test__no_github_account(bc: Breathecode, client: APIClient, patch_get):
expected = {'data': {'getTask': {'id': random.randint(1, 100)}}}
query = {
bc.fake.slug(): bc.fake.slug(),
bc.fake.slug(): bc.fake.slug(),
bc.fake.slug(): bc.fake.slug(),
}

code = random.randint(200, 299)
headers = {'Content-Type': 'application/json'}

patch_get(expected, code, headers)

task = {'github_url': bc.fake.url()}
model = bc.database.create(profile_academy=1, task=task)
client.force_authenticate(model.user)

url = reverse_lazy('assignments:me_coderevision') + '?' + bc.format.querystring(query)

response = client.get(url)
assert ClientSession.get.call_args_list == []

assert response.getvalue().decode('utf-8') == '{"detail":"github-account-not-connected","status_code":400}'
assert response.status_code == 400
assert bc.database.list_of('assignments.Task') == [bc.format.to_dict(model.task)]


# When: auth in get
# Then: response 200
def test__get__auth(bc: Breathecode, client: APIClient, patch_get):
expected = {'data': {'getTask': {'id': random.randint(1, 100)}}}
query = {
bc.fake.slug(): bc.fake.slug(),
bc.fake.slug(): bc.fake.slug(),
bc.fake.slug(): bc.fake.slug(),
}

code = random.randint(200, 299)
headers = {'Content-Type': 'application/json'}

patch_get(expected, code, headers)

task = {'github_url': bc.fake.url()}
credentials_github = {'username': bc.fake.slug()}
model = bc.database.create(profile_academy=1,
task=task,
credentials_github=credentials_github,
app={'slug': 'rigobot'})
client.force_authenticate(model.user)

url = reverse_lazy('assignments:me_coderevision') + '?' + bc.format.querystring(query)

token = bc.random.string(lower=True, upper=True, symbol=True, number=True, size=20)
with patch('linked_services.django.actions.get_jwt', MagicMock(return_value=token)):
response = client.get(url)
assert ClientSession.get.call_args_list == [
call(model.app.app_url + '/v1/finetuning/me/coderevision',
params={
**query,
'github_username': model.credentials_github.username,
},
headers={'Authorization': f'Link App=breathecode,Token={token}'}),
]

assert response.getvalue().decode('utf-8') == json.dumps(expected)
assert response.status_code == code
assert bc.database.list_of('assignments.Task') == [bc.format.to_dict(model.task)]
Loading

0 comments on commit 4519beb

Please sign in to comment.