Skip to content

Commit 186d237

Browse files
committed
Add follow page , FollowView view
Fix models test Signed-off-by: ziad <ziadhany2016@gmail.com>
1 parent a6715f1 commit 186d237

11 files changed

Lines changed: 272 additions & 108 deletions

File tree

purl_sync/purl_sync/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,4 @@
144144
MEDIA_URL = "/media/"
145145
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
146146
GIT_PATH = os.path.join(MEDIA_ROOT, "git")
147-
ACTIVITYPUB_CONTENT_TYPE = "application/activity+json"
147+
ACTIVITYPUB_CONTENT_TYPE = "application/activity+json"

purl_sync/purl_sync/urls.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
from django.urls import include
66
from django.urls import path
77

8-
from review.views import CreatGitView, CreateReview, repository
8+
from review.views import CreateReview
9+
from review.views import CreatGitView
910
from review.views import DatabaseAdminView
11+
from review.views import FollowView
1012
from review.views import RepositoryListView
1113
from review.views import ReviewListView
1214
from review.views import ReviewView
@@ -16,9 +18,10 @@
1618
from review.views import SecurityTeamView
1719
from review.views import UserLogin
1820
from review.views import WebfingerView
21+
from review.views import comment_vote
1922
from review.views import database_admin_inbox
2023
from review.views import database_admin_outbox
21-
from review.views import comment_vote
24+
from review.views import repository
2225
from review.views import review_vote
2326

