Skip to content

Commit

Permalink
chore(controller): prevent access to deleted projects (#3112)
Browse files Browse the repository at this point in the history
  • Loading branch information
jialeicui authored Jan 5, 2024
1 parent 456f07a commit e30c32c
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import ai.starwhale.mlops.domain.user.bo.Role;
import ai.starwhale.mlops.domain.user.bo.User;
import ai.starwhale.mlops.exception.StarwhaleException;
import ai.starwhale.mlops.exception.SwNotFoundException;
import ai.starwhale.mlops.exception.SwNotFoundException.ResourceType;
import ai.starwhale.mlops.exception.SwValidationException;
import io.jsonwebtoken.Claims;
import java.io.IOException;
Expand Down Expand Up @@ -66,9 +68,13 @@ public JwtTokenFilter(JwtTokenUtil jwtTokenUtil, UserService userService, Projec
}

boolean allowAnonymous(HttpServletRequest request) {
var projects = getProjects(request);
// only for public project
return projects.stream().allMatch(p -> p.getPrivacy() == Project.Privacy.PUBLIC);
try {
var projects = getProjects(request);
// only for public project
return projects.stream().allMatch(p -> p.getPrivacy() == Project.Privacy.PUBLIC);
} catch (SwNotFoundException e) {
return false;
}
}

@Override
Expand Down Expand Up @@ -120,6 +126,9 @@ protected void doFilterInternal(HttpServletRequest httpServletRequest,
Set<Project> projects = getProjects(httpServletRequest);
Set<Role> rolesOfUser = userService.getProjectsRolesOfUser(user, projects);
roles.addAll(rolesOfUser);
} catch (SwNotFoundException e) {
error(httpServletResponse, HttpStatus.NOT_FOUND.value(), Code.validationException, e.getMessage());
return;
} catch (StarwhaleException e) {
logger.error(e.getMessage());
}
Expand All @@ -133,12 +142,18 @@ protected void doFilterInternal(HttpServletRequest httpServletRequest,
}

@NotNull
private Set<Project> getProjects(HttpServletRequest httpServletRequest) {
private Set<Project> getProjects(HttpServletRequest httpServletRequest) throws SwNotFoundException {
@SuppressWarnings("unchecked")
Set<Project> projects = ((Set<String>) httpServletRequest
.getAttribute(ProjectDetectionFilter.ATTRIBUTE_PROJECT))
.stream()
.map(projectService::findProject)
.map((String projectUrl) -> {
var p = projectService.findProject(projectUrl);
if (p.isDeleted()) {
throw new SwNotFoundException(ResourceType.PROJECT, "Project is deleted");
}
return p;
})
.collect(Collectors.toSet());
return projects;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package ai.starwhale.mlops.configuration.security;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
Expand All @@ -28,6 +29,7 @@
import ai.starwhale.mlops.domain.project.ProjectService;
import ai.starwhale.mlops.domain.project.bo.Project;
import ai.starwhale.mlops.domain.user.UserService;
import ai.starwhale.mlops.domain.user.bo.User;
import ai.starwhale.mlops.exception.SwValidationException;
import ai.starwhale.mlops.exception.SwValidationException.ValidSubject;
import io.jsonwebtoken.impl.DefaultClaims;
Expand Down Expand Up @@ -65,6 +67,7 @@ public void setup() {
when(jwtTokenUtil.parseJwt("y")).thenThrow(new SwValidationException(ValidSubject.USER));
DefaultClaims claims = new DefaultClaims(Map.of("taskId", "x"));
when(jwtTokenUtil.parseJwt("a")).thenReturn(claims);
userService = mock(UserService.class);
JwtClaimValidator jwtClaimValidator = mock(JwtClaimValidator.class);
doThrow(SwValidationException.class).when(jwtClaimValidator).validClaims(claims);
jwtClaimValidators = List.of(jwtClaimValidator);
Expand Down Expand Up @@ -119,4 +122,21 @@ public void testAnonymous(Project.Privacy privacy, int errorTimes) throws Servle
"Not logged in."), times(errorTimes));
}

@Test
public void testDeletedProject() throws ServletException, IOException {
when(projectService.findProject("deleted"))
.thenReturn(Project.builder().isDeleted(true).build());
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader("Authorization")).thenReturn("Bearer a");
when(request.getAttribute("PROJECT")).thenReturn(Set.of("deleted"));
HttpServletResponse response = mock(HttpServletResponse.class);
FilterChain filterchain = mock(FilterChain.class);
when(jwtTokenUtil.getUsername(any())).thenReturn("foo");
when(userService.loadUserByUsername("foo")).thenReturn(mock(User.class));
jwtTokenFilter = new JwtTokenFilter(jwtTokenUtil, userService, projectService, List.of());
jwtTokenFilter.doFilterInternal(request, response, filterchain);
httpUtilMockedStatic.verify(
() -> HttpUtil.error(response, HttpStatus.NOT_FOUND.value(), Code.validationException,
"Resource is not found Project\nProject is deleted"), times(1));
}
}

0 comments on commit e30c32c

Please sign in to comment.