Repository: armada-ths/ais

Issue:
Organization API absolute URL for images broken
https://ais.armada.nu/api/organization/

Because of S3 buckets and an ancient absolute URL generator, a common URL to see is:

```
https://ais.armada.nu/https://armada-ais-files.s3.amazonaws.com/profiles/picture_original/c388dcbddb1448 ...
```


Discussion:

Resolving patch:
diff --git a/api/serializers.py b/api/serializers.py
--- a/api/serializers.py
+++ b/api/serializers.py
@@ -25,11 +25,19 @@ def absolute_url(request, path):
     return "{}{}/{}".format(protocol, url, path)
 
 
+def image_url_or_missing_relative(image, missing=MISSING_IMAGE):
+    return image.url if image else missing
+
+
+# This function does not handle trailing slashes
+# A common response is "http://localhost:3000//static/images/no-image.png"
+#
+# Another problem is the usage of ais buckets
+# A common response is "https://ais.armada.nu/https://armada-ais-files.s3.amazonaws.com/profiles/picture_original/3d867d2a75f84e3eb32..."
+#
+# Please use `image_url_or_missing_relative`
 def image_url_or_missing(request, image, missing=MISSING_IMAGE):
-    if image:
-        return absolute_url(request, image.url)
-    else:
-        return absolute_url(request, missing)
+    return absolute_url(request, image.url if image else missing)
 
 
 def obj_name(obj):
@@ -188,6 +196,45 @@ def partner(request, partner):
     )
 
 
+def person_v2(user):
+    # Check that there is a profile for the user
+    try:
+        profile = user.profile
+
+        try:
+            programme = profile.programme.name
+        except AttributeError:
+            programme = None
+
+        return OrderedDict(
+            [
+                ("id", profile.user.pk),
+                ("name", profile.user.get_full_name()),
+                (
+                    "picture",
+                    image_url_or_missing_relative(
+                        profile.picture_original, MISSING_PERSON
+                    ),
+                ),
+                ("linkedin_url", profile.linkedin_url),
+                ("programme", programme),
+                ("role", user.delegated_role.__str__()),
+            ]
+        )
+    except Profile.DoesNotExist:  # There is no profile for this user
+        return OrderedDict(
+            [
+                ("id", user.pk),
+                ("name", user.user.get_full_name()),
+                (
+                    "role",
+                    user.delegated_role.__str__() if user.delegated_role else None,
+                ),
+            ]
+        )
+
+
+# Todo: Deprecate the usage of this serializer (used by armada.nu)
 def person(request, person, role):
     # Check that there are a profile for the user
     try:
diff --git a/api/urls.py b/api/urls.py
--- a/api/urls.py
+++ b/api/urls.py
@@ -10,6 +10,7 @@
     url(r"^fair/", include("fair.api_urls")),
     url(r"^catalogueselections/", views.catalogueselections),
     url(r"^news/", views.news),
+    url(r"^organization/v2", views.organization_v2),
     url(r"^organization/", views.organization),
     url(r"^partners/", views.partners),
     url(r"^questions/?$", views.questions),
diff --git a/api/views.py b/api/views.py
--- a/api/views.py
+++ b/api/views.py
@@ -32,7 +32,7 @@
     CatalogueCompetence,
 )  # CatalogueBenefit
 from exhibitors.api import serialize_exhibitor
-from fair.models import Partner, Fair, current_fair
+from fair.models import Partner, Fair, OrganizationGroup, current_fair
 from matching.models import StudentQuestionBase as QuestionBase, WorkField, Survey
 from news.models import NewsArticle
 from recruitment.models import RecruitmentPeriod, RecruitmentApplication
@@ -325,6 +325,7 @@ def partners(request):
     return JsonResponse(data, safe=False)
 
 
+# Todo: Deprecate the usage of this serializer (used by armada.nu)
 @cache_page(60 * 5)
 def organization(request):
     """
@@ -344,6 +345,42 @@ def organization(request):
     return JsonResponse(data, safe=False)
 
 
+@cache_page(60 * 5)
+def organization_v2(request):
+    fair = get_object_or_404(Fair, current=True)
+    groups = OrganizationGroup.objects.filter(fair=fair)
+    people = lambda group: [
+        serializers.person_v2(
+            user,
+        )
+        for user in RecruitmentApplication.objects.select_related("user")
+        .filter(
+            delegated_role__organization_group=group,
+            status="accepted",
+            recruitment_period__fair=fair,
+        )
+        .order_by(
+            "delegated_role__organization_group",
+            "recruitment_period__start_date",
+            "delegated_role",
+            "user__first_name",
+            "user__last_name",
+        )
+    ]
+
+    result = [
+        OrderedDict(
+            [
+                ("name", group.name),
+                ("people", people(group)),
+            ]
+        )
+        for group in groups
+    ]
+
+    return JsonResponse(result, safe=False)
+
+
 def status(request):
     hostname = platform.node()
     python_version = platform.python_version()


Test patch: