use of org.pmiops.workbench.exceptions.ForbiddenException in project workbench by all-of-us.
the class AuthInterceptor method preHandle.
/**
* Returns true iff the request is auth'd and should proceed. Publishes authenticated user info
* using Spring's SecurityContext.
* @param handler The Swagger-generated ApiController. It contains our handler as a private
* delegate.
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// OPTIONS methods requests don't need authorization.
if (request.getMethod().equals(HttpMethods.OPTIONS)) {
return true;
}
HandlerMethod method = (HandlerMethod) handler;
boolean isAuthRequired = false;
ApiOperation apiOp = AnnotationUtils.findAnnotation(method.getMethod(), ApiOperation.class);
if (apiOp != null) {
for (Authorization auth : apiOp.authorizations()) {
if (auth.value().equals(authName)) {
isAuthRequired = true;
break;
}
}
}
if (!isAuthRequired) {
return true;
}
String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
log.warning("No bearer token found in request");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
String token = authorizationHeader.substring("Bearer".length()).trim();
Userinfoplus userInfo;
try {
userInfo = userInfoService.getUserInfo(token);
} catch (HttpResponseException e) {
log.log(Level.WARNING, "{0} response getting user info for bearer token {1}: {2}", new Object[] { e.getStatusCode(), token, e.getStatusMessage() });
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
// TODO: check Google group membership to ensure user is in registered user group
String userEmail = userInfo.getEmail();
WorkbenchConfig workbenchConfig = workbenchConfigProvider.get();
if (workbenchConfig.auth.serviceAccountApiUsers.contains(userEmail)) {
// Whitelisted service accounts are able to make API calls, too.
// TODO: stop treating service accounts as normal users, have a separate table for them,
// administrators.
User user = userDao.findUserByEmail(userEmail);
if (user == null) {
user = userService.createServiceAccountUser(userEmail);
}
SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(user, userInfo, token, UserType.SERVICE_ACCOUNT));
log.log(Level.INFO, "{0} service account in use", userInfo.getEmail());
return true;
}
String gsuiteDomainSuffix = "@" + workbenchConfig.googleDirectoryService.gSuiteDomain;
if (!userEmail.endsWith(gsuiteDomainSuffix)) {
try {
// If the email isn't in our GSuite domain, try FireCloud; we could be dealing with a
// pet service account. In both AofU and FireCloud, the pet SA is treated as if it were
// the user it was created for.
userEmail = fireCloudService.getMe().getUserInfo().getUserEmail();
} catch (ApiException e) {
log.log(Level.INFO, "FireCloud lookup for {0} failed, can't access the workbench: {1}", new Object[] { userInfo.getEmail(), e.getMessage() });
response.sendError(e.getCode());
return false;
}
if (!userEmail.endsWith(gsuiteDomainSuffix)) {
log.log(Level.INFO, "User {0} isn't in domain {1}, can't access the workbench", new Object[] { userEmail, gsuiteDomainSuffix });
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return false;
}
}
User user = userDao.findUserByEmail(userEmail);
if (user == null) {
// TODO(danrodney): start populating contact email in Google account, use it here.
user = userService.createUser(userInfo.getGivenName(), userInfo.getFamilyName(), userInfo.getEmail(), null);
} else {
if (user.getDisabled()) {
throw new ForbiddenException(ExceptionUtils.errorResponse(ErrorCode.USER_DISABLED, "This user account has been disabled."));
}
}
SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(user, userInfo, token, UserType.RESEARCHER));
// TODO: setup this in the context, get rid of log statement
log.log(Level.INFO, "{0} logged in", userInfo.getEmail());
if (!hasRequiredAuthority(method, user)) {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return false;
}
return true;
}
use of org.pmiops.workbench.exceptions.ForbiddenException in project workbench by all-of-us.
the class CohortMaterializationService method materializeCohort.
public MaterializeCohortResponse materializeCohort(@Nullable CohortReview cohortReview, SearchRequest searchRequest, MaterializeCohortRequest request) {
long offset = 0L;
FieldSet fieldSet = request.getFieldSet();
List<CohortStatus> statusFilter = request.getStatusFilter();
String paginationToken = request.getPageToken();
int pageSize = request.getPageSize();
// TODO: add CDR version ID here
Object[] paginationParameters = new Object[] { searchRequest, statusFilter };
if (paginationToken != null) {
PaginationToken token = PaginationToken.fromBase64(paginationToken);
if (token.matchesParameters(paginationParameters)) {
offset = token.getOffset();
} else {
throw new BadRequestException(String.format("Use of pagination token %s with new parameter values", paginationToken));
}
}
int limit = pageSize + 1;
if (statusFilter == null) {
statusFilter = ALL_STATUSES;
}
ParticipantCriteria criteria;
MaterializeCohortResponse response = new MaterializeCohortResponse();
if (statusFilter.contains(CohortStatus.NOT_REVIEWED)) {
Set<Long> participantIdsToExclude;
if (statusFilter.size() < CohortStatus.values().length) {
// Find the participant IDs that have statuses which *aren't* in the filter.
Set<CohortStatus> statusesToExclude = Sets.difference(ImmutableSet.copyOf(CohortStatus.values()), ImmutableSet.copyOf(statusFilter));
participantIdsToExclude = getParticipantIdsWithStatus(cohortReview, ImmutableList.copyOf(statusesToExclude));
} else {
participantIdsToExclude = ImmutableSet.of();
}
criteria = new ParticipantCriteria(searchRequest, participantIdsToExclude);
} else {
Set<Long> participantIds = getParticipantIdsWithStatus(cohortReview, statusFilter);
if (participantIds.isEmpty()) {
// return an empty response.
return response;
}
criteria = new ParticipantCriteria(participantIds);
}
TableQueryAndConfig tableQueryAndConfig = getTableQueryAndConfig(fieldSet);
QueryJobConfiguration jobConfiguration = fieldSetQueryBuilder.buildQuery(criteria, tableQueryAndConfig, limit, offset);
QueryResult result;
try {
result = bigQueryService.executeQuery(bigQueryService.filterBigQueryConfig(jobConfiguration));
} catch (BigQueryException e) {
if (e.getCode() == HttpServletResponse.SC_SERVICE_UNAVAILABLE) {
throw new ServerUnavailableException("BigQuery was temporarily unavailable, try again later", e);
} else if (e.getCode() == HttpServletResponse.SC_FORBIDDEN) {
throw new ForbiddenException("Access to the CDR is denied", e);
} else {
throw new ServerErrorException(String.format("An unexpected error occurred materializing the cohort with " + "query = (%s), params = (%s)", jobConfiguration.getQuery(), jobConfiguration.getNamedParameters()), e);
}
}
Map<String, Integer> rm = bigQueryService.getResultMapper(result);
int numResults = 0;
boolean hasMoreResults = false;
ArrayList<Object> results = new ArrayList<>();
for (List<FieldValue> row : result.iterateAll()) {
if (numResults == pageSize) {
hasMoreResults = true;
break;
}
Map<String, Object> resultMap = fieldSetQueryBuilder.extractResults(tableQueryAndConfig, row);
results.add(resultMap);
numResults++;
}
response.setResults(results);
if (hasMoreResults) {
// TODO: consider pagination based on cursor / values rather than offset
PaginationToken token = PaginationToken.of(offset + pageSize, paginationParameters);
response.setNextPageToken(token.toBase64());
}
return response;
}
Aggregations