Skip to content

Commit e2cf21d

Browse files
committed
.
Signed-off-by: ziadhany <ziadhany2016@gmail.com>
1 parent 7dcabd4 commit e2cf21d

15 files changed

Lines changed: 424 additions & 103 deletions

File tree

.github/workflows/main.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ name: run tests
33
on: [push, pull_request]
44

55
env:
6-
DB_NAME: vulnerablecode
7-
DB_USER: vulnerablecode
8-
DB_PASSWORD: vulnerablecode
6+
DB_NAME: purl-sync
7+
DB_USER: purl-sync
8+
DB_PASSWORD: purl-sync
99

1010
jobs:
1111
build:

purl_sync/Makefile

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# http://nexb.com and https://github.com/nexB/scancode.io
4+
# The ScanCode.io software is licensed under the Apache License version 2.0.
5+
# Data generated with ScanCode.io is provided as-is without warranties.
6+
# ScanCode is a trademark of nexB Inc.
7+
#
8+
# You may not use this software except in compliance with the License.
9+
# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0
10+
# Unless required by applicable law or agreed to in writing, software distributed
11+
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12+
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
13+
# specific language governing permissions and limitations under the License.
14+
#
15+
# Data Generated with ScanCode.io is provided on an "AS IS" BASIS, WITHOUT WARRANTIES
16+
# OR CONDITIONS OF ANY KIND, either express or implied. No content created from
17+
# ScanCode.io should be considered or used as legal advice. Consult an Attorney
18+
# for any legal advice.
19+
#
20+
# ScanCode.io is a free software code scanning tool from nexB Inc. and others.
21+
# Visit https://github.com/nexB/scancode.io for support and download.
22+
# Modified for VulnerableCode use
23+
24+
# Python version can be specified with `$ PYTHON_EXE=python3.x make conf`
25+
PYTHON_EXE?=python3
26+
VENV=venv
27+
MANAGE=${VENV}/bin/python manage.py
28+
ACTIVATE?=. ${VENV}/bin/activate;
29+
VIRTUALENV_PYZ=etc/thirdparty/virtualenv.pyz
30+
# Do not depend on Python to generate the SECRET_KEY
31+
GET_SECRET_KEY=`base64 /dev/urandom | head -c50`
32+
# Customize with `$ make envfile ENV_FILE=/etc/vulnerablecode/.env`
33+
ENV_FILE=.env
34+
# Customize with `$ make postgres VULNERABLECODE_DB_PASSWORD=YOUR_PASSWORD`
35+
VULNERABLECODE_DB_PASSWORD=vulnerablecode
36+
37+
virtualenv:
38+
@echo "-> Bootstrap the virtualenv with PYTHON_EXE=${PYTHON_EXE}"
39+
@${PYTHON_EXE} ${VIRTUALENV_PYZ} --never-download --no-periodic-update ${VENV}
40+
41+
conf: virtualenv
42+
@echo "-> Install dependencies"
43+
@${ACTIVATE} pip install -e . -c requirements.txt
44+
45+
dev: virtualenv
46+
@echo "-> Configure and install development dependencies"
47+
@${ACTIVATE} pip install -e .[dev] -c requirements.txt
48+
49+
envfile:
50+
@echo "-> Create the .env file and generate a secret key"
51+
@if test -f ${ENV_FILE}; then echo ".env file exists already"; exit 1; fi
52+
@mkdir -p $(shell dirname ${ENV_FILE}) && touch ${ENV_FILE}
53+
@echo SECRET_KEY=\"${GET_SECRET_KEY}\" > ${ENV_FILE}
54+
55+
isort:
56+
@echo "-> Apply isort changes to ensure proper imports ordering"
57+
${VENV}/bin/isort .
58+
59+
black:
60+
@echo "-> Apply black code formatter"
61+
${VENV}/bin/black .
62+
63+
doc8:
64+
@echo "-> Run doc8 validation"
65+
@${ACTIVATE} doc8 --max-line-length 100 --ignore-path docs/_build/ --quiet docs/
66+
67+
valid: isort black
68+
69+
check:
70+
@echo "-> Run pycodestyle (PEP8) validation"
71+
@${ACTIVATE} pycodestyle --max-line-length=100 --exclude=venv,lib,thirdparty,docs,migrations,settings.py .
72+
@echo "-> Run isort imports ordering validation"
73+
@${ACTIVATE} isort --check-only .
74+
@echo "-> Run black validation"
75+
@${ACTIVATE} black --check ${BLACK_ARGS}
76+
77+
clean:
78+
@echo "-> Clean the Python env"
79+
rm -rf ${VENV} build/ dist/ vulnerablecode.egg-info/ docs/_build/ pip-selfcheck.json
80+
find . -type f -name '*.py[co]' -delete -o -type d -name __pycache__ -delete
81+
82+
migrate:
83+
@echo "-> Apply database migrations"
84+
${MANAGE} migrate
85+
86+
sqlite:
87+
@echo "-> Configure SQLite database"
88+
@echo VULNERABLECODE_DB_ENGINE=\"django.db.backends.sqlite3\" >> ${ENV_FILE}
89+
@echo VULNERABLECODE_DB_NAME=\"sqlite3.db\" >> ${ENV_FILE}
90+
@$(MAKE) migrate
91+
92+
run:
93+
${MANAGE} runserver 8000 --insecure
94+
95+
test:
96+
@echo "-> Run the test suite"
97+
${ACTIVATE} ${PYTHON_EXE} -m pytest -vvs -m "not webtest"
98+
99+
webtest:
100+
@echo "-> Run web tests"
101+
${ACTIVATE} ${PYTHON_EXE} -m pytest -vvs -m "webtest"

