Skip to content

Commit

Permalink
add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
jefer94 committed Sep 5, 2024
1 parent 643b9eb commit 5fffa6a
Show file tree
Hide file tree
Showing 11 changed files with 452 additions and 306 deletions.
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,4 @@ google-apps-meet = "*"
google-auth-httplib2 = "*"
google-auth-oauthlib = "*"
capy-core = {extras = ["django"], version = "*"}
google-api-python-client = "*"
494 changes: 232 additions & 262 deletions Pipfile.lock

Large diffs are not rendered by default.

17 changes: 16 additions & 1 deletion breathecode/authenticate/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,22 @@ def save(self, *args, **kwargs):
class AcademyAuthSettings(models.Model):
academy = models.OneToOneField(Academy, on_delete=models.CASCADE)
github_username = models.SlugField(max_length=40, blank=True)
github_owner = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, default=None, null=True)
github_owner = models.ForeignKey(
User,
on_delete=models.SET_NULL,
blank=True,
default=None,
null=True,
help_text="Github auth token for this user will be used for any admin call to the google cloud api, for example: inviting users to the academy",
)
google_cloud_owner = models.ForeignKey(
User,
on_delete=models.SET_NULL,
blank=True,
default=None,
null=True,
help_text="Google auth token for this user will be used for any admin call to the google cloud api, for example: creating classroom video calls",
)
github_default_team_ids = models.CharField(
max_length=40,
blank=True,
Expand Down
39 changes: 37 additions & 2 deletions breathecode/services/google_meet/google_meet.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import os.path
import pickle
from typing import Optional, TypedDict, Unpack

import google.apps.meet_v2.services.conference_records_service.pagers as pagers
from asgiref.sync import async_to_sync
from google.apps import meet_v2
from google.apps.meet_v2.types import Space
from google.auth.transport.requests import Request
from google.protobuf.field_mask_pb2 import FieldMask
from google_auth_oauthlib.flow import InstalledAppFlow

__all__ = ["GoogleMeet"]

Expand Down Expand Up @@ -78,6 +82,33 @@ class ListParticipantsRequest(TypedDict):
filter: str # in EBNF format, start_time and end_time


# Scopes for Google Calendar API (used for creating Google Meet links)
SCOPES = ["https://www.googleapis.com/auth/calendar"]
CREDENTIAL_FILE_NAME = "google_cloud_oauth_token.pickle"


def get_credentials():
creds = None
# Check if google_meet_oauth_token.pickle exists (to reuse the token)
if os.path.exists(CREDENTIAL_FILE_NAME):
with open(CREDENTIAL_FILE_NAME, "rb") as token:
creds = pickle.load(token)

# If there are no valid credentials available, prompt the user to log in
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file("client_secret.json", SCOPES)
creds = flow.run_local_server(port=0)

# Save the credentials for the next run
with open(CREDENTIAL_FILE_NAME, "wb") as token:
pickle.dump(creds, token)

return creds


class GoogleMeet:
_spaces_service_client: Optional[meet_v2.SpacesServiceAsyncClient]
_conference_records_service_client: Optional[meet_v2.ConferenceRecordsServiceAsyncClient]
Expand All @@ -92,13 +123,17 @@ def __init__(self):

async def spaces_service_client(self):
if self._spaces_service_client is None:
self._spaces_service_client = meet_v2.SpacesServiceAsyncClient()
credentials = get_credentials()
self._spaces_service_client = meet_v2.SpacesServiceAsyncClient(credentials=credentials)

return self._spaces_service_client

async def conference_records_service_client(self):
if self._conference_records_service_client is None:
self._conference_records_service_client = meet_v2.ConferenceRecordsServiceAsyncClient()
credentials = get_credentials()
self._conference_records_service_client = meet_v2.ConferenceRecordsServiceAsyncClient(
credentials=credentials
)

return self._conference_records_service_client

Expand Down
4 changes: 2 additions & 2 deletions breathecode/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
]

GRAPHENE = {"SCHEMA": "breathecode.schema.schema"}
IS_TEST_ENV = os.getenv("ENV") == "test"

if os.getenv("ALLOW_UNSAFE_CYPRESS_APP") or ENVIRONMENT == "test":
INSTALLED_APPS.append("breathecode.cypress")
Expand Down Expand Up @@ -170,7 +171,7 @@
}
# STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

else:
elif IS_TEST_ENV is False:
INSTALLED_APPS += [
"whitenoise.runserver_nostatic",
]
Expand Down Expand Up @@ -233,7 +234,6 @@
# Disable Django's logging setup
LOGGING_CONFIG = None

IS_TEST_ENV = os.getenv("ENV") == "test"
LOG_LEVEL = os.environ.get("LOG_LEVEL", "INFO").upper()

# this prevent the duplications of logs because heroku redirect the output to Coralogix
Expand Down
10 changes: 5 additions & 5 deletions docs/essential/django-rest-framework/serializers.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Serializers

A serializer is an element (a [class](<https://en.wikipedia.org/wiki/Class_(computer_programming)>) this case) that translates and [object](<https://en.wikipedia.org/wiki/Object_(computer_science)>) ([Object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)) and generate an output that should be useful by something, in Django a serializer is used to format the object before be sent. We just using the [Django Rest Framework](https://www.django-rest-framework.org) Serializers for POST and PUT methods, for the GET method we are using [Serpy](../serpy/introduction) because it is faster than DRF Serializers.
A serializer is an element (a [class](https://en.wikipedia.org/wiki/Class_(computer_programming)) in this case) that translates an [object](https://en.wikipedia.org/wiki/Object_(computer_science)) ([Object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming)) and generates an output that should be useful for something. In Django, a serializer is used to format the object before it is sent. We are using the [Django Rest Framework](https://www.django-rest-framework.org) Serializers for POST and PUT methods, and for the GET method we are using [Serpy](../../serpy/) because it is faster than DRF Serializers.

Related articles:

- [HTTP](https://en.wikipedia.org/wiki/HTTP).
- [REST](https://en.wikipedia.org/wiki/REST).
- [HTTP](https://en.wikipedia.org/wiki/HTTP)
- [REST](https://en.wikipedia.org/wiki/REST)

## Writing Serializers

Read [this](https://www.django-rest-framework.org/tutorial/1-serialization/).

## Where is the admin?
## Where are the serializers?

It where in `breathecode/APP_NAME/serializers.py`.
They are located in `breathecode/APP_NAME/serializers.py`.
File renamed without changes.
33 changes: 0 additions & 33 deletions docs/testing/runing-tests.md

This file was deleted.

38 changes: 38 additions & 0 deletions docs/testing/running-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Running tests

## Run a test file

```bash
pipenv run test breathecode/payments/tests/urls/tests_me_service_slug_consumptionsession_hash.py
```

### Pytest options

- `-v`: verbose
- `-vv`: more verbose
- `-s`: don't capture the stdout, useful when the test execution won't end.
- `-k`: only run test methods and classes that match the pattern or substring.

## Run tests in parallel

```bash
pipenv run ptest
```

## Run tests in parallel in a module

```bash
pipenv run ptest ./breathecode/
```

## Run coverage in parallel

```bash
pipenv run pcov
```

## Run coverage in parallel in a module

```bash
pipenv run pcov breathecode.admissions
```
117 changes: 117 additions & 0 deletions docs/workflows/file-uploading.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# File uploading

## Steps

- Get operation type meta.
- Split file into chunks.
- Check if chunk lenght is less than `max_chunks` or `null`.
- Upload each chunk.
- Process the file and send the metadata if required.
- If the file is not processed automatically you should pass the file id to another endpoint.

### Notes

- For user uploading, use `/v2/media/me/chunk` and `/v2/media/me/chunk/upload`.
- For academy uploading, use `/v2/media/academy/chunk` and `/v2/media/academy/chunk/upload` with the `Academy` header.
- Status `TRANSFERRING` means that the file is being processed.
- Status `CREATED` means that the `file.id` must be provided to another endpoint for processing.

## Get available operation types

### Request

```http
GET /v2/media/operationtype HTTP/1.1
Host: breathecode.herokuapp.com
```

### Response

```json
[
    "media",
    "proof-of-payment"
]
```

## Get operation type meta

### Request

```http
GET /v2/media/operationtype/media HTTP/1.1
Host: breathecode.herokuapp.com
```


### Response

```json
{
    "chunk_size": 10485760,
    "max_chunks": null
}
```

## Upload chunk

### Request

```http
POST /v2/media/me/chunk HTTP/1.1
Host: breathecode.herokuapp.com
Content-Type: multipart/form-data; boundary=...
{
"operation_type": "media",
"total_chunks": 3,
"chunk": chunk,
"chunk_index": 0
}
```

### Response

```json
{
    "academy": null,
    "chunk_index": 0,
    "mime": "image/png",
    "name": "chunk.png",
    "operation_type": "media",
    "total_chunks": 3,
    "user": 1
}
```

## End file uploading and ask for processing

### Request

```http
POST /v2/media/me/chunk/upload HTTP/1.1
Host: breathecode.herokuapp.com
Content-Type: application/json
{
"operation_type": "media",
"total_chunks": 3,
"filename": "chunk.png",
"mime": "image/png",
"meta": "{\"slug\":\"my-media\",\"name\":\"my-name\",\"categories\":[\"my-category\"],\"academy\":1}"
}
```

### Response

```json
{
    "id": 1,
    "academy": null,
    "mime": "image/png",
    "name": "a291e39ac495b2effd38d508417cd731",
    "operation_type": "media",
    "user": 1,
    "status": "TRANSFERRING"
}
```
5 changes: 4 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ nav:
- "advanced/celery/routing.md"
- "advanced/celery/settings.md"
- Testing:
- "testing/runing-tests.md"
- "testing/running-tests.md"
- "testing/parametrize.md"
- Mixins:
- "bc": "testing/mixins/bc.md"
- "bc.fake": "testing/mixins/bc-fake.md"
Expand All @@ -87,6 +88,8 @@ nav:
- Mocks:
- "testing/mocks/using-mocks.md"
- "testing/mocks/mock-requests.md"
- Workflows:
- "workflows/file-uploading.md"
- Infrastructure:
- "infrastructure/journal.md"
- "infrastructure/web.md"
Expand Down

0 comments on commit 5fffa6a

Please sign in to comment.