Skip to content
Merged

Dev #22

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
7 changes: 3 additions & 4 deletions apps/authentication/services.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from operator import itemgetter
from typing import Literal

import requests
Expand Down Expand Up @@ -64,9 +63,9 @@ def handle_access_token(access_token, provider: Literal["GOOGLE"]):
response = requests.post(url=info_url, headers=headers, timeout=10)
response.raise_for_status()
user_info_dict = response.json()
given_name, family_name, email = itemgetter("given_name", "family_name", "email")(
user_info_dict
)
given_name = user_info_dict.get("given_name", "")
family_name = user_info_dict.get("family_name", "")
email = user_info_dict["email"]
Comment on lines +66 to +68

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Accessing email directly from user_info_dict may raise a KeyError if the key is missing from the provider's response. It is safer to use .get() and handle the missing value explicitly, for example by raising a ValidationError.

    given_name = user_info_dict.get("given_name", "")
    family_name = user_info_dict.get("family_name", "")
    email = user_info_dict.get("email")
    if not email:
        raise ValidationError({"email": f"Email not provided by {provider}."})

root_user, is_created = RootUser.objects.get_or_create(
email=email,
)
Expand Down
25 changes: 25 additions & 0 deletions apps/organization/migrations/0002_organization_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 5.0.6 on 2026-05-13 04:03

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("organization", "0001_initial"),
]

operations = [
migrations.AddField(
model_name="organization",
name="template",
field=models.CharField(
blank=True,
choices=[
("smart_building", "Smart Building"),
("smart_fleet_monitor", "Smart Fleet Monitor"),
],
max_length=256,
null=True,
),
),
]
4 changes: 4 additions & 0 deletions apps/organization/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging

from common.apps.organization.constants import OrganizationTemplate
from common.models.base_model import BaseModel
from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator
Expand Down Expand Up @@ -32,3 +33,6 @@ class Organization(BaseModel):
rabbitmq_provisioned_at = models.DateTimeField(
blank=True, null=True, help_text="When RabbitMQ resources were provisioned"
)
template = models.CharField(
max_length=256, choices=OrganizationTemplate.choices, blank=True, null=True
)
Comment on lines +36 to +38

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The template field is added here, but it is not being populated in the init_organization management command. This field will remain null in the database for newly initialized organizations.

12 changes: 9 additions & 3 deletions bootstrap_service/management/commands/init_organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def _get_config(self, **kwargs):
return {
"org_name": kwargs.get("org_name") or os.getenv("ORG_NAME"),
"org_slug": kwargs.get("org_slug") or os.getenv("ORG_SLUG"),
"org_template": kwargs.get("org_template") or os.getenv("ORG_TEMPLATE"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The --org-template argument is missing from the add_arguments method in this command. Since docker-entrypoint.sh passes this flag, the command will fail with an 'unrecognized arguments' error, preventing the service from starting.

"owner_email": kwargs.get("owner_email") or os.getenv("OWNER_EMAIL"),
"owner_password": kwargs.get("owner_password")
or os.getenv("OWNER_PASSWORD"),
Expand Down Expand Up @@ -136,7 +137,7 @@ def _create_organization_with_roles(self, org_id, 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):
def _send_celery_task(self, org_id, org_name, org_slug, org_template, user):
"""Send initialization task to Celery."""
send_task(
name="new_organization",
Expand All @@ -145,6 +146,7 @@ def _send_celery_task(self, org_id, org_name, org_slug, user):
"name": org_name,
"slug_name": org_slug,
"is_active": True,
"template": org_template,
"owner": model_to_dict(
user,
fields=[
Expand Down Expand Up @@ -198,7 +200,11 @@ def _delete_organization(self, provisioner, organization):

def handle(self, *args, **kwargs):
config = self._get_config(**kwargs)
org_name, org_slug = config["org_name"], config["org_slug"]
org_name, org_slug, org_template = (
config["org_name"],
config["org_slug"],
config.get("org_template", ""),
)
owner_email, owner_password = config["owner_email"], config["owner_password"]
encrypted_password = make_password(owner_password)
org_id = str(uuid.uuid4())
Expand Down Expand Up @@ -235,7 +241,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)
self._send_celery_task(org_id, org_name, org_slug, org_template, user)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The org_template value is passed to the Celery task but is not used to populate the template field of the Organization model during creation. The _create_organization_with_roles method should be updated to accept this parameter and include it in the Organization.objects.create call.

else:
self.stdout.write(
self.style.WARNING(
Expand Down
2 changes: 2 additions & 0 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ echo "Organization Service Starting..."
echo "ORG_NAME: ${ORG_NAME:-not set}"
echo "ORG_SLUG: spacedf"
echo "OWNER_EMAIL: ${OWNER_EMAIL:-not set}"
echo "ORG_TEMPLATE: ${ORG_TEMPLATE:-not set}"

echo "Waiting for RabbitMQ AMQP on rabbitmq:5672..."
until nc -z rabbitmq 5672; do
Expand Down Expand Up @@ -33,6 +34,7 @@ echo "Running organization initialization..."
python manage.py init_organization \
--org-name="${ORG_NAME}" \
--org-slug="spacedf" \
--org-template="${ORG_TEMPLATE}" \
--owner-email="${OWNER_EMAIL}" \
--owner-password="${OWNER_PASSWORD}"

Expand Down
Loading