purl_sync/purl_sync/urls.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from review import views
1717
from review.views import CreateReview
1818
from review.views import CreatGitView
19-
from review.views import FollowView
19+
from review.views import FollowPurlView
2020
from review.views import HomeView
2121
from review.views import NoteView
2222
from review.views import PersonSignUp
@@ -48,7 +48,7 @@
4848
path("", HomeView.as_view(), name="home-page"),
4949
path("users/@<str:slug>", PersonView.as_view(), name="user-profile"),
5050
path("purls/@<path:slug>/", PurlView.as_view(), name="purl-profile"),
51-
path("purls/@<path:purl_string>/follow", FollowView.as_view(), name="purl-follow"),
51+
path("purls/@<path:purl_string>/follow", FollowPurlView.as_view(), name="purl-follow"),
5252
path("accounts/sign-up", PersonSignUp.as_view(), name="signup"),
5353
path("accounts/login/", UserLogin.as_view(), name="login"),
5454
path("accounts/logout", LogoutView.as_view(next_page="login"), name="logout"),

purl_sync/requirements.txt

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,49 @@
1+
anyio==4.0.0
12
asgiref==3.7.2
3+
attrs==23.1.0
4+
certifi==2023.5.7
5+
cffi==1.15.1
6+
charset-normalizer==3.1.0
7+
cryptography==41.0.1
8+
dateparser==1.1.8
9+
Deprecated==1.2.14
210
Django==4.2.2
311
django-environ==0.10.0
12+
django-oauth-toolkit==2.3.0
13+
django-rest-framework==0.1.0
14+
djangorestframework==3.14.0
415
exceptiongroup==1.1.1
16+
gitdb==4.0.10
17+
GitPython==3.1.31
18+
h11==0.14.0
19+
http-message-signatures==0.4.4
20+
http-sfv==0.9.8
21+
httpcore==0.17.3
22+
httpx==0.24.1
23+
idna==3.4
524
iniconfig==2.0.0
25+
jwcrypto==1.5.0
26+
oauthlib==3.2.2
27+
packageurl-python==0.11.1
628
packaging==23.1
729
Pillow==9.5.0
830
pluggy==1.0.0
31+
pycparser==2.21
932
pytest==7.3.2
1033
pytest-django==4.5.2
34+
python-dateutil==2.8.2
35+
pytz==2023.3
36+
PyYAML==6.0.1
37+
regex==2023.8.8
38+
requests==2.31.0
39+
saneyaml==0.6.0
40+
six==1.16.0
41+
smmap==5.0.0
42+
sniffio==1.3.0
1143
sqlparse==0.4.4
1244
tomli==2.0.1
1345
typing_extensions==4.6.3
14-
15-
djangorestframework~=3.14.0
16-
requests~=2.31.0
17-
saneyaml~=0.6.0
18-
django-oauth-toolkit~=2.3.0
46+
tzlocal==5.0.1
47+
unidiff==0.7.5
48+
urllib3==2.0.3
49+
wrapt==1.15.0

purl_sync/review/activitypub.py

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@
5656

5757
AP_TARGET = {"cc": "https://www.w3.org/ns/activitystreams#Public"}
5858

59+
OBJ_Map = {
60+
"Note": "note-page",
61+
"Review": "review-page",
62+
"Repository": "repository-page",
63+
"Vulnerability": "vulnerability-page",
64+
}
65+
5966

