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
8 changes: 8 additions & 0 deletions aboutcode/federatedcode/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import os
from typing import Union
from urllib.parse import quote
from urllib.parse import urljoin

import requests
Expand Down Expand Up @@ -60,3 +61,10 @@ def get_package_scan(purl: Union[PackageURL, str]):
if response.status_code == 404:
raise ScanNotAvailableError(f"No scan available for {purl!s}")
raise err


def subscribe_package(federatedcode_host, remote_username, purl):
"""Subscribe package for their metadata update from FederatedCode."""

url_path = f"api/v0/users/@{remote_username}/subscribe/?purl={quote(purl)}"
return requests.get(urljoin(federatedcode_host, url_path))
Empty file.
Empty file.
38 changes: 38 additions & 0 deletions aboutcode/federatedcode/contrib/django/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# FederatedCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
# See https://github.com/nexB/federatedcode for support or download.
# See https://aboutcode.org for more information about AboutCode.org OSS projects.
#

from django.db import models
from django.utils.translation import gettext_lazy as _


class FederatedCodePackageActivityMixin(models.Model):
"""Abstract Model for FederatedCode package activity."""

author = models.CharField(
max_length=300,
null=False,
blank=False,
help_text=_("Author of package activity."),
)

content = models.JSONField(
null=False,
blank=False,
help_text=_("Package activity content."),
)

activity_update_date = models.DateTimeField(
null=True,
blank=True,
db_index=True,
help_text=_("Timestamp indicating when original activity was last updated."),
)

class Meta:
abstract = True
35 changes: 35 additions & 0 deletions aboutcode/federatedcode/contrib/django/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# FederatedCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
# See https://github.com/nexB/federatedcode for support or download.
# See https://aboutcode.org for more information about AboutCode.org OSS projects.
#


import saneyaml


def get_package_activity_type(activity: dict) -> str:
return activity.get("type")


def get_package_activity_object(activity: dict) -> dict:
return activity.get("object")


def get_package_activity_author(activity: dict) -> str:
activity_object = get_package_activity_object(activity)
return activity_object.get("author")


def get_package_activity_content(activity: dict) -> dict:
activity_object = get_package_activity_object(activity)
content = activity_object.get("content")
return saneyaml.load(content)


def get_package_activity_update_date(activity: dict) -> str:
activity_object = get_package_activity_object(activity)
return activity_object.get("update_date")
4 changes: 2 additions & 2 deletions fedcode/management/commands/federate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# See https://aboutcode.org for more information about AboutCode.org OSS projects.
#

import json
from traceback import format_exc as traceback_format_exc

import requests
Expand All @@ -24,9 +25,8 @@ def send_fed_req_task():
if not rq.done:
try:
headers = {"Content-Type": "application/json"}
requests.post(rq.target, json=rq.body, headers=headers)
requests.post(rq.target, json=json.loads(rq.body), headers=headers)
rq.done = True
rq.save()
except Exception as e:
rq.error_message = f"Failed to federate {rq!r} {e!r} \n {traceback_format_exc()}"
finally:
Expand Down
8 changes: 6 additions & 2 deletions fedcode/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#

import uuid
from urllib.parse import urljoin

from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericForeignKey
Expand Down Expand Up @@ -424,11 +425,13 @@ def absolute_url_ap(self):
@property
def inbox_url(self):
if not self.local:
return self.remote_actor.url
return urljoin(self.remote_actor.url, "inbox")
return full_reverse("user-inbox", self.user.username)

@property
def outbox_url(self):
if not self.local:
return urljoin(self.remote_actor.url, "outbox")
return full_reverse("user-outbox", self.user.username)

@property
Expand All @@ -444,10 +447,11 @@ def key_id(self):

@property
def to_ap(self):
name = self.user.username if self.local else self.remote_actor.username
return {
"id": self.absolute_url_ap,
"type": "Person",
"name": self.user.username,
"name": name,
"summary": self.summary,
"inbox": self.inbox_url,
"outbox": self.outbox_url,
Expand Down
6 changes: 4 additions & 2 deletions fedcode/pipes/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
# See https://aboutcode.org for more information about AboutCode.org OSS projects.
#

import json

import saneyaml
from packageurl import PackageURL

Expand All @@ -22,7 +24,7 @@ def create_note(pkg, note_dict):
create_activity = CreateActivity(actor=pkg.to_ap, object=note.to_ap)
Activity.federate(
targets=pkg.followers_inboxes,
body=create_activity.to_ap(),
body=json.dumps(create_activity.to_ap()),
key_id=pkg.key_id,
)

Expand All @@ -36,7 +38,7 @@ def delete_note(pkg, note_dict):
deleted_activity = DeleteActivity(actor=pkg.to_ap, object=note_ap)
Activity.federate(
targets=pkg.followers_inboxes,
body=deleted_activity.to_ap,
body=json.dumps(deleted_activity.to_ap),
key_id=pkg.key_id,
)

Expand Down
19 changes: 8 additions & 11 deletions fedcode/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,22 +698,19 @@ def post(self, request, *args, **kwargs):
return HttpResponseBadRequest("Invalid message")


@method_decorator(has_valid_header, name="dispatch")
class RemoteUserSubscribe(View):
def get(self, request, *args, **kwargs):
"""Endpoint to for existing remote user to subscribe to package."""
"""Endpoint for existing remote user to subscribe to package."""
purl = request.GET.get("purl").rstrip("/")
package = get_object_or_404(Package, purl=purl)
remote_actor = get_object_or_404(RemoteActor, username=kwargs["username"])
host = request.get_host()
if urlparse(remote_actor.url).netloc == host:
_, created = Follow.objects.get_or_create(package=package, person=remote_actor.person)
message = f"Already subscribed package {purl}"
if created:
message = f"Successfully subscribed package {purl}"

return JsonResponse({"status": "success", "message": message})
return HttpResponseBadRequest()

_, created = Follow.objects.get_or_create(package=package, person=remote_actor.person)
message = f"Already subscribed to package {purl}"
if created:
message = f"Successfully subscribed to package {purl}"

return JsonResponse({"status": "success", "message": message})


@method_decorator(has_valid_header, name="dispatch")
Expand Down
2 changes: 1 addition & 1 deletion federatedcode/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
path("api/v0/users/@<str:username>/outbox", UserOutbox.as_view(), name="user-outbox"),
path("api/v0/purls/@<path:purl_string>/inbox", PackageInbox.as_view(), name="purl-inbox"),
path(
"api/v0/users/@<str:username>/subscribe",
"api/v0/users/@<str:username>/subscribe/",
RemoteUserSubscribe.as_view(),
name="purl-subscribe",
),
Expand Down
6 changes: 4 additions & 2 deletions pyproject-aboutcode.federatedcode.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ classifiers = [
]

dependencies = [
"packageurl_python >= 0.15.6",
"aboutcode.hashid>=0.2.0",
"python-dotenv>=1.0.1",
"click>=8.1.7",
"Django>=5.1.2",
"packageurl_python >= 0.15.6",
"python-dotenv>=1.0.1",
"requests>=2.32.3",
"saneyaml>=0.6.0",
]

urls = { Homepage = "https://github.com/aboutcode-org/federatedcode" }
Expand Down