Skip to content

[PermissionService] Update authenticated user handling#3876

Merged
imnasnainaec merged 13 commits intomasterfrom
perm-service
Jun 17, 2025
Merged

[PermissionService] Update authenticated user handling#3876
imnasnainaec merged 13 commits intomasterfrom
perm-service

Conversation

@imnasnainaec
Copy link
Collaborator

@imnasnainaec imnasnainaec commented Jun 12, 2025

This change is Reviewable

@codecov
Copy link

codecov bot commented Jun 12, 2025

Codecov Report

Attention: Patch coverage is 46.66667% with 8 lines in your changes missing coverage. Please review.

Project coverage is 74.41%. Comparing base (f04266c) to head (b0838bf).
Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
Backend/Services/PermissionService.cs 20.00% 5 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3876      +/-   ##
==========================================
- Coverage   74.48%   74.41%   -0.07%     
==========================================
  Files         287      287              
  Lines       10672    10667       -5     
  Branches     1327     1330       +3     
==========================================
- Hits         7949     7938      -11     
- Misses       2339     2344       +5     
- Partials      384      385       +1     
Flag Coverage Δ
backend 85.50% <46.66%> (-0.15%) ⬇️
frontend 66.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@hahn-kev hahn-kev left a comment

Choose a reason for hiding this comment

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

nice job, I left a few suggestions, it's mostly API design related and not security related.

I would suggest changing IsSiteAdmin so that if the user's not logged in it just returns false, where as right now it'll throw an error, that's quite unexpected. Additionally IsCurrentUserAuthenticated seems to be used a lot, even in places where we know the request came from an authenticated context, I would only expect that API to be used in places where the request was AllowAnonymous (or maybe highly sensitive areas where code accidentally calling without auth would be catastrophic).

public async Task<IActionResult> UploadAvatar(IFormFile? file)
{
if (!_permissionService.IsCurrentUserAuthorized(HttpContext))
if (!_permissionService.IsCurrentUserAuthenticated(HttpContext))
Copy link
Contributor

Choose a reason for hiding this comment

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

reading this new name makes sense, but now it begs the question. Why does UploadAvatar require Authentication when DownloadAvatar does not? Well actually since this Controller has the Authorize attribute, the user is already authenticated. So maybe this whole branch can just go away? along with any other controllers where the request is authenticated at the controller level?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Any user can see the avatar of other users in the project, and the frontend uses the DownloadAvatar api as a direct link, so there are no permissions required.

Copy link
Contributor

Choose a reason for hiding this comment

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

so are you saying you can hit the DownloadAvatar API when not logged in? because I don't think that's actually the case because of the Authorize attribute on the controller.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not when logged out. My understanding was that we add [AllowAnonymous] to specific methods whose url the frontend is using as (e.g.) an image source.

var result = _permService.MakeJwt(user).Result;
const string longEnough = "0123456789abcdefghijklmnopqrstuvwxyz";
Environment.SetEnvironmentVariable(PermissionService.JwtSecretKeyEnv, longEnough);
var result = _permService.MakeJwt(_userRepo.Create(new()).Result!).Result;
Copy link
Contributor

Choose a reason for hiding this comment

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

might I suggest making this test function async? This line should become more readable: var result = await _permService.MakeJwt(await _userRepo.Create(new()))

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

None of the test in this file are async, using .Result everywhere instead. I also think making them async/await is more readable, but that's better left for another time.

{
if (!_permissionService.IsUserIdAuthorized(HttpContext, userId))
if (!_permissionService.IsUserAuthenticated(HttpContext, userId)
&& !await _permissionService.IsSiteAdmin(HttpContext))
Copy link
Contributor

Choose a reason for hiding this comment

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

might I suggest a more descriptive API for permission requests? _permissionService.CanModifyUser, you pass in a UserId internally it checks if you're that user, or if you're an admin. Sure technically this API is for reading the user, but if the permissions are the same between reading and writing then it doesn't matter. Take a look at our permissions API for more Ideas. Interestingly we don't actually have a CanModifyUser permission because we have different APIs for Admins to update a user vs a user updating themselves.

I suggest this because I initially read this incorrectly and thought it would only let an admin update their own account.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good idea! Done.

Copy link
Collaborator Author

@imnasnainaec imnasnainaec left a comment

Choose a reason for hiding this comment

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

IsSiteAdmin is being removed in another pr, so I'll leave it alone here.

Since we apparently use IsCurrentUserAuthenticated unnecessarily in so many places (also noted by Tim), that's probably good for it's own pr.

Reviewable status: 0 of 11 files reviewed, 3 unresolved discussions (waiting on @hahn-kev and @imnasnainaec)

public async Task<IActionResult> UploadAvatar(IFormFile? file)
{
if (!_permissionService.IsCurrentUserAuthorized(HttpContext))
if (!_permissionService.IsCurrentUserAuthenticated(HttpContext))
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Any user can see the avatar of other users in the project, and the frontend uses the DownloadAvatar api as a direct link, so there are no permissions required.

{
if (!_permissionService.IsUserIdAuthorized(HttpContext, userId))
if (!_permissionService.IsUserAuthenticated(HttpContext, userId)
&& !await _permissionService.IsSiteAdmin(HttpContext))
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good idea! Done.

var result = _permService.MakeJwt(user).Result;
const string longEnough = "0123456789abcdefghijklmnopqrstuvwxyz";
Environment.SetEnvironmentVariable(PermissionService.JwtSecretKeyEnv, longEnough);
var result = _permService.MakeJwt(_userRepo.Create(new()).Result!).Result;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

None of the test in this file are async, using .Result everywhere instead. I also think making them async/await is more readable, but that's better left for another time.

Copy link
Collaborator Author

@imnasnainaec imnasnainaec left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 11 files reviewed, 3 unresolved discussions (waiting on @hahn-kev and @imnasnainaec)

public async Task<IActionResult> UploadAvatar(IFormFile? file)
{
if (!_permissionService.IsCurrentUserAuthorized(HttpContext))
if (!_permissionService.IsCurrentUserAuthenticated(HttpContext))
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not when logged out. My understanding was that we add [AllowAnonymous] to specific methods whose url the frontend is using as (e.g.) an image source.

Copy link
Contributor

@hahn-kev hahn-kev left a comment

Choose a reason for hiding this comment

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

looks good to me!

@imnasnainaec imnasnainaec merged commit 43b56a0 into master Jun 17, 2025
17 of 18 checks passed
@imnasnainaec imnasnainaec deleted the perm-service branch June 17, 2025 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants