Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Change 'bool CanSyncProject' to 'bool IsProjectMember' #1235

Merged
merged 1 commit into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/LexBoxApi/Controllers/IntegrationController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
[ProducesResponseType(StatusCodes.Status302Found)]
public async Task<ActionResult> OpenWithFlex(Guid projectId)
{
if (!await permissionService.CanSyncProjectAsync(projectId)) return Unauthorized();
if (!await permissionService.CanSyncProject(projectId)) return Unauthorized();
var project = await lexBoxDbContext.Projects.FirstOrDefaultAsync(p => p.Id == projectId);
if (project is null) return NotFound();
var repoId = await hgService.GetRepositoryIdentifier(project);
Expand All @@ -59,7 +59,7 @@
public async Task<ActionResult<RefreshResponse>> GetProjectToken(string projectCode)
{
var projectId = await projectService.LookupProjectId(projectCode);
if (projectId == default) return NotFound();

Check warning on line 62 in backend/LexBoxApi/Controllers/IntegrationController.cs

View workflow job for this annotation

GitHub Actions / Build API / publish-api

Action method returns undeclared status code '404'
return GetRefreshResponse(projectId);
}

Expand Down
2 changes: 1 addition & 1 deletion backend/LexBoxApi/GraphQL/LexQueries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ public IQueryable<User> UsersInMyOrg(LexBoxDbContext context, LoggedInContext lo
}
});
// Members and non-members alike can see all public projects plus their own
org.Projects = org.Projects?.Where(p => p.IsConfidential == false || permissionService.CanSyncProject(p.Id))?.ToList() ?? [];
org.Projects = org.Projects?.Where(p => p.IsConfidential == false || permissionService.IsProjectMember(p.Id, updatedUser))?.ToList() ?? [];
hahn-kev marked this conversation as resolved.
Show resolved Hide resolved
if (!permissionService.IsOrgMember(orgId, updatedUser))
{
// Non-members also cannot see membership, only org admins
Expand Down
23 changes: 12 additions & 11 deletions backend/LexBoxApi/Services/PermissionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ private async ValueTask<bool> ManagesOrgThatOwnsProject(Guid projectId, LexAuthU
// Org admins can view, edit, and sync all projects, even confidential ones
var managedOrgIds = user.Orgs.Where(o => o.Role == OrgRole.Admin).Select(o => o.OrgId).ToHashSet();
var projectOrgIds = await projectService.LookupProjectOrgIds(projectId);
if (projectOrgIds.Any(oId => managedOrgIds.Contains(oId))) return true;
if (projectOrgIds.Any(managedOrgIds.Contains)) return true;
}
return false;
}
Expand All @@ -31,7 +31,7 @@ private async ValueTask<bool> IsMemberOfOrgThatOwnsProject(Guid projectId)
{
var memberOfOrgIds = User.Orgs.Select(o => o.OrgId).ToHashSet();
var projectOrgIds = await projectService.LookupProjectOrgIds(projectId);
if (projectOrgIds.Any(oId => memberOfOrgIds.Contains(oId))) return true;
if (projectOrgIds.Any(memberOfOrgIds.Contains)) return true;
}
return false;
}
Expand All @@ -40,20 +40,21 @@ public async ValueTask<bool> CanSyncProject(string projectCode)
{
if (User is null) return false;
if (User.Role == UserRole.admin) return true;
return await CanSyncProjectAsync(await projectService.LookupProjectId(projectCode));
return await CanSyncProject(await projectService.LookupProjectId(projectCode));
}

public bool CanSyncProject(Guid projectId)
public bool IsProjectMember(Guid projectId, LexAuthUser? overrideUser = null)
{
if (User is null) return false;
if (User.Role == UserRole.admin) return true;
if (User.Projects is null) return false;
return User.IsProjectMember(projectId);
var user = overrideUser ?? User;
if (user is null) return false;
return user.IsProjectMember(projectId);
}

public async ValueTask<bool> CanSyncProjectAsync(Guid projectId)
public async ValueTask<bool> CanSyncProject(Guid projectId)
{
if (CanSyncProject(projectId)) return true;
if (User is null) return false;
if (User.Role == UserRole.admin) return true;
if (User.IsProjectMember(projectId)) return true;
// Org managers can sync any project owned by their org(s)
return await ManagesOrgThatOwnsProject(projectId);
}
Expand All @@ -65,7 +66,7 @@ public async ValueTask AssertCanSyncProject(string projectCode)

public async ValueTask AssertCanSyncProject(Guid projectId)
{
if (!await CanSyncProjectAsync(projectId)) throw new UnauthorizedAccessException();
if (!await CanSyncProject(projectId)) throw new UnauthorizedAccessException();
}

public async ValueTask<bool> CanViewProject(Guid projectId, LexAuthUser? overrideUser = null)
Expand Down
2 changes: 2 additions & 0 deletions backend/LexCore/Auth/LexAuthUser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ public ClaimsPrincipal GetPrincipal(string authenticationType)

public bool IsProjectMember(Guid projectId, ProjectRole? role = null)
{
if (Projects is null) return false;

if (role is not null)
{
return Projects.Any(p => p.ProjectId == projectId && p.Role == role);
Expand Down
11 changes: 2 additions & 9 deletions backend/LexCore/ServiceInterfaces/IPermissionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,8 @@ namespace LexCore.ServiceInterfaces;
public interface IPermissionService
{
ValueTask<bool> CanSyncProject(string projectCode);
/// <summary>
/// Does NOT check permissions for org managers, because that requires async DB access.
/// Use CanSyncProject(projectCode) or CanSyncProjectAsync(projectId) if org manager permissions also need to be checked.
/// </summary>
bool CanSyncProject(Guid projectId);
/// <summary>
/// Does all the checks from CanSyncProject, plus allows org managers to access the org as well.
/// </summary>
ValueTask<bool> CanSyncProjectAsync(Guid projectId);
bool IsProjectMember(Guid projectId, LexAuthUser? overrideUser = null);
ValueTask<bool> CanSyncProject(Guid projectId);
ValueTask AssertCanSyncProject(string projectCode);
ValueTask AssertCanSyncProject(Guid projectId);
ValueTask<bool> CanViewProject(Guid projectId, LexAuthUser? overrideUser = null);
Expand Down
Loading