API: Upload new version of an extension #138

Merged
Dalai Felinto merged 12 commits from tokens-version-api into main 2024-05-27 16:18:05 +02:00

URL: /api/v1/version-upload/
Method: POST
Parameters:

  • extension_id
  • version_file
  • release_notes

This patch includes: !134

URL: /api/v1/version-upload/ Method: POST Parameters: * extension_id * version_file * release_notes This patch includes: !134
Dalai Felinto force-pushed tokens-version-api from 3faa541385 to 167b7fc30b 2024-05-18 20:46:30 +02:00 Compare
Author
Owner

I suspect I may have to sanitize the release message, but not sure if it is needed.

I suspect I may have to sanitize the release message, but not sure if it is needed.
Author
Owner

WIP: This is failling the tests at the moment because it requires a token even to get the extensions listing.

WIP: This is failling the tests at the moment because it requires a token even to get the extensions listing.
Dalai Felinto changed title from API: Upload new version of an extension to WIP: API: Upload new version of an extension 2024-05-20 22:53:58 +02:00
Dalai Felinto changed title from WIP: API: Upload new version of an extension to API: Upload new version of an extension 2024-05-20 23:01:04 +02:00
Oleg-Komarov reviewed 2024-05-21 12:39:38 +02:00
Oleg-Komarov left a comment
Owner

overall the api endpoint looks good, some comments inline

token handling is discussed in #134

overall the api endpoint looks good, some comments inline token handling is discussed in #134
@ -152,0 +196,4 @@
status=status.HTTP_403_FORBIDDEN,
)
try:
Owner

could we avoid this big try-except? what is the default drf error behavior?
we need to make sure that we are not leaking any error details in production - we will have the exception logged via sentry, and api users can't do anything useful with those details

could we avoid this big try-except? what is the default drf error behavior? we need to make sure that we are not leaking any error details in production - we will have the exception logged via sentry, and api users can't do anything useful with those details
Oleg-Komarov marked this conversation as resolved
@ -152,0 +210,4 @@
# Create the file instance
file_instance = form.save(commit=False)
file_instance.user = user
file_instance.save()
Owner

this save and the update_or_create below should ideally be together in the same transaction, we should wrap all db writes in one with transaction.atomic():

this save and the update_or_create below should ideally be together in the same transaction, we should wrap all db writes in one `with transaction.atomic():`
dfelinto marked this conversation as resolved
@ -152,0 +226,4 @@
'extension_id': extension_id,
'version_file': version_file.name,
'release_notes': version.release_notes,
'version_id': version.id,
Owner

in UI we don't expose our internal ids, do we need to return this one here?

in UI we don't expose our internal ids, do we need to return this one here?
dfelinto marked this conversation as resolved
Dalai Felinto force-pushed tokens-version-api from 6b79f74233 to f4b3b0d4e7 2024-05-22 00:03:57 +02:00 Compare
Author
Owner

Addressed the review comments.

could we avoid this big try-except? what is the default drf error behavior?

Without the try/catch if I force an error I get one of the usual error screens:

Screenshot 2024-05-22 at 00.02.38.png

But this probably only happens because I'm in a debug environment, right?

Addressed the review comments. > could we avoid this big try-except? what is the default drf error behavior? Without the try/catch if I force an error I get one of the usual error screens: ![Screenshot 2024-05-22 at 00.02.38.png](/attachments/82c71afe-25ba-46b7-9636-09c884fd8a94) But this probably only happens because I'm in a debug environment, right?
Owner

But this probably only happens because I'm in a debug environment, right?

yes, that's normal in dev, in prod we will have a standard 500 error page

> But this probably only happens because I'm in a debug environment, right? yes, that's normal in dev, in prod we will have a standard 500 error page
Oleg-Komarov reviewed 2024-05-23 13:24:24 +02:00
@ -0,0 +14,4 @@
TEST_FILES_DIR = Path(__file__).resolve().parent / 'files'
class VersionUploadAPITest(APITestCase):
Owner

should include a test for a non-authenticated request

should include a test for a non-authenticated request
Owner

returning 403 is ok: maybe not 100% correct from a purist perspective, but it serves the purpose

returning 403 is ok: maybe not 100% correct from a purist perspective, but it serves the purpose
dfelinto marked this conversation as resolved
@ -0,0 +44,4 @@
'release_notes': 'These are the release notes',
},
format='multipart',
HTTP_AUTHORIZATION=f'Bearer {self.token.token}',
Owner

how does this part work now? we are not keeping a token field on the object anymore as far as i can tell

how does this part work now? we are not keeping a `token` field on the object anymore as far as i can tell
dfelinto marked this conversation as resolved
@ -0,0 +85,4 @@
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertIn('version_id', response.data)
Owner

this assert must be failing now after the changes to the response

this assert must be failing now after the changes to the response
dfelinto marked this conversation as resolved
Dalai Felinto force-pushed tokens-version-api from f4b3b0d4e7 to b8fe0d6929 2024-05-25 14:12:26 +02:00 Compare
Author
Owner
  • Address all the comments.
  • Included a mini-refactor which belongs on #134 (UserToken.create_with_token)

Should include a test for a non-authenticated request.

I could not get the test to produce a 401 in this case. I'm checking for a 403, is that ok?

* Address all the comments. * Included a mini-refactor which belongs on #134 (UserToken.create_with_token) > Should include a test for a non-authenticated request. I could not get the test to produce a 401 in this case. I'm checking for a 403, is that ok?
Oleg-Komarov approved these changes 2024-05-27 09:47:12 +02:00
Dismissed
Oleg-Komarov left a comment
Owner

overall looks good, but let's change the url/parameter structure, as mentioned inline

overall looks good, but let's change the url/parameter structure, as mentioned inline
@ -17,2 +17,4 @@
# API
path('api/v1/extensions/', api.ExtensionsAPIView.as_view(), name='api'),
path(
'api/v1/version-upload/',
Owner

sorry, haven't thought of this before, let's restructure the parameters: make them more in line with REST conventions, and get a nice bonus for logs transparency

the url becomes api/v1/extensions/<extension_id>/versions/new/, and the extension_id in the body is not needed

sorry, haven't thought of this before, let's restructure the parameters: make them more in line with REST conventions, and get a nice bonus for logs transparency the url becomes `api/v1/extensions/<extension_id>/versions/new/`, and the `extension_id` in the body is not needed
Oleg-Komarov marked this conversation as resolved
Dalai Felinto referenced this issue from a commit 2024-05-27 12:53:31 +02:00
Author
Owner

Pending changes:

  • new unittest that triggers the actual code path where date_last_access is supposed to be updated.
  • remove create_with_token from the model
Pending changes: * new unittest that triggers the actual code path where date_last_access is supposed to be updated. * remove create_with_token from the model
Dalai Felinto changed title from API: Upload new version of an extension to WIP: API: Upload new version of an extension 2024-05-27 12:59:42 +02:00
Dalai Felinto force-pushed tokens-version-api from 15e4287643 to f72b6c217c 2024-05-27 15:15:06 +02:00 Compare
Dalai Felinto added 1 commit 2024-05-27 15:31:49 +02:00
Dalai Felinto added 1 commit 2024-05-27 15:49:23 +02:00
Author
Owner

All suggestions tackled

All suggestions tackled
Dalai Felinto changed title from WIP: API: Upload new version of an extension to API: Upload new version of an extension 2024-05-27 15:49:48 +02:00
Oleg-Komarov reviewed 2024-05-27 15:59:10 +02:00
@ -154,0 +212,4 @@
file_instance.save()
# Create the version from the file
version = Version.objects.update_or_create(
Owner

btw, what's the use case for update here? why we are not just creating the object?

btw, what's the use case for update here? why we are not just creating the object?
Author
Owner

I guess I was just copying the same code we used on UploadFileView.form_valid. Which probably should be changed as well.

Anyways, changing the PR to use create(), and will merge after testing.

I guess I was just copying the same code we used on UploadFileView.form_valid. Which probably should be changed as well. Anyways, changing the PR to use create(), and will merge after testing.
Oleg-Komarov approved these changes 2024-05-27 15:59:13 +02:00
Author
Owner

Apparently create_or_update is required because of the many-to-many relations.

Without it I get the following errors during test:

  • ERROR: test_date_last_access (extensions.tests.test_api.VersionUploadAPITest)
  • ERROR: test_version_upload_success (extensions.tests.test_api.VersionUploadAPITest)

The error is: TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use licenses.set() instead.

Apparently create_or_update is required because of the many-to-many relations. Without it I get the following errors during test: * ERROR: test_date_last_access (extensions.tests.test_api.VersionUploadAPITest) * ERROR: test_version_upload_success (extensions.tests.test_api.VersionUploadAPITest) The error is: `TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use licenses.set() instead.`
Dalai Felinto merged commit 1de4f84144 into main 2024-05-27 16:18:05 +02:00
Dalai Felinto deleted branch tokens-version-api 2024-05-27 16:18:05 +02:00
Márton Lente referenced this issue from a commit 2024-05-27 16:57:58 +02:00
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: infrastructure/extensions-website#138
No description provided.