6067
def check_and_r_ap_context(request):
6168
"""
@@ -270,19 +277,13 @@ def save(self):
270277

271278
def succeeded_ap_rs(self, new_obj):
272279
"""Response for successfully deleting the object"""
273-
Obj_Map = {
274-
"Note": "note-page",
275-
"Review": "review-page",
276-
"Repository": "repository-page",
277-
"Vulnerability": "vulnerability-page",
278-
}
279280
return JsonResponse(
280-
{"Location": full_reverse(Obj_Map[self.object.type], new_obj.id)}, status=201
281+
{"Location": full_reverse(OBJ_Map[self.object.type], new_obj.id)}, status=201
281282
)
282283

283284
def failed_ap_rs(self):
284285
"""Response for failure deleting the object"""
285-
return JsonResponse({self.object}, status=405)
286+
return HttpResponseBadRequest("Invalid Create Activity request")
286287

287288
def to_ap(self):
288289
"""Request for creating object in activitypub format"""
@@ -309,19 +310,20 @@ def save(self):
309310
}
310311

311312
if (
312-
(isinstance(actor, Person) and self.object.type in ["Note", "Review"])
313-
or (isinstance(actor, Service) and self.object.type == "Repository")
314-
or (isinstance(actor, Purl) and self.object.type == "Note")
313+
(isinstance(actor, Person) and self.object.type in ["Note", "Review"])
314+
or (isinstance(actor, Service) and self.object.type == "Repository")
315+
or (isinstance(actor, Purl) and self.object.type == "Note")
315316
):
316317
for key, value in updated_param[self.object.type].items():
317318
if value:
318319
setattr(old_obj, key, value)
319320
old_obj.save()
320-
return "TODO"
321321

322-
def succeeded_ap_rs(self):
322+
return self.succeeded_ap_rs(old_obj.to_ap)
323+
324+
def succeeded_ap_rs(self, update_obj):
323325
"""Response for successfully deleting the object"""
324-
return JsonResponse({self.object}, status=410)
326+
return JsonResponse(update_obj, status=200)
325327

326328
def failed_ap_rs(self):
327329
"""Response for failure deleting the object"""
@@ -344,9 +346,9 @@ def save(self):
344346
return self.failed_ap_rs()
345347

346348
if (
347-
(type(actor) is Person and self.object.type in ["Note", "Review"])
348-
or (type(actor) is Purl and self.object.type in ["Note"])
349-
or (type(actor) is Service and self.object.type == ["Repository", "Purl"])
349+
(type(actor) is Person and self.object.type in ["Note", "Review"])
350+
or (type(actor) is Purl and self.object.type in ["Note"])
351+
or (type(actor) is Service and self.object.type == ["Repository", "Purl"])
350352
):
351353
instance = self.object.get_object()
352354
instance.delete()
@@ -360,7 +362,7 @@ def ap_rq(self):
360362

361363
def succeeded_ap_rs(self):
362364
"""Response for successfully deleting the object"""
363-
return JsonResponse(asdict(self.object), status=410)
365+
return JsonResponse({"message": "The object has been deleted successfully"}, status=200)
364366

365367
def failed_ap_rs(self):
366368
"""Response for failure deleting the object"""

purl_sync/review/forms.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,11 @@ class CreateReviewForm(forms.Form):
7474
)
7575
data = forms.CharField(widget=forms.Textarea(attrs={"class": "textarea", "rows": 16}))
7676
filename = forms.CharField(widget=forms.HiddenInput())
77+
78+
79+
class SubscribePurlForm(forms.Form):
80+
acct = forms.CharField(label="Subscribe with a remote account:",
81+
widget=forms.TextInput(
82+
attrs={'placeholder': 'ziadhany@vulnerablecode.io',
83+
'class': 'input'
84+
}))

purl_sync/review/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
class RemoteActor(models.Model):
3333
url = models.URLField(primary_key=True)
3434
username = models.CharField(max_length=100)
35-
profile_data = models.JSONField()
3635
updated_at = models.DateTimeField(auto_now=True)
3736

3837
class Meta:
@@ -185,10 +184,12 @@ def acct(self):
185184
def followers_count(self):
186185
return Follow.objects.filter(purl=self).count()
187186

187+
# TODO raise error if the purl have a version or qualifiers or subpath
188188
# def save(self, *args, **kwargs):
189189
# if not check_purl_actor(self.string):
190190
# return ValidationError(self.string)
191191
# super(Purl, self).save(*args, **kwargs)
192+
192193
@property
193194
def absolute_url_ap(self):
194195
return full_reverse("purl-ap-profile", self.string)

0 commit comments

Comments
 (0)