Skip to content
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
33 changes: 17 additions & 16 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
## What?
Explain the changes you've made
## Why?
The “why” tells us what business or engineering goal this change achieves
## How?

## Testing?
[ ] Functional Testing

[ ] Security

[ ] Performance
<!-- Explain the changes you've made in this pull request. Provide a brief summary of the features, bug fixes, or refactors included. -->

[ ] Error Handling
## Why?

[ ] Code Quality
<!-- Describe the business or technical reason behind these changes. What goal does this PR achieve? -->

[ ] Documentation
## How?

[ ] Database
<!-- Detail how the changes were implemented. Include specifics on the code, technologies, or processes used. -->

[ ] Deployment
## Testing?

[ ] Final Review
- [ ] Functional Testing
- [ ] Security
- [ ] Performance
- [ ] Error Handling
- [ ] Code Quality
- [ ] Documentation
- [ ] Database
- [ ] Deployment
- [ ] Final Review

## Anything Else?

<!-- Add any further context, suggestions, or future considerations. -->
10 changes: 7 additions & 3 deletions apps/authentication/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ def get_tokens(self):
self.user, organization_slug=default_organization_slug
)

return refresh_token, access_token
return refresh_token, access_token, default_organization_slug

def get_response_data(self):
refresh_token, access_token = self.get_tokens()
refresh_token, access_token, default_organization = self.get_tokens()

return {"refresh": str(refresh_token), "access": str(access_token)}
return {
"refresh": str(refresh_token),
"access": str(access_token),
"default_organization": default_organization,
}


class AuthTokenPairSerializer(TokenPairSerializer):
Expand Down
45 changes: 21 additions & 24 deletions bootstrap_service/management/commands/init_organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@
import uuid
from datetime import datetime

from common.celery.task_senders import send_task
from common.rabitmq.rabbitmq_provisioner import RabbitMQProvisioner
from django.conf import settings
from django.contrib.auth.hashers import make_password
from django.core.management.base import BaseCommand
from django.forms.models import model_to_dict
from django.utils import timezone
from django.utils.module_loading import import_string
from kombu import Exchange

from apps.authentication.models import RootUser
from apps.organization.models import Organization
Expand Down Expand Up @@ -102,9 +101,10 @@ def _publish_org_event(self, org_id, org_slug, org_name, result):
},
)

