Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development #1525

Merged
merged 2 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ django-storages = {extras = ["google"] }
aiohttp = {extras = ["speedups"] }
aiodns = "*"
eventlet = "*"
linked-services = {extras = ["django", "aiohttp", "requests"] }
celery-task-manager = {extras = ["django"] }
django-sql-explorer = {extras = ["xls"] }
contextlib2 = "*"
Expand All @@ -157,3 +156,4 @@ pyright = "*"
mypy = "*"
python-magic = "*"
uvicorn = {extras = ["standard"], version = "*"}
linked-services = {extras = ["requests", "django", "aiohttp"], version = "*"}
2,582 changes: 1,337 additions & 1,245 deletions Pipfile.lock

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions breathecode/activity/management/commands/upload_activities.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import os

from django.core.cache import cache
from django.core.management.base import BaseCommand
from django.utils import timezone
from django.core.cache import cache

from breathecode.activity import tasks

IS_DJANGO_REDIS = hasattr(cache, "delete_pattern")
IS_DJANGO_REDIS = hasattr(cache, "fake") is False


def db_backup_bucket():
Expand Down
4 changes: 2 additions & 2 deletions breathecode/activity/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import Optional

import zstandard
from capyc.core.managers import feature
from celery import shared_task
from django.core.cache import cache
from django.utils import timezone
Expand All @@ -24,7 +25,6 @@
from breathecode.utils import NDB
from breathecode.utils.decorators import TaskPriority
from breathecode.utils.redis import Lock
from capyc.core.managers import feature

from .models import StudentActivity

Expand All @@ -38,7 +38,7 @@ def get_activity_sampling_rate():
return 60


IS_DJANGO_REDIS = hasattr(cache, "delete_pattern")
IS_DJANGO_REDIS = hasattr(cache, "fake") is False

API_URL = os.getenv("API_URL", "")

Expand Down
16 changes: 16 additions & 0 deletions breathecode/authenticate/migrations/0062_delete_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Generated by Django 5.1.4 on 2024-12-28 22:39

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("authenticate", "0061_googlewebhook_type"),
]

operations = [
migrations.DeleteModel(
name="App",
),
]
17 changes: 1 addition & 16 deletions breathecode/authenticate/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,7 @@ def __init__(self, *args, **kwargs):
regex=r"^\+?1?\d{9,15}$",
message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.",
)
phone = models.CharField(
validators=[phone_regex], max_length=17, blank=True, default=""
) # validators should be a list
phone = models.CharField(validators=[phone_regex], max_length=17, blank=True, default="")

status = models.CharField(max_length=15, choices=PROFILE_ACADEMY_STATUS, default=INVITED, db_index=True)

Expand Down Expand Up @@ -698,19 +696,6 @@ class GitpodUser(models.Model):
)


class App(models.Model):
"""
The only reason for keeping this model is because this model is really indestructible.

Remove it as soon as Django team let us do it.
"""

def __init__(self, *args, **kwargs):
raise DeprecationWarning("authenticate.App was deprecated, use linked_services.App instead")

name = models.CharField(max_length=25, unique=True, help_text="Descriptive and unique name of the app")


class GoogleWebhook(models.Model):
class Status(models.TextChoices):
PENDING = ("PENDING", "Pending")
Expand Down
95 changes: 94 additions & 1 deletion breathecode/authenticate/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import random
import urllib.parse

import capyc.django.serializer as capy
from capyc.core.i18n import translation
from capyc.rest_framework.exceptions import ValidationException
from django.contrib.auth.models import Permission, User
Expand All @@ -14,7 +15,7 @@
from task_manager.django.actions import schedule_task

import breathecode.notify.actions as notify_actions
from breathecode.admissions.models import Academy, Cohort, CohortUser
from breathecode.admissions.models import Academy, City, Cohort, CohortUser, Country
from breathecode.authenticate.actions import get_app_url, get_user_settings
from breathecode.authenticate.tasks import verify_user_invite_email
from breathecode.events.models import Event
Expand All @@ -37,6 +38,98 @@
logger = logging.getLogger(__name__)


class CapyAppUserSerializer(capy.Serializer):
model = User
path = "/v1/auth/app/user"
fields = {
"default": (
"id",
"username",
"first_name",
"last_name",
"email",
),
"timestamps": (
"date_joined",
"last_login",
),
}
filters = (
"id",
"username",
"first_name",
"last_name",
"email",
"date_joined",
"last_login",
)


class CapyAppCountrySerializer(capy.Serializer):
model = Country
path = "/v1/auth/app/country"
fields = {
"default": ("code", "name"),
}
filters = (
"code",
"name",
)


class CapyAppCitySerializer(capy.Serializer):
model = City
path = "/v1/auth/app/city"
fields = {"default": ("id", "name", "country"), "country": ("country[]",)}
filters = ("name",)
country = CapyAppCountrySerializer()