2427
urlpatterns = [
@@ -30,22 +33,22 @@
3033
path("accounts/login/", UserLogin.as_view(), name="login"),
3134
path("accounts/logout", LogoutView.as_view(next_page="login"), name="logout"),
3235
path("create-repo", CreatGitView.as_view(), name="repo-create"),
33-
34-
path("repository/<uuid:repository_id>/create-review/", CreateReview.as_view(), name="review-create"),
35-
36+
path("follow-purl/", FollowView.as_view(), name="follow-purl"),
37+
path(
38+
"repository/<uuid:repository_id>/create-review/",
39+
CreateReview.as_view(),
40+
name="review-create",
41+
),
3642
path("review/<uuid:id>/", ReviewView.as_view(), name="review-page"),
3743
path("review-list", ReviewListView.as_view(), name="review-list"),
3844
path("repo-list", RepositoryListView.as_view(), name="repo-list"),
39-
4045
path("review/<uuid:review_id>/votes/", review_vote, name="vote-review"),
4146
path("comment/<uuid:comment_id>/votes/", comment_vote, name="vote-comment"),
4247
path("repository/<uuid:repository_id>/", repository, name="repository"),
43-
4448
path("security-team/<str:username>/inbox/", SecurityTeamInbox.as_view()),
4549
path("security-team/<str:username>/outbox/", SecurityTeamOutbox.as_view()),
4650
path("database-admin/<str:username>/outbox/", database_admin_outbox),
4751
path("database-admin/<str:username>/inbox/", database_admin_inbox),
48-
4952
# path("security-team/@<str:username>/edit-followers/", database_admin_profile_view),
5053
# path("database-admin/<str:username>/followers/", ),
5154
# path("security-team/<str:username>/following/", ),

purl_sync/review/activitypub.py

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,29 @@
22
import json
33

44
from django.contrib.auth.models import User
5-
from django.http import HttpResponseBadRequest, JsonResponse
5+
from django.http import HttpResponseBadRequest
6+
from django.http import JsonResponse
67

7-
from review.models import DatabaseAdmin, SecurityTeam, Review, Comment, Repository
8+
from review.models import Comment
9+
from review.models import DatabaseAdmin
10+
from review.models import Repository
11+
from review.models import Review
12+
from review.models import SecurityTeam
813

914
CONTENT_TYPE = "application/activity+json"
1015
ACTOR_TYPES = ["SecurityTeam", "DatabaseAdmin"]
1116
ACTIVITY_TYPES = ["Like", "Follow", "Create", "Update", "Delete", "Dislike"]
12-
VALID_HEADERS = ['application/ld+json; profile="https://www.w3.org/ns/activitystreams"', 'application/activity+json']
17+
VALID_HEADERS = [
18+
'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
19+
"application/activity+json",
20+
]
1321
OBJECT_TYPES = ["Notes", "Review", "Repository", "Vulnerability", "PackageURL"]
1422

15-
AS_CONTEXT = {"@context": ["https://www.w3.org/ns/activitystreams",
16-
"..........."
17-
], }
23+
AS_CONTEXT = {
24+
"@context": ["https://www.w3.org/ns/activitystreams", "..........."],
25+
}
1826
response = {
1927
**AS_CONTEXT,
20-
2128
"@type": "DatabaseAdmin",
2229
"@id": "https://example.com/database-admin/vcio",
2330
"name": "vcio",
@@ -26,9 +33,7 @@
2633
"inbox": "https://example.com/database-admin/vcio/inbox",
2734
"outbox": "https://example.com/database-admin/vcio/outbox",
2835
"followers": "https://example.com/database-admin/vcio/followers",
29-
"icon": [
30-
"https://example.com/image/avatar"
31-
],
36+
"icon": ["https://example.com/image/avatar"],
3237
"liked": "https://example.com/database-admin/vcio/liked/",
3338
}
3439

@@ -41,9 +46,7 @@ def ap_r(response):
4146
raise Exception("Invalid json response")
4247

4348
if not response.get("@context"):
44-
response.append(
45-
**AS_CONTEXT
46-
)
49+
response.append(**AS_CONTEXT)
4750

4851
return response
4952

@@ -56,20 +59,20 @@ def ap_p(request):
5659
return json_r
5760

5861

59-
def get_actor(actor):
60-
"""
61-
{
62-
"type": "Person",
63-
"name": "Sally"
64-
}
65-
"""
66-
actor_type = actor.get("type")
67-
actor_name = actor.get("name")
68-
69-
if actor_type in ["Person", "Organization"]:
70-
return User.objects.get(username=actor_name)
71-
else:
72-
return HttpResponseBadRequest("")
62+
# def get_actor(actor):
63+
# """
64+
# {
65+
# "type": "Person",
66+
# "name": "Sally"
67+
# }
68+
# """
69+
# actor_type = actor.get("type")
70+
# actor_name = actor.get("name")
71+
#
72+
# if actor_type in ["Person", "Organization"]:
73+
# return User.objects.get(username=actor_name)
74+
# else:
75+
# return HttpResponseBadRequest("")
7376

7477

7578
def create_object(actor, activity_object):

purl_sync/review/admin.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
from django.contrib import admin
22

3+
from review.models import Comment
34
from review.models import DatabaseAdmin
45
from review.models import Follow
5-
from review.models import Repository
6-
from review.models import Comment
76
from review.models import PackageUrl
87
from review.models import RemoteActor
98
from review.models import RemoteDatabaseAdmin
109
from review.models import RemoteSecurityTeam
10+
from review.models import Repository
1111
from review.models import Reputation
1212
from review.models import Review
1313
from review.models import SecurityTeam

purl_sync/review/forms.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
from django.contrib.auth.forms import UserCreationForm
33
from django.contrib.auth.models import User
44

5-
from review.models import Repository
65
from review.models import Comment
6+
from review.models import Repository
77
from review.models import Review
88

99

@@ -55,7 +55,27 @@ class Meta:
5555

5656

5757
class CreateReviewForm(forms.Form):
58-
headline = forms.CharField(widget=forms.TextInput(attrs={'class': 'input is-medium title has-text-centered',
59-
"placeholder": "Review Title"}))
60-
data = forms.CharField(widget=forms.Textarea(attrs={'class': 'textarea', 'rows': 16}))
58+
headline = forms.CharField(
59+
widget=forms.TextInput(
60+
attrs={
61+
"class": "input is-medium title has-text-centered",
62+
"placeholder": "Review Title",
63+
}
64+
)
65+
)
66+
data = forms.CharField(widget=forms.Textarea(attrs={"class": "textarea", "rows": 16}))
6167
filename = forms.CharField(widget=forms.HiddenInput())
68+
69+
70+
class FollowPurlForm(forms.Form):
71+
purl_string = forms.CharField(max_length=150, label="PackageURL:")
72+
database_admin_webfinger = forms.CharField(max_length=100, label="Database Admin:")
73+
74+
def __init__(self, *args, **kwargs):
75+
super().__init__(*args, **kwargs)
76+
self.fields["purl_string"].widget.attrs.update(
77+
{"class": "input", "placeholder": "pkg:maven/org.apache.commons/io@1.3.4"}
78+
)
79+
self.fields["database_admin_webfinger"].widget.attrs.update(
80+
{"class": "input", "placeholder": "maven@vcio.com", "style": "width: 25%;"}
81+
)

purl_sync/review/migrations/0001_initial.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
# Generated by Django 4.2.2 on 2023-07-17 13:05
1+
# Generated by Django 4.2.2 on 2023-07-21 18:12
22

3-
from django.conf import settings
4-
from django.db import migrations, models
5-
import django.db.models.deletion
63
import uuid
74

5+
import django.db.models.deletion
6+
from django.conf import settings
7+
from django.db import migrations
8+
from django.db import models
9+
810

911
class Migration(migrations.Migration):
1012

@@ -224,13 +226,8 @@ class Migration(migrations.Migration):
224226
name="PackageUrl",
225227
fields=[
226228
("id", models.AutoField(primary_key=True, serialize=False)),
227-
("purl_string", models.CharField(max_length=300)),
228-
(
229-
"vulnerability",
230-
models.ForeignKey(
231-
on_delete=django.db.models.deletion.CASCADE, to="review.vulnerability"
232-
),
233-
),
229+
("purl_string", models.CharField(max_length=300, unique=True)),
230+
("vulnerabilities", models.ManyToManyField(to="review.vulnerability")),
234231
],
235232
),
236233
migrations.AddField(

purl_sync/review/models.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ def reputation_value(self):
2626
"""if someone like your review you will get +1, dislike: -1"""
2727
user_reputation = Reputation.objects.filter(voter=self.acct)
2828
return (
29-
user_reputation.filter(positive=True).count()
30-
- user_reputation.filter(positive=False).count()
29+
user_reputation.filter(positive=True).count()
30+
- user_reputation.filter(positive=False).count()
3131
)
3232

3333
class Meta:
@@ -70,8 +70,8 @@ def username(self):
7070
def reputation_value(self):
7171
review_reputation = Reputation.objects.filter(object_type=1, object_id=self.id)
7272
return (
73-
review_reputation.filter(positive=True).count()
74-
- review_reputation.filter(positive=False).count()
73+
review_reputation.filter(positive=True).count()
74+
- review_reputation.filter(positive=False).count()
7575
)
7676

7777
@property
@@ -164,11 +164,14 @@ class Vulnerability(models.Model):
164164

165165
@property
166166
def load_file(self):
167+
"""
168+
copied from https://stackoverflow.com/a/54900961/9871531
169+
"""
167170
commit = self.repo.git_repo.commit(self.commit_id)
168171
target_file = commit.tree / self.filename
169172

170173
with io.BytesIO(target_file.data_stream.read()) as f:
171-
return f.read().decode('utf-8')
174+
return f.read().decode("utf-8")
172175

173176
@property
174177
def to_ap(self):
@@ -177,8 +180,8 @@ def to_ap(self):
177180

178181
class PackageUrl(models.Model):
179182
id = models.AutoField(primary_key=True, help_text="")
180-
purl_string = models.CharField(max_length=300, help_text="")
181-
vulnerability = models.ForeignKey(Vulnerability, on_delete=models.CASCADE, help_text="")
183+
purl_string = models.CharField(max_length=300, unique=True, help_text="")
184+
vulnerabilities = models.ManyToManyField(Vulnerability, help_text="")
182185

183186

184187
class Follow(models.Model):
@@ -231,8 +234,8 @@ def __str__(self):
231234
def reputation_value(self):
232235
review_reputation = Reputation.objects.filter(object_type=0, object_id=self.id)
233236
return (
234-
review_reputation.filter(positive=True).count()
235-
- review_reputation.filter(positive=False).count()
237+
review_reputation.filter(positive=True).count()
238+
- review_reputation.filter(positive=False).count()
236239
)
237240

238241
@property
@@ -250,7 +253,7 @@ def to_ap(self):
250253
"vulnerability": self.vulnerability.id,
251254
"reviewData": self.data,
252255
"commentCount": self.comments.count(),
253-
"comments": [note.to_ap() for note in self.comments],
256+
"comments": [comment.to_ap() for comment in self.comments],
254257
"dateCreated": self.created_at,
255258
"dateModified": self.updated_at,
256259
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{% extends "base.html" %}
2+
{% block title %}
3+
Review page
4+
{% endblock %}
5+
6+
{% block extrahead %}
7+
{% endblock %}
8+
{% block content %}
9+
<div class="columns">
10+
<div class="column">
11+
</div>
12+
13+
<div class="column is-two-thirds">
14+
<div class="content is-normal">
15+
<h1>Follow PackageURL List</h1>
16+
<hr/>
17+
<div>
18+
{% if form.errors %}
19+
<article class="message is-danger">
20+
<div class="message-header">
21+
<p>Error</p>
22+
<button class="delete" aria-label="delete"></button>
23+
</div>
24+
<div class="message-body">
25+
{{ form.errors }}
26+
</div>
27+
</article>
28+
{% endif %}
29+
30+
<form method="post" class="is-flex mb-3">
31+
{% csrf_token %}
32+
<label class="mr-4">{{ form.purl_string.label }}</label>
33+
{{ form.purl_string }}
34+
<label class="has-text-centered mr-2 ml-2">{{ form.database_admin.label }}</label>
35+
{{ form.database_admin_webfinger }}
36+
<input class="button is-success mr-3 ml-3" type="submit" value="Save">
37+
</form>
38+
39+
40+
<table class="table">
41+
<thead>
42+
<tr>
43+
<th>PackageURL</th>
44+
<th>Database Admin</th>
45+
</tr>
46+
</thead>
47+
<tbody>
48+
{% for follow in follows %}
49+
<tr>
50+
<td> {{ follow.purl.purl_string }}</td>
51+
<td> {{ follow.database_admin.acct }} </td>
52+
</tr>
53+
{% endfor %}
54+
</tbody>
55+
</table>
56+
</div>
57+
58+
</div>
59+
</div>
60+
61+
<div class="column"></div>
62+
</div>
63+
64+
{% endblock %}

0 commit comments

Comments
 (0)