def _create_organization_with_roles(self, org_name, org_slug, result):
def _create_organization_with_roles(self, org_id, org_name, org_slug, result):
"""Create organization with default policies and roles."""
organization = Organization.objects.create(
id=org_id,
name=org_name,
slug_name=org_slug,
logo="",
Expand Down Expand Up @@ -135,36 +135,33 @@ def _create_organization_with_roles(self, org_name, org_slug, result):
self.stdout.write(self.style.SUCCESS("Created default roles"))
return organization, owner_role

def _send_celery_task(self, org_id, org_name, org_slug, user, encrypted_password):
def _send_celery_task(self, org_id, org_name, org_slug, user):
"""Send initialization task to Celery."""
celery_app = import_string(settings.CELERY_APP)
celery_app.send_task(
name="spacedf.tasks.new_organization",
exchange=Exchange("new_organization", type="fanout"),
routing_key="new_organization",
kwargs={
send_task(
name="new_organization",
message={
"id": org_id,
"name": org_name,
"slug_name": org_slug,
"is_active": True,
"owner": {
"id": str(user.id),
"email": user.email,
"password": encrypted_password,
},
"owner": model_to_dict(
user,
fields=[
"id",
"email",
"password",
],
),
"created_at": datetime.now().isoformat(),
"updated_at": datetime.now().isoformat(),
},
)

def _send_delete_celery_task(self, org_slug):
"""Send organization deletion task to Celery."""
celery_app = import_string(settings.CELERY_APP)
celery_app.send_task(
name="spacedf.tasks.delete_organization",
exchange=Exchange("delete_organization", type="fanout"),
routing_key="delete_organization",
kwargs={
send_task(
name="delete_organization",
message={
"slug_name": org_slug,
},
)
Expand Down Expand Up @@ -227,7 +224,7 @@ def handle(self, *args, **kwargs):
)
self.stdout.write(self.style.SUCCESS(f"Created owner user: {owner_email}"))
_, owner_role = self._create_organization_with_roles(
org_name, org_slug, result
org_id, org_name, org_slug, result
)
OrganizationRoleUser(root_user=user, organization_role=owner_role).save()
self.stdout.write(
Expand All @@ -236,7 +233,7 @@ def handle(self, *args, **kwargs):

# Publish organization event
self._publish_org_event(org_id, org_slug, org_name, result)
self._send_celery_task(org_id, org_name, org_slug, user, encrypted_password)
self._send_celery_task(org_id, org_name, org_slug, user)
else:
self.stdout.write(
self.style.WARNING(
Expand Down
12 changes: 12 additions & 0 deletions bootstrap_service/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@
ORG_DISCOVERY_ROUTING_KEY = "org.discovery.request"

# Celery Configuration (for sending tasks only)
CELERY_ACKS_LATE = True
CELERYD_PREFETCH_MULTIPLIER = 1
CELERY_APP = "bootstrap_service.celery.app"
CELERY_BROKER_URL = os.getenv("CELERY_BROKER_URL", "amqp://default:password@rabbitmq")
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True
Expand Down Expand Up @@ -206,3 +208,13 @@
DEFAULT_FROM_EMAIL = os.getenv("DEFAULT_FROM_EMAIL", "")
EMAIL_HOST_USER = os.getenv("EMAIL_HOST_USER", "")
EMAIL_HOST_PASSWORD = os.getenv("EMAIL_HOST_PASSWORD", "")

CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": os.getenv("REDIS_HOST", "redis://127.0.0.1:6379/1"),
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
}
}
8 changes: 4 additions & 4 deletions bootstrap_service/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@

schema_view = get_schema_view(
openapi.Info(
title="SPACEDF CONSOLE API",
title="SPACEDF BOOTSTRAP API",
default_version="v1",
terms_of_service="https://www.google.com/policies/terms/",
contact=openapi.Contact(email="contact@snippets.local"),
license=openapi.License(name="BSD License"),
terms_of_service="https://spacedf.com/terms-of-service",
contact=openapi.Contact(email="hello@df.technology"),
license=openapi.License(name="Apache 2.0"),
),
public=True,
permission_classes=[permissions.AllowAny],
Expand Down
14 changes: 9 additions & 5 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,19 @@ echo "EMQX is ready"
echo "Running database migrations..."
python manage.py migrate

echo "Starting Celery worker..."
celery -A bootstrap_service worker -l info -c 1 &
sleep 5

echo "Running organization initialization..."
python manage.py init_organization \
--org-name="${ORG_NAME}" \
--org-slug="${ORG_SLUG}" \
--owner-email="${OWNER_EMAIL}" \
--owner-password="${OWNER_PASSWORD}"

echo "Organization initialization complete"

# Start Gunicorn and Celery
gunicorn --worker-class gevent --bind 0.0.0.0:80 --access-logfile - bootstrap_service.wsgi \
& celery -A bootstrap_service worker -l info -c 1
echo "Starting Gunicorn..."
exec gunicorn bootstrap_service.wsgi:application \
--worker-class gevent \
--bind 0.0.0.0:80 \
--access-logfile -
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ django-environ==0.11.2
pika==1.3.2
django-redis==5.4.0
boto3==1.37.13
psycopg2-binary==2.9.9
psycopg2-binary==2.9.9
django_tenants==3.6.1
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules,venv

[isort]
line_length = 88
known_first_party = console-service
known_first_party = bootstrap-service
multi_line_output = 3
default_section = THIRDPARTY
skip = venv/
Expand All @@ -14,7 +14,7 @@ force_grid_wrap = 0
use_parentheses = true

[coverage:run]
include = console-service/*
include = bootstrap-service/*
omit = *migrations*, *tests*
plugins =
django_coverage_plugin