class CapyAppAcademySerializer(capy.Serializer):
model = Academy
path = "/v1/auth/app/academy"
fields = {
"default": ("id", "name", "slug", "legal_name", "status"),
"meta": ("white_labeled", "available_as_saas", "is_hidden_on_prework", "timezone"),
"marketing": ("active_campaign_slug", "logistical_information"),
"urls": ("logo_url", "icon_url", "website_url", "white_label_url"),
"emails": ("marketing_email", "feedback_email"),
"social": ("linkedin_url", "youtube_url"),
"location": ("city[]", "country[]", "latitude", "longitude", "zip_code", "street_address"),
"timestamps": ("created_at", "updated_at"),
}
filters = ("name", "slug", "legal_name", "status", "created_at", "available_as_saas")
country = CapyAppCountrySerializer()
city = CapyAppCitySerializer()


class CapyAppProfileAcademySerializer(capy.Serializer):
model = ProfileAcademy
path = "/v1/auth/app/student"
fields = {
"default": (
"id",
"first_name",
"last_name",
"status",
"email",
"phone",
"user",
"academy",
),
"address": ("address",),
"academy": ("academy[]",),
"user": ("user[]",),
"timestamps": (
"created_at",
"updated_at",
),
}
filters = ("status", "email", "id")
academy = CapyAppAcademySerializer()
user = CapyAppUserSerializer()


class GetSmallCohortSerializer(serpy.Serializer):
"""The serializer schema definition."""

Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import capyc.django.serializer as capy

from breathecode.authenticate.models import Academy
from breathecode.authenticate.serializers import CapyAppAcademySerializer


def test_is_capy_serializer():
serializer = CapyAppAcademySerializer()
assert isinstance(serializer, capy.Serializer)


def test_fields():
assert CapyAppAcademySerializer.fields == {
"default": ("id", "name", "slug", "legal_name", "status"),
"meta": ("white_labeled", "available_as_saas", "is_hidden_on_prework", "timezone"),
"marketing": ("active_campaign_slug", "logistical_information"),
"urls": ("logo_url", "icon_url", "website_url", "white_label_url"),
"emails": ("marketing_email", "feedback_email"),
"social": ("linkedin_url", "youtube_url"),
"location": ("city[]", "country[]", "latitude", "longitude", "zip_code", "street_address"),
"timestamps": ("created_at", "updated_at"),
}


def test_filters():
assert CapyAppAcademySerializer.filters == (
"name",
"slug",
"legal_name",
"status",
"created_at",
"available_as_saas",
)


def test_path():
assert CapyAppAcademySerializer.path == "/v1/auth/app/academy"


def test_model():
assert CapyAppAcademySerializer.model == Academy


def test_references():
serializer = CapyAppAcademySerializer()

result = {}
for field in dir(serializer):
if field.startswith("_"):
continue

if isinstance(x := getattr(serializer, field), capy.Serializer):
result[field] = x.__module__ + "." + x.__class__.__name__

assert result == {
"city": "breathecode.authenticate.serializers.CapyAppCitySerializer",
"country": "breathecode.authenticate.serializers.CapyAppCountrySerializer",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import capyc.django.serializer as capy

from breathecode.admissions.models import City
from breathecode.authenticate.serializers import CapyAppCitySerializer, CapyAppCountrySerializer


def test_is_capy_serializer():
serializer = CapyAppCitySerializer()
assert isinstance(serializer, capy.Serializer)


def test_fields():
assert CapyAppCitySerializer.fields == {
"default": ("id", "name", "country"),
"country": ("country[]",),
}


def test_filters():
assert CapyAppCitySerializer.filters == ("name",)


def test_path():
assert CapyAppCitySerializer.path == "/v1/auth/app/city"


def test_model():
assert CapyAppCitySerializer.model == City


def test_references():
serializer = CapyAppCitySerializer()

result = {}
for field in dir(serializer):
if field.startswith("_"):
continue

if isinstance(x := getattr(serializer, field), capy.Serializer):
result[field] = x.__module__ + "." + x.__class__.__name__

assert result == {"country": "breathecode.authenticate.serializers.CapyAppCountrySerializer"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import capyc.django.serializer as capy

from breathecode.admissions.models import Country
from breathecode.authenticate.serializers import CapyAppCountrySerializer


def test_is_capy_serializer():
serializer = CapyAppCountrySerializer()
assert isinstance(serializer, capy.Serializer)


def test_fields():
assert CapyAppCountrySerializer.fields == {
"default": ("code", "name"),
}


def test_filters():
assert CapyAppCountrySerializer.filters == (
"code",
"name",
)


def test_path():
assert CapyAppCountrySerializer.path == "/v1/auth/app/country"


def test_model():
assert CapyAppCountrySerializer.model == Country


def test_references():
serializer = CapyAppCountrySerializer()

result = {}
for field in dir(serializer):
if field.startswith("_"):
continue

if isinstance(x := getattr(serializer, field), capy.Serializer):
result[field] = x.__module__ + "." + x.__class__.__name__

assert result == {}
Loading
Loading