🐛 Handle non-existing user IDs in read_user_by_id - #1396

Merged
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user
Jan 22, 2026
Merged

🐛 Handle non-existing user IDs in read_user_by_id#1396
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user

Conversation

@saltie2193

Copy link
Copy Markdown
Contributor

Fix an issue where read_user_by_id would fail to return if the requested user ID did not exist.

  • Return 404 - Not Found when ID does not exist.
  • Request without sufficient permission will always result in 403 - Unauthorized.
  • Add tests to test requesting non-existing user IDs as superuser and normal user.

@alejsdevalejsdev changed the title 👷 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_id.Oct 24, 2024
@alejsdevalejsdev added the bug Something isn't working label Oct 24, 2024
@alejsdevalejsdev changed the title 🐛 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_idOct 24, 2024
@berar

berar commented Nov 7, 2024

Copy link
Copy Markdown

Hello. I'd like to know why this pull request has not been approved. It is valid.

@jonbzt

Copy link
Copy Markdown

Yeah pretty minor upgrade but it makes sens to merge IMO.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saltie2193, thanks for working on this!

Please, take a look at my change suggestions.
Basically, I think we should leave existing tests untouched (only rename test_get_existing_user -> test_get_existing_user_as_superuser) and add 2 test for non-existing user (superuser - 404, regular user - 403)

Comment on lines +91 to +93
@pytest.mark.parametrize(
"is_superuser", (True, False), ids=lambda x: "superuser" if x else "normal user"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case with is_superuser=True is already covered by test_get_existing_user_as_superuser.
No need to parameterize this test

@saltie2193saltie2193Sep 5, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be the same as in test_get_existing_user_as_superuser.

test_get_existing_user_as_superuser tests whether a user authenticated as superuser is able to access another user. (User A tries to access data of user B)

test_get_exiting_user_current_user however tests whether a user is allowed to access his own data, independent of them being a superuser or not. (User A tries to access data of user A)

That's at least what they are intended to test.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is to ensure that superuser can access their own user information, not only other user's information, right?
I still think this is redundant. I believe the chance somebody writes the algorithm this way is extremely low..

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It's to ensure superuser privileges don't influence it.
Sure might be excessive but it's just an additional simple case of the test, ensuring the correct function of the backend, and not even expensive.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I can come up with 10 more additional tests. And all of them will be hypothetically possible.
I think we should consider:

  • what is the probability that somebody writes this function this way (superuser can access random user, but can't access their own info. At the same time normal user can access their own info)?
  • every change is additional load for people who will review it and read this code later

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean especially when talking about authentication and authorization it do think it's not unlikely to not think about something like this, that seems really easy ans stupid. Especially when looking at differences between superusers and non superuser. Often the most simple parts are overlooked because people thought it's obvious how it's supposed to work and nobody would ever make a mistake like that.
This just uses as simple test case in a preventive way ensuring the backend is working as intended and at the same time explicitly documents the intended behavior.

But I do understand and have to respect it if this project does not want to use test cases in this way.

So we only test if the current user (authenticated as non-superuser) is able to access his data and I drop the changes to test_get_existing_user_current_user?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep test_get_existing_user_current_user as it was before this PR

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Fix an issue where `read_user_by_id` would fail to return if the requested user ID did not exist.
* Return `404 - Not Found` when ID does not exist.
* Request without sufficient permission will always result in `403 - Unauthorized`.
* Add tests to test requesting non-existing user IDs as superuser and normal user.
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from a2dd74f to e031948CompareSeptember 5, 2025 18:27
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

@YuriiMotov please have a look at the adjustments I made. I hope I could address all your concerns.

Note, I rebased the original commits onto the master branch so test_get_existing_user_current_user does not show as code contributed by me, since I did not change it.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I added a few suggestions that can reduce the diff a bit. Feel free to ignore

@saltie2193, thank you!

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Comment threadbackend/tests/api/routes/test_users.py
Comment threadbackend/tests/api/routes/test_users.py
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

From my side this is ready to merge.

@YuriiMotov, thank you for taking the time to review this pull request!

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has a merge conflict that needs to be resolved.

@github-actionsgithub-actionsBot added conflicts Automatically generated when a PR has a merge conflict and removed conflicts Automatically generated when a PR has a merge conflict labels Sep 20, 2025
# Conflicts:
#	backend/tests/api/routes/test_users.py
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from 796afd5 to 568f0daCompareSeptember 24, 2025 11:53

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @saltie2193! 🚀

And thanks @YuriiMotov for the review and help 🙌

@tiangolo
tiangolo merged commit 4cab9e9 into fastapi:masterJan 22, 2026
16 checks passed
samsam926 pushed a commit to samsam926/KD-Path that referenced this pull request Jan 28, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
BraidaFac pushed a commit to BraidaFac/insurance-broker-api that referenced this pull request Apr 27, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@saltie2193@berar@jonbzt@tiangolo@YuriiMotov@alejsdev
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

🐛 Handle non-existing user IDs in read_user_by_id - #1396

Merged
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user
Jan 22, 2026
Merged

🐛 Handle non-existing user IDs in read_user_by_id#1396
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user

Conversation

@saltie2193

Copy link
Copy Markdown
Contributor

Fix an issue where read_user_by_id would fail to return if the requested user ID did not exist.

  • Return 404 - Not Found when ID does not exist.
  • Request without sufficient permission will always result in 403 - Unauthorized.
  • Add tests to test requesting non-existing user IDs as superuser and normal user.

@alejsdevalejsdev changed the title 👷 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_id.Oct 24, 2024
@alejsdevalejsdev added the bug Something isn't working label Oct 24, 2024
@alejsdevalejsdev changed the title 🐛 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_idOct 24, 2024
@berar

berar commented Nov 7, 2024

Copy link
Copy Markdown

Hello. I'd like to know why this pull request has not been approved. It is valid.

@jonbzt

Copy link
Copy Markdown

Yeah pretty minor upgrade but it makes sens to merge IMO.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saltie2193, thanks for working on this!

Please, take a look at my change suggestions.
Basically, I think we should leave existing tests untouched (only rename test_get_existing_user -> test_get_existing_user_as_superuser) and add 2 test for non-existing user (superuser - 404, regular user - 403)

Comment on lines +91 to +93
@pytest.mark.parametrize(
"is_superuser", (True, False), ids=lambda x: "superuser" if x else "normal user"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case with is_superuser=True is already covered by test_get_existing_user_as_superuser.
No need to parameterize this test

@saltie2193saltie2193Sep 5, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be the same as in test_get_existing_user_as_superuser.

test_get_existing_user_as_superuser tests whether a user authenticated as superuser is able to access another user. (User A tries to access data of user B)

test_get_exiting_user_current_user however tests whether a user is allowed to access his own data, independent of them being a superuser or not. (User A tries to access data of user A)

That's at least what they are intended to test.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is to ensure that superuser can access their own user information, not only other user's information, right?
I still think this is redundant. I believe the chance somebody writes the algorithm this way is extremely low..

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It's to ensure superuser privileges don't influence it.
Sure might be excessive but it's just an additional simple case of the test, ensuring the correct function of the backend, and not even expensive.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I can come up with 10 more additional tests. And all of them will be hypothetically possible.
I think we should consider:

  • what is the probability that somebody writes this function this way (superuser can access random user, but can't access their own info. At the same time normal user can access their own info)?
  • every change is additional load for people who will review it and read this code later

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean especially when talking about authentication and authorization it do think it's not unlikely to not think about something like this, that seems really easy ans stupid. Especially when looking at differences between superusers and non superuser. Often the most simple parts are overlooked because people thought it's obvious how it's supposed to work and nobody would ever make a mistake like that.
This just uses as simple test case in a preventive way ensuring the backend is working as intended and at the same time explicitly documents the intended behavior.

But I do understand and have to respect it if this project does not want to use test cases in this way.

So we only test if the current user (authenticated as non-superuser) is able to access his data and I drop the changes to test_get_existing_user_current_user?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep test_get_existing_user_current_user as it was before this PR

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Fix an issue where `read_user_by_id` would fail to return if the requested user ID did not exist.
* Return `404 - Not Found` when ID does not exist.
* Request without sufficient permission will always result in `403 - Unauthorized`.
* Add tests to test requesting non-existing user IDs as superuser and normal user.
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from a2dd74f to e031948CompareSeptember 5, 2025 18:27
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

@YuriiMotov please have a look at the adjustments I made. I hope I could address all your concerns.

Note, I rebased the original commits onto the master branch so test_get_existing_user_current_user does not show as code contributed by me, since I did not change it.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I added a few suggestions that can reduce the diff a bit. Feel free to ignore

@saltie2193, thank you!

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Comment threadbackend/tests/api/routes/test_users.py
Comment threadbackend/tests/api/routes/test_users.py
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

From my side this is ready to merge.

@YuriiMotov, thank you for taking the time to review this pull request!

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has a merge conflict that needs to be resolved.

@github-actionsgithub-actionsBot added conflicts Automatically generated when a PR has a merge conflict and removed conflicts Automatically generated when a PR has a merge conflict labels Sep 20, 2025
# Conflicts:
#	backend/tests/api/routes/test_users.py
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from 796afd5 to 568f0daCompareSeptember 24, 2025 11:53

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @saltie2193! 🚀

And thanks @YuriiMotov for the review and help 🙌

@tiangolo
tiangolo merged commit 4cab9e9 into fastapi:masterJan 22, 2026
16 checks passed
samsam926 pushed a commit to samsam926/KD-Path that referenced this pull request Jan 28, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
BraidaFac pushed a commit to BraidaFac/insurance-broker-api that referenced this pull request Apr 27, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@saltie2193@berar@jonbzt@tiangolo@YuriiMotov@alejsdev
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

🐛 Handle non-existing user IDs in read_user_by_id - #1396

Merged
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user
Jan 22, 2026
Merged

🐛 Handle non-existing user IDs in read_user_by_id#1396
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user

Conversation

@saltie2193

Copy link
Copy Markdown
Contributor

Fix an issue where read_user_by_id would fail to return if the requested user ID did not exist.

  • Return 404 - Not Found when ID does not exist.
  • Request without sufficient permission will always result in 403 - Unauthorized.
  • Add tests to test requesting non-existing user IDs as superuser and normal user.

@alejsdevalejsdev changed the title 👷 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_id.Oct 24, 2024
@alejsdevalejsdev added the bug Something isn't working label Oct 24, 2024
@alejsdevalejsdev changed the title 🐛 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_idOct 24, 2024
@berar

berar commented Nov 7, 2024

Copy link
Copy Markdown

Hello. I'd like to know why this pull request has not been approved. It is valid.

@jonbzt

Copy link
Copy Markdown

Yeah pretty minor upgrade but it makes sens to merge IMO.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saltie2193, thanks for working on this!

Please, take a look at my change suggestions.
Basically, I think we should leave existing tests untouched (only rename test_get_existing_user -> test_get_existing_user_as_superuser) and add 2 test for non-existing user (superuser - 404, regular user - 403)

Comment on lines +91 to +93
@pytest.mark.parametrize(
"is_superuser", (True, False), ids=lambda x: "superuser" if x else "normal user"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case with is_superuser=True is already covered by test_get_existing_user_as_superuser.
No need to parameterize this test

@saltie2193saltie2193Sep 5, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be the same as in test_get_existing_user_as_superuser.

test_get_existing_user_as_superuser tests whether a user authenticated as superuser is able to access another user. (User A tries to access data of user B)

test_get_exiting_user_current_user however tests whether a user is allowed to access his own data, independent of them being a superuser or not. (User A tries to access data of user A)

That's at least what they are intended to test.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is to ensure that superuser can access their own user information, not only other user's information, right?
I still think this is redundant. I believe the chance somebody writes the algorithm this way is extremely low..

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It's to ensure superuser privileges don't influence it.
Sure might be excessive but it's just an additional simple case of the test, ensuring the correct function of the backend, and not even expensive.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I can come up with 10 more additional tests. And all of them will be hypothetically possible.
I think we should consider:

  • what is the probability that somebody writes this function this way (superuser can access random user, but can't access their own info. At the same time normal user can access their own info)?
  • every change is additional load for people who will review it and read this code later

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean especially when talking about authentication and authorization it do think it's not unlikely to not think about something like this, that seems really easy ans stupid. Especially when looking at differences between superusers and non superuser. Often the most simple parts are overlooked because people thought it's obvious how it's supposed to work and nobody would ever make a mistake like that.
This just uses as simple test case in a preventive way ensuring the backend is working as intended and at the same time explicitly documents the intended behavior.

But I do understand and have to respect it if this project does not want to use test cases in this way.

So we only test if the current user (authenticated as non-superuser) is able to access his data and I drop the changes to test_get_existing_user_current_user?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep test_get_existing_user_current_user as it was before this PR

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Fix an issue where `read_user_by_id` would fail to return if the requested user ID did not exist.
* Return `404 - Not Found` when ID does not exist.
* Request without sufficient permission will always result in `403 - Unauthorized`.
* Add tests to test requesting non-existing user IDs as superuser and normal user.
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from a2dd74f to e031948CompareSeptember 5, 2025 18:27
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

@YuriiMotov please have a look at the adjustments I made. I hope I could address all your concerns.

Note, I rebased the original commits onto the master branch so test_get_existing_user_current_user does not show as code contributed by me, since I did not change it.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I added a few suggestions that can reduce the diff a bit. Feel free to ignore

@saltie2193, thank you!

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Comment threadbackend/tests/api/routes/test_users.py
Comment threadbackend/tests/api/routes/test_users.py
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

From my side this is ready to merge.

@YuriiMotov, thank you for taking the time to review this pull request!

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has a merge conflict that needs to be resolved.

@github-actionsgithub-actionsBot added conflicts Automatically generated when a PR has a merge conflict and removed conflicts Automatically generated when a PR has a merge conflict labels Sep 20, 2025
# Conflicts:
#	backend/tests/api/routes/test_users.py
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from 796afd5 to 568f0daCompareSeptember 24, 2025 11:53

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @saltie2193! 🚀

And thanks @YuriiMotov for the review and help 🙌

@tiangolo
tiangolo merged commit 4cab9e9 into fastapi:masterJan 22, 2026
16 checks passed
samsam926 pushed a commit to samsam926/KD-Path that referenced this pull request Jan 28, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
BraidaFac pushed a commit to BraidaFac/insurance-broker-api that referenced this pull request Apr 27, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@saltie2193@berar@jonbzt@tiangolo@YuriiMotov@alejsdev
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

🐛 Handle non-existing user IDs in read_user_by_id - #1396

Merged
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user
Jan 22, 2026
Merged

🐛 Handle non-existing user IDs in read_user_by_id#1396
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user

Conversation

@saltie2193

Copy link
Copy Markdown
Contributor

Fix an issue where read_user_by_id would fail to return if the requested user ID did not exist.

  • Return 404 - Not Found when ID does not exist.
  • Request without sufficient permission will always result in 403 - Unauthorized.
  • Add tests to test requesting non-existing user IDs as superuser and normal user.

@alejsdevalejsdev changed the title 👷 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_id.Oct 24, 2024
@alejsdevalejsdev added the bug Something isn't working label Oct 24, 2024
@alejsdevalejsdev changed the title 🐛 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_idOct 24, 2024
@berar

berar commented Nov 7, 2024

Copy link
Copy Markdown

Hello. I'd like to know why this pull request has not been approved. It is valid.

@jonbzt

Copy link
Copy Markdown

Yeah pretty minor upgrade but it makes sens to merge IMO.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saltie2193, thanks for working on this!

Please, take a look at my change suggestions.
Basically, I think we should leave existing tests untouched (only rename test_get_existing_user -> test_get_existing_user_as_superuser) and add 2 test for non-existing user (superuser - 404, regular user - 403)

Comment on lines +91 to +93
@pytest.mark.parametrize(
"is_superuser", (True, False), ids=lambda x: "superuser" if x else "normal user"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case with is_superuser=True is already covered by test_get_existing_user_as_superuser.
No need to parameterize this test

@saltie2193saltie2193Sep 5, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be the same as in test_get_existing_user_as_superuser.

test_get_existing_user_as_superuser tests whether a user authenticated as superuser is able to access another user. (User A tries to access data of user B)

test_get_exiting_user_current_user however tests whether a user is allowed to access his own data, independent of them being a superuser or not. (User A tries to access data of user A)

That's at least what they are intended to test.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is to ensure that superuser can access their own user information, not only other user's information, right?
I still think this is redundant. I believe the chance somebody writes the algorithm this way is extremely low..

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It's to ensure superuser privileges don't influence it.
Sure might be excessive but it's just an additional simple case of the test, ensuring the correct function of the backend, and not even expensive.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I can come up with 10 more additional tests. And all of them will be hypothetically possible.
I think we should consider:

  • what is the probability that somebody writes this function this way (superuser can access random user, but can't access their own info. At the same time normal user can access their own info)?
  • every change is additional load for people who will review it and read this code later

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean especially when talking about authentication and authorization it do think it's not unlikely to not think about something like this, that seems really easy ans stupid. Especially when looking at differences between superusers and non superuser. Often the most simple parts are overlooked because people thought it's obvious how it's supposed to work and nobody would ever make a mistake like that.
This just uses as simple test case in a preventive way ensuring the backend is working as intended and at the same time explicitly documents the intended behavior.

But I do understand and have to respect it if this project does not want to use test cases in this way.

So we only test if the current user (authenticated as non-superuser) is able to access his data and I drop the changes to test_get_existing_user_current_user?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep test_get_existing_user_current_user as it was before this PR

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Fix an issue where `read_user_by_id` would fail to return if the requested user ID did not exist.
* Return `404 - Not Found` when ID does not exist.
* Request without sufficient permission will always result in `403 - Unauthorized`.
* Add tests to test requesting non-existing user IDs as superuser and normal user.
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from a2dd74f to e031948CompareSeptember 5, 2025 18:27
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

@YuriiMotov please have a look at the adjustments I made. I hope I could address all your concerns.

Note, I rebased the original commits onto the master branch so test_get_existing_user_current_user does not show as code contributed by me, since I did not change it.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I added a few suggestions that can reduce the diff a bit. Feel free to ignore

@saltie2193, thank you!

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Comment threadbackend/tests/api/routes/test_users.py
Comment threadbackend/tests/api/routes/test_users.py
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

From my side this is ready to merge.

@YuriiMotov, thank you for taking the time to review this pull request!

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has a merge conflict that needs to be resolved.

@github-actionsgithub-actionsBot added conflicts Automatically generated when a PR has a merge conflict and removed conflicts Automatically generated when a PR has a merge conflict labels Sep 20, 2025
# Conflicts:
#	backend/tests/api/routes/test_users.py
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from 796afd5 to 568f0daCompareSeptember 24, 2025 11:53

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @saltie2193! 🚀

And thanks @YuriiMotov for the review and help 🙌

@tiangolo
tiangolo merged commit 4cab9e9 into fastapi:masterJan 22, 2026
16 checks passed
samsam926 pushed a commit to samsam926/KD-Path that referenced this pull request Jan 28, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
BraidaFac pushed a commit to BraidaFac/insurance-broker-api that referenced this pull request Apr 27, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@saltie2193@berar@jonbzt@tiangolo@YuriiMotov@alejsdev
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

🐛 Handle non-existing user IDs in read_user_by_id - #1396

Merged
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user
Jan 22, 2026
Merged

🐛 Handle non-existing user IDs in read_user_by_id#1396
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user

Conversation

@saltie2193

Copy link
Copy Markdown
Contributor

Fix an issue where read_user_by_id would fail to return if the requested user ID did not exist.

  • Return 404 - Not Found when ID does not exist.
  • Request without sufficient permission will always result in 403 - Unauthorized.
  • Add tests to test requesting non-existing user IDs as superuser and normal user.

@alejsdevalejsdev changed the title 👷 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_id.Oct 24, 2024
@alejsdevalejsdev added the bug Something isn't working label Oct 24, 2024
@alejsdevalejsdev changed the title 🐛 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_idOct 24, 2024
@berar

berar commented Nov 7, 2024

Copy link
Copy Markdown

Hello. I'd like to know why this pull request has not been approved. It is valid.

@jonbzt

Copy link
Copy Markdown

Yeah pretty minor upgrade but it makes sens to merge IMO.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saltie2193, thanks for working on this!

Please, take a look at my change suggestions.
Basically, I think we should leave existing tests untouched (only rename test_get_existing_user -> test_get_existing_user_as_superuser) and add 2 test for non-existing user (superuser - 404, regular user - 403)

Comment on lines +91 to +93
@pytest.mark.parametrize(
"is_superuser", (True, False), ids=lambda x: "superuser" if x else "normal user"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case with is_superuser=True is already covered by test_get_existing_user_as_superuser.
No need to parameterize this test

@saltie2193saltie2193Sep 5, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be the same as in test_get_existing_user_as_superuser.

test_get_existing_user_as_superuser tests whether a user authenticated as superuser is able to access another user. (User A tries to access data of user B)

test_get_exiting_user_current_user however tests whether a user is allowed to access his own data, independent of them being a superuser or not. (User A tries to access data of user A)

That's at least what they are intended to test.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is to ensure that superuser can access their own user information, not only other user's information, right?
I still think this is redundant. I believe the chance somebody writes the algorithm this way is extremely low..

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It's to ensure superuser privileges don't influence it.
Sure might be excessive but it's just an additional simple case of the test, ensuring the correct function of the backend, and not even expensive.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I can come up with 10 more additional tests. And all of them will be hypothetically possible.
I think we should consider:

  • what is the probability that somebody writes this function this way (superuser can access random user, but can't access their own info. At the same time normal user can access their own info)?
  • every change is additional load for people who will review it and read this code later

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean especially when talking about authentication and authorization it do think it's not unlikely to not think about something like this, that seems really easy ans stupid. Especially when looking at differences between superusers and non superuser. Often the most simple parts are overlooked because people thought it's obvious how it's supposed to work and nobody would ever make a mistake like that.
This just uses as simple test case in a preventive way ensuring the backend is working as intended and at the same time explicitly documents the intended behavior.

But I do understand and have to respect it if this project does not want to use test cases in this way.

So we only test if the current user (authenticated as non-superuser) is able to access his data and I drop the changes to test_get_existing_user_current_user?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep test_get_existing_user_current_user as it was before this PR

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Fix an issue where `read_user_by_id` would fail to return if the requested user ID did not exist.
* Return `404 - Not Found` when ID does not exist.
* Request without sufficient permission will always result in `403 - Unauthorized`.
* Add tests to test requesting non-existing user IDs as superuser and normal user.
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from a2dd74f to e031948CompareSeptember 5, 2025 18:27
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

@YuriiMotov please have a look at the adjustments I made. I hope I could address all your concerns.

Note, I rebased the original commits onto the master branch so test_get_existing_user_current_user does not show as code contributed by me, since I did not change it.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I added a few suggestions that can reduce the diff a bit. Feel free to ignore

@saltie2193, thank you!

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Comment threadbackend/tests/api/routes/test_users.py
Comment threadbackend/tests/api/routes/test_users.py
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

From my side this is ready to merge.

@YuriiMotov, thank you for taking the time to review this pull request!

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has a merge conflict that needs to be resolved.

@github-actionsgithub-actionsBot added conflicts Automatically generated when a PR has a merge conflict and removed conflicts Automatically generated when a PR has a merge conflict labels Sep 20, 2025
# Conflicts:
#	backend/tests/api/routes/test_users.py
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from 796afd5 to 568f0daCompareSeptember 24, 2025 11:53

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @saltie2193! 🚀

And thanks @YuriiMotov for the review and help 🙌

@tiangolo
tiangolo merged commit 4cab9e9 into fastapi:masterJan 22, 2026
16 checks passed
samsam926 pushed a commit to samsam926/KD-Path that referenced this pull request Jan 28, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
BraidaFac pushed a commit to BraidaFac/insurance-broker-api that referenced this pull request Apr 27, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@saltie2193@berar@jonbzt@tiangolo@YuriiMotov@alejsdev
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

🐛 Handle non-existing user IDs in read_user_by_id - #1396

Merged
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user
Jan 22, 2026
Merged

🐛 Handle non-existing user IDs in read_user_by_id#1396
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user

Conversation

@saltie2193

Copy link
Copy Markdown
Contributor

Fix an issue where read_user_by_id would fail to return if the requested user ID did not exist.

  • Return 404 - Not Found when ID does not exist.
  • Request without sufficient permission will always result in 403 - Unauthorized.
  • Add tests to test requesting non-existing user IDs as superuser and normal user.

@alejsdevalejsdev changed the title 👷 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_id.Oct 24, 2024
@alejsdevalejsdev added the bug Something isn't working label Oct 24, 2024
@alejsdevalejsdev changed the title 🐛 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_idOct 24, 2024
@berar

berar commented Nov 7, 2024

Copy link
Copy Markdown

Hello. I'd like to know why this pull request has not been approved. It is valid.

@jonbzt

Copy link
Copy Markdown

Yeah pretty minor upgrade but it makes sens to merge IMO.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saltie2193, thanks for working on this!

Please, take a look at my change suggestions.
Basically, I think we should leave existing tests untouched (only rename test_get_existing_user -> test_get_existing_user_as_superuser) and add 2 test for non-existing user (superuser - 404, regular user - 403)

Comment on lines +91 to +93
@pytest.mark.parametrize(
"is_superuser", (True, False), ids=lambda x: "superuser" if x else "normal user"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case with is_superuser=True is already covered by test_get_existing_user_as_superuser.
No need to parameterize this test

@saltie2193saltie2193Sep 5, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be the same as in test_get_existing_user_as_superuser.

test_get_existing_user_as_superuser tests whether a user authenticated as superuser is able to access another user. (User A tries to access data of user B)

test_get_exiting_user_current_user however tests whether a user is allowed to access his own data, independent of them being a superuser or not. (User A tries to access data of user A)

That's at least what they are intended to test.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is to ensure that superuser can access their own user information, not only other user's information, right?
I still think this is redundant. I believe the chance somebody writes the algorithm this way is extremely low..

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It's to ensure superuser privileges don't influence it.
Sure might be excessive but it's just an additional simple case of the test, ensuring the correct function of the backend, and not even expensive.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I can come up with 10 more additional tests. And all of them will be hypothetically possible.
I think we should consider:

  • what is the probability that somebody writes this function this way (superuser can access random user, but can't access their own info. At the same time normal user can access their own info)?
  • every change is additional load for people who will review it and read this code later

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean especially when talking about authentication and authorization it do think it's not unlikely to not think about something like this, that seems really easy ans stupid. Especially when looking at differences between superusers and non superuser. Often the most simple parts are overlooked because people thought it's obvious how it's supposed to work and nobody would ever make a mistake like that.
This just uses as simple test case in a preventive way ensuring the backend is working as intended and at the same time explicitly documents the intended behavior.

But I do understand and have to respect it if this project does not want to use test cases in this way.

So we only test if the current user (authenticated as non-superuser) is able to access his data and I drop the changes to test_get_existing_user_current_user?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep test_get_existing_user_current_user as it was before this PR

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Fix an issue where `read_user_by_id` would fail to return if the requested user ID did not exist.
* Return `404 - Not Found` when ID does not exist.
* Request without sufficient permission will always result in `403 - Unauthorized`.
* Add tests to test requesting non-existing user IDs as superuser and normal user.
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from a2dd74f to e031948CompareSeptember 5, 2025 18:27
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

@YuriiMotov please have a look at the adjustments I made. I hope I could address all your concerns.

Note, I rebased the original commits onto the master branch so test_get_existing_user_current_user does not show as code contributed by me, since I did not change it.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I added a few suggestions that can reduce the diff a bit. Feel free to ignore

@saltie2193, thank you!

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Comment threadbackend/tests/api/routes/test_users.py
Comment threadbackend/tests/api/routes/test_users.py
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

From my side this is ready to merge.

@YuriiMotov, thank you for taking the time to review this pull request!

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has a merge conflict that needs to be resolved.

@github-actionsgithub-actionsBot added conflicts Automatically generated when a PR has a merge conflict and removed conflicts Automatically generated when a PR has a merge conflict labels Sep 20, 2025
# Conflicts:
#	backend/tests/api/routes/test_users.py
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from 796afd5 to 568f0daCompareSeptember 24, 2025 11:53

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @saltie2193! 🚀

And thanks @YuriiMotov for the review and help 🙌

@tiangolo
tiangolo merged commit 4cab9e9 into fastapi:masterJan 22, 2026
16 checks passed
samsam926 pushed a commit to samsam926/KD-Path that referenced this pull request Jan 28, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
BraidaFac pushed a commit to BraidaFac/insurance-broker-api that referenced this pull request Apr 27, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@saltie2193@berar@jonbzt@tiangolo@YuriiMotov@alejsdev
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

🐛 Handle non-existing user IDs in read_user_by_id - #1396

Merged
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user
Jan 22, 2026
Merged

🐛 Handle non-existing user IDs in read_user_by_id#1396
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user

Conversation

@saltie2193

Copy link
Copy Markdown
Contributor

Fix an issue where read_user_by_id would fail to return if the requested user ID did not exist.

  • Return 404 - Not Found when ID does not exist.
  • Request without sufficient permission will always result in 403 - Unauthorized.
  • Add tests to test requesting non-existing user IDs as superuser and normal user.

@alejsdevalejsdev changed the title 👷 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_id.Oct 24, 2024
@alejsdevalejsdev added the bug Something isn't working label Oct 24, 2024
@alejsdevalejsdev changed the title 🐛 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_idOct 24, 2024
@berar

berar commented Nov 7, 2024

Copy link
Copy Markdown

Hello. I'd like to know why this pull request has not been approved. It is valid.

@jonbzt

Copy link
Copy Markdown

Yeah pretty minor upgrade but it makes sens to merge IMO.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saltie2193, thanks for working on this!

Please, take a look at my change suggestions.
Basically, I think we should leave existing tests untouched (only rename test_get_existing_user -> test_get_existing_user_as_superuser) and add 2 test for non-existing user (superuser - 404, regular user - 403)

Comment on lines +91 to +93
@pytest.mark.parametrize(
"is_superuser", (True, False), ids=lambda x: "superuser" if x else "normal user"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case with is_superuser=True is already covered by test_get_existing_user_as_superuser.
No need to parameterize this test

@saltie2193saltie2193Sep 5, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be the same as in test_get_existing_user_as_superuser.

test_get_existing_user_as_superuser tests whether a user authenticated as superuser is able to access another user. (User A tries to access data of user B)

test_get_exiting_user_current_user however tests whether a user is allowed to access his own data, independent of them being a superuser or not. (User A tries to access data of user A)

That's at least what they are intended to test.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is to ensure that superuser can access their own user information, not only other user's information, right?
I still think this is redundant. I believe the chance somebody writes the algorithm this way is extremely low..

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It's to ensure superuser privileges don't influence it.
Sure might be excessive but it's just an additional simple case of the test, ensuring the correct function of the backend, and not even expensive.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I can come up with 10 more additional tests. And all of them will be hypothetically possible.
I think we should consider:

  • what is the probability that somebody writes this function this way (superuser can access random user, but can't access their own info. At the same time normal user can access their own info)?
  • every change is additional load for people who will review it and read this code later

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean especially when talking about authentication and authorization it do think it's not unlikely to not think about something like this, that seems really easy ans stupid. Especially when looking at differences between superusers and non superuser. Often the most simple parts are overlooked because people thought it's obvious how it's supposed to work and nobody would ever make a mistake like that.
This just uses as simple test case in a preventive way ensuring the backend is working as intended and at the same time explicitly documents the intended behavior.

But I do understand and have to respect it if this project does not want to use test cases in this way.

So we only test if the current user (authenticated as non-superuser) is able to access his data and I drop the changes to test_get_existing_user_current_user?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep test_get_existing_user_current_user as it was before this PR

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Fix an issue where `read_user_by_id` would fail to return if the requested user ID did not exist.
* Return `404 - Not Found` when ID does not exist.
* Request without sufficient permission will always result in `403 - Unauthorized`.
* Add tests to test requesting non-existing user IDs as superuser and normal user.
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from a2dd74f to e031948CompareSeptember 5, 2025 18:27
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

@YuriiMotov please have a look at the adjustments I made. I hope I could address all your concerns.

Note, I rebased the original commits onto the master branch so test_get_existing_user_current_user does not show as code contributed by me, since I did not change it.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I added a few suggestions that can reduce the diff a bit. Feel free to ignore

@saltie2193, thank you!

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Comment threadbackend/tests/api/routes/test_users.py
Comment threadbackend/tests/api/routes/test_users.py
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

From my side this is ready to merge.

@YuriiMotov, thank you for taking the time to review this pull request!

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has a merge conflict that needs to be resolved.

@github-actionsgithub-actionsBot added conflicts Automatically generated when a PR has a merge conflict and removed conflicts Automatically generated when a PR has a merge conflict labels Sep 20, 2025
# Conflicts:
#	backend/tests/api/routes/test_users.py
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from 796afd5 to 568f0daCompareSeptember 24, 2025 11:53

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @saltie2193! 🚀

And thanks @YuriiMotov for the review and help 🙌

@tiangolo
tiangolo merged commit 4cab9e9 into fastapi:masterJan 22, 2026
16 checks passed
samsam926 pushed a commit to samsam926/KD-Path that referenced this pull request Jan 28, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
BraidaFac pushed a commit to BraidaFac/insurance-broker-api that referenced this pull request Apr 27, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@saltie2193@berar@jonbzt@tiangolo@YuriiMotov@alejsdev
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

🐛 Handle non-existing user IDs in read_user_by_id - #1396

Merged
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user
Jan 22, 2026
Merged

🐛 Handle non-existing user IDs in read_user_by_id#1396
tiangolo merged 5 commits into
fastapi:masterfrom
saltie2193:backend-read-user-by-id-no-user

Conversation

@saltie2193

Copy link
Copy Markdown
Contributor

Fix an issue where read_user_by_id would fail to return if the requested user ID did not exist.

  • Return 404 - Not Found when ID does not exist.
  • Request without sufficient permission will always result in 403 - Unauthorized.
  • Add tests to test requesting non-existing user IDs as superuser and normal user.

@alejsdevalejsdev changed the title 👷 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_id.Oct 24, 2024
@alejsdevalejsdev added the bug Something isn't working label Oct 24, 2024
@alejsdevalejsdev changed the title 🐛 Handle non-existing user IDs in read_user_by_id.🐛 Handle non-existing user IDs in read_user_by_idOct 24, 2024
@berar

berar commented Nov 7, 2024

Copy link
Copy Markdown

Hello. I'd like to know why this pull request has not been approved. It is valid.

@jonbzt

Copy link
Copy Markdown

Yeah pretty minor upgrade but it makes sens to merge IMO.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saltie2193, thanks for working on this!

Please, take a look at my change suggestions.
Basically, I think we should leave existing tests untouched (only rename test_get_existing_user -> test_get_existing_user_as_superuser) and add 2 test for non-existing user (superuser - 404, regular user - 403)

Comment on lines +91 to +93
@pytest.mark.parametrize(
"is_superuser", (True, False), ids=lambda x: "superuser" if x else "normal user"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case with is_superuser=True is already covered by test_get_existing_user_as_superuser.
No need to parameterize this test

@saltie2193saltie2193Sep 5, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be the same as in test_get_existing_user_as_superuser.

test_get_existing_user_as_superuser tests whether a user authenticated as superuser is able to access another user. (User A tries to access data of user B)

test_get_exiting_user_current_user however tests whether a user is allowed to access his own data, independent of them being a superuser or not. (User A tries to access data of user A)

That's at least what they are intended to test.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is to ensure that superuser can access their own user information, not only other user's information, right?
I still think this is redundant. I believe the chance somebody writes the algorithm this way is extremely low..

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It's to ensure superuser privileges don't influence it.
Sure might be excessive but it's just an additional simple case of the test, ensuring the correct function of the backend, and not even expensive.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I can come up with 10 more additional tests. And all of them will be hypothetically possible.
I think we should consider:

  • what is the probability that somebody writes this function this way (superuser can access random user, but can't access their own info. At the same time normal user can access their own info)?
  • every change is additional load for people who will review it and read this code later

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean especially when talking about authentication and authorization it do think it's not unlikely to not think about something like this, that seems really easy ans stupid. Especially when looking at differences between superusers and non superuser. Often the most simple parts are overlooked because people thought it's obvious how it's supposed to work and nobody would ever make a mistake like that.
This just uses as simple test case in a preventive way ensuring the backend is working as intended and at the same time explicitly documents the intended behavior.

But I do understand and have to respect it if this project does not want to use test cases in this way.

So we only test if the current user (authenticated as non-superuser) is able to access his data and I drop the changes to test_get_existing_user_current_user?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep test_get_existing_user_current_user as it was before this PR

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Fix an issue where `read_user_by_id` would fail to return if the requested user ID did not exist.
* Return `404 - Not Found` when ID does not exist.
* Request without sufficient permission will always result in `403 - Unauthorized`.
* Add tests to test requesting non-existing user IDs as superuser and normal user.
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from a2dd74f to e031948CompareSeptember 5, 2025 18:27
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

@YuriiMotov please have a look at the adjustments I made. I hope I could address all your concerns.

Note, I rebased the original commits onto the master branch so test_get_existing_user_current_user does not show as code contributed by me, since I did not change it.

@YuriiMotovYuriiMotov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I added a few suggestions that can reduce the diff a bit. Feel free to ignore

@saltie2193, thank you!

Comment threadbackend/app/tests/api/routes/test_users.py Outdated
Comment threadbackend/tests/api/routes/test_users.py
Comment threadbackend/tests/api/routes/test_users.py
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
@saltie2193

Copy link
Copy Markdown
ContributorAuthor

From my side this is ready to merge.

@YuriiMotov, thank you for taking the time to review this pull request!

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has a merge conflict that needs to be resolved.

@github-actionsgithub-actionsBot added conflicts Automatically generated when a PR has a merge conflict and removed conflicts Automatically generated when a PR has a merge conflict labels Sep 20, 2025
# Conflicts:
#	backend/tests/api/routes/test_users.py
@saltie2193
saltie2193force-pushed the backend-read-user-by-id-no-user branch from 796afd5 to 568f0daCompareSeptember 24, 2025 11:53

@tiangolotiangolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @saltie2193! 🚀

And thanks @YuriiMotov for the review and help 🙌

@tiangolo
tiangolo merged commit 4cab9e9 into fastapi:masterJan 22, 2026
16 checks passed
samsam926 pushed a commit to samsam926/KD-Path that referenced this pull request Jan 28, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
BraidaFac pushed a commit to BraidaFac/insurance-broker-api that referenced this pull request Apr 27, 2026
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugSomething isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@saltie2193@berar@jonbzt@tiangolo@YuriiMotov@alejsdev