Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug-1909637: allow searching for files from regular and try symbol uploads #2992

Merged
merged 1 commit into from
Aug 19, 2024
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
37 changes: 29 additions & 8 deletions frontend/src/Files.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ class DisplayFiles extends React.PureComponent {
const filter = this.props.filter;
this.refs.key.value = filter.key || "";
this.refs.size.value = filter.size || "";
this.refs.upload_type.value = filter.upload_type || "";
this.refs.created_at.value = filter.created_at || "";
this.refs.bucketName.value = filter.bucket_name || "";
}
Expand All @@ -209,6 +210,7 @@ class DisplayFiles extends React.PureComponent {
event.preventDefault();
const key = this.refs.key.value.trim();
const size = this.refs.size.value.trim();
const upload_type = this.refs.upload_type.value.trim();
const created_at = this.refs.created_at.value.trim();
const bucketName = this.refs.bucketName.value.trim();
this.props.updateFilter({
Expand All @@ -217,13 +219,15 @@ class DisplayFiles extends React.PureComponent {
size,
created_at,
bucket_name: bucketName,
upload_type: upload_type,
});
};

resetFilter = (event) => {
this.refs.key.value = "";
this.refs.size.value = "";
this.refs.bucketName.value = "";
this.refs.upload_type.value = "";
this.refs.created_at.value = "";
this.submitForm(event);
};
Expand All @@ -238,6 +242,7 @@ class DisplayFiles extends React.PureComponent {
<th>Key</th>
<th>Size</th>
<th>Bucket</th>
<th>Upload type</th>
<th>Uploaded</th>
<th
className="bool-row is-clipped"
Expand All @@ -254,6 +259,7 @@ class DisplayFiles extends React.PureComponent {
<th>Time to complete</th>
</tr>
</thead>

<tfoot>
<tr>
<td>
Expand Down Expand Up @@ -282,6 +288,15 @@ class DisplayFiles extends React.PureComponent {
style={{ width: 140 }}
/>
</td>
<td>
<span className="select">
<select name="upload_type" ref="upload_type">
<option></option>
<option>regular</option>
<option>try</option>
</select>
</span>
</td>
<td>
<input
type="text"
Expand Down Expand Up @@ -316,6 +331,20 @@ class DisplayFiles extends React.PureComponent {
</td>
<td>{formatFileSize(file.size)}</td>
<td>{file.bucket_name}</td>
<td>
{file.upload && file.upload.upload_type === "try" ? (
<span className="tag is-info" title="try symbol upload">
try
</span>
) : (
<span
className="tag"
title="{file.upload.upload_type} symbol upload"
>
{file.upload.upload_type}
</span>
)}
</td>
<td>
{file.upload ? (
<Link
Expand All @@ -327,14 +356,6 @@ class DisplayFiles extends React.PureComponent {
) : (
<DisplayDate date={file.created_at} />
)}{" "}
{file.upload && file.upload.try_symbols ? (
<span
className="tag is-info"
title="Part of a Try build upload"
>
Try
</span>
) : null}
</td>
<td>{BooleanIcon(file.update)}</td>
<td>{BooleanIcon(file.compressed)}</td>
Expand Down
3 changes: 3 additions & 0 deletions tecken/api/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ class FileUploadsForm(UploadsForm):
size = forms.CharField(required=False)
created_at = forms.CharField(required=False)
completed_at = forms.CharField(required=False)
upload_type = forms.ChoiceField(
choices=[("", ""), ("try", "try"), ("regular", "regular")], required=False
)
key = forms.CharField(required=False)
update = forms.BooleanField(required=False)
compressed = forms.BooleanField(required=False)
Expand Down
12 changes: 12 additions & 0 deletions tecken/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,16 +387,19 @@ def _upload_files_build_qs(request):
form = forms.FileUploadsForm(request.GET)
if not form.is_valid():
return http.JsonResponse({"errors": form.errors}, status=400)

qs = FileUpload.objects.all()
for operator, value in form.cleaned_data["size"]:
orm_operator = "size__{}".format(ORM_OPERATORS[operator])
qs = qs.filter(**{orm_operator: value})

qs = filter_form_dates(qs, form, ("created_at", "completed_at"))
if form.cleaned_data.get("key"):
key_q = Q(key__icontains=form.cleaned_data["key"][0])
for other in form.cleaned_data["key"][1:]:
key_q &= Q(key__icontains=other)
qs = qs.filter(key_q)

include_bucket_names = []
for operator, bucket_name in form.cleaned_data["bucket_name"]:
if operator == "!":
Expand All @@ -405,6 +408,14 @@ def _upload_files_build_qs(request):
include_bucket_names.append(bucket_name)
if include_bucket_names:
qs = qs.filter(bucket_name__in=include_bucket_names)

if form.cleaned_data.get("upload_type", ""):
# NOTE(willkg): we have two upload types: try and regular. The try_symbols field
# is a boolean where try=True and regular=False, so we convert from a general
# upload types domain to the boolean domain of whether it's try upload or not.
# In the future, we may want to support other types by fixing the Upload model.
try_symbols = form.cleaned_data["upload_type"] == "try"
qs = qs.filter(upload__try_symbols=try_symbols)
return qs


Expand Down Expand Up @@ -455,6 +466,7 @@ def hydrate_upload(upload_id):
upload = uploads[upload_id]
uploads_cache[upload_id] = {
"id": upload.id,
"upload_type": "try" if upload.try_symbols else "regular",
"try_symbols": upload.try_symbols,
"user": {"id": upload.user.id, "email": upload.user.email},
"created_at": upload.created_at,
Expand Down
104 changes: 94 additions & 10 deletions tecken/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,62 @@ def test_upload_files(client, settings):
assert [x["id"] for x in data["files"]] == [file_upload2.id]


@pytest.mark.django_db
def test_upload_files_filter_upload_type(client, settings):
url = reverse("api:upload_files")

user = User.objects.create(username="user1", email="user1@example.com")
user.set_password("secret")
user.save()
assert client.login(username="user1", password="secret")

permission = Permission.objects.get(codename="view_all_uploads")
user.user_permissions.add(permission)

# Create upload data
regular_upload = Upload.objects.create(user=user, size=123_456)
regular_file = FileUpload.objects.create(
upload=regular_upload,
size=1234,
bucket_name="symbols-public",
key="bar.pdb/46A0ADB3F299A70B4C4C44205044422E1/bar.sym",
)

try_upload = Upload.objects.create(user=user, size=123_456, try_symbols=True)
try_file = FileUpload.objects.create(
upload=try_upload,
size=100,
bucket_name="symbols-public",
key="v1/libxul.so/A772CC9A3E852CF48965ED79FB65E3150/libxul.so.sym",
)

# Request all files--should return both files
response = client.get(url)
assert response.status_code == 200
data = response.json()
assert data["files"]
all_ids = {regular_file.id, try_file.id}
assert {x["id"] for x in data["files"]} == all_ids

# Request upload_type=""--should return both files
response = client.get(url, {"upload_type": ""})
assert response.status_code == 200
data = response.json()
assert {x["id"] for x in data["files"]} == all_ids

# Request upload_type="try"--should return only try file
response = client.get(url, {"upload_type": "try"})
assert response.status_code == 200
data = response.json()
assert {x["id"] for x in data["files"]} == {try_file.id}

# Request upload_type="regular"--should return only regular file
response = client.get(url, {"upload_type": "regular"})
assert response.status_code == 200
data = response.json()
assert {x["id"] for x in data["files"]} == {regular_file.id}


@pytest.mark.django_db
def test_upload_files_count(client):
url = reverse("api:upload_files")
Expand All @@ -863,14 +919,23 @@ def test_upload_files_count(client):
assert client.login(username="user1", password="secret")

# Create data
upload = Upload.objects.create(user=user, size=123_456)
file_upload_1 = FileUpload.objects.create(
upload=upload,
regular_upload = Upload.objects.create(user=user, size=123_456)
regular_file_upload = FileUpload.objects.create(
upload=regular_upload,
size=1234,
bucket_name="symbols-public",
key="v1/bar.pdb/46A0ADB3F299A70B4C4C44205044422E1/bar.sym",
key="bar.pdb/46A0ADB3F299A70B4C4C44205044422E1/bar.sym",
)

try_upload = Upload.objects.create(user=user, size=123_456, try_symbols=True)
try_file_upload = FileUpload.objects.create(
upload=try_upload,
size=50,
bucket_name="symbols-public",
key="libxul.so/9B6C6BD630483C5F453471EE0EEEB09A0/libxul.so.sym",
)
file_upload_2 = FileUpload.objects.create(

file_upload = FileUpload.objects.create(
size=100,
bucket_name="symbols-public",
key="libxul.so/A772CC9A3E852CF48965ED79FB65E3150/libxul.so.sym",
Expand All @@ -883,7 +948,7 @@ def test_upload_files_count(client):
data = response.json()
assert data["files"] == [
{
"id": file_upload_2.id,
"id": file_upload.id,
"key": "libxul.so/A772CC9A3E852CF48965ED79FB65E3150/libxul.so.sym",
"update": False,
"compressed": True,
Expand All @@ -894,7 +959,24 @@ def test_upload_files_count(client):
"upload": None,
},
{
"id": file_upload_1.id,
"bucket_name": "symbols-public",
"completed_at": None,
"compressed": False,
"created_at": ANY,
"id": try_file_upload.id,
"key": "libxul.so/9B6C6BD630483C5F453471EE0EEEB09A0/libxul.so.sym",
"size": 50,
"update": False,
"upload": {
"created_at": ANY,
"id": try_upload.id,
"try_symbols": True,
"upload_type": "try",
"user": {"id": user.id, "email": "user1@example.com"},
},
},
{
"id": regular_file_upload.id,
"key": "bar.pdb/46A0ADB3F299A70B4C4C44205044422E1/bar.sym",
"update": False,
"compressed": False,
Expand All @@ -903,8 +985,9 @@ def test_upload_files_count(client):
"completed_at": None,
"created_at": ANY,
"upload": {
"id": upload.id,
"id": regular_upload.id,
"try_symbols": False,
"upload_type": "regular",
"user": {"id": user.id, "email": "user1@example.com"},
"created_at": ANY,
},
Expand All @@ -925,14 +1008,15 @@ def test_upload_files_count(client):
"completed_at": None,
"compressed": False,
"created_at": ANY,
"id": file_upload_1.id,
"id": regular_file_upload.id,
"key": "bar.pdb/46A0ADB3F299A70B4C4C44205044422E1/bar.sym",
"size": 1234,
"update": False,
"upload": {
"created_at": ANY,
"id": upload.id,
"id": regular_upload.id,
"try_symbols": False,
"upload_type": "regular",
"user": {
"email": "user1@example.com",
"id": user.id,
Expand Down