001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.rest.guards; 014 015import java.text.*; 016import java.util.*; 017import java.util.stream.*; 018 019import org.apache.juneau.rest.*; 020 021/** 022 * {@link RestGuard} that uses role expressions to determine whether an authenticated user has access to a class or method. 023 * 024 * <p> 025 * The role expression supports the following constructs: 026 * <ul> 027 * <li><js>"foo"</js> - Single arguments. 028 * <li><js>"foo,bar,baz"</js> - Multiple OR'ed arguments. 029 * <li><js>"foo | bar | bqz"</js> - Multiple OR'ed arguments, pipe syntax. 030 * <li><js>"foo || bar || bqz"</js> - Multiple OR'ed arguments, Java-OR syntax. 031 * <li><js>"fo*"</js> - Patterns including <js>'*'</js> and <js>'?'</js>. 032 * <li><js>"fo* & *oo"</js> - Multiple AND'ed arguments, ampersand syntax. 033 * <li><js>"fo* && *oo"</js> - Multiple AND'ed arguments, Java-AND syntax. 034 * <li><js>"fo* || (*oo || bar)"</js> - Parenthesis. 035 * </ul> 036 * 037 * <ul class='notes'> 038 * <li>AND operations take precedence over OR operations (as expected). 039 * <li>Whitespace is ignored. 040 * <li><jk>null</jk> or empty expressions always match as <jk>false</jk>. 041 * </ul> 042 */ 043public class RoleBasedRestGuard extends RestGuard { 044 045 private final Set<String> roles; 046 private final RoleMatcher roleMatcher; 047 048 /** 049 * Constructor. 050 * 051 * @param declaredRoles 052 * List of possible declared roles. 053 * <br>If <jk>null</jk>, we find the roles in the expression itself. 054 * <br>This is only needed if you're using pattern matching in the expression. 055 * @param roleExpression 056 * The role expression. 057 * <br>If <jk>null</jk> or empty/blanks, the this guard will never pass. 058 * @throws ParseException Invalid role expression syntax. 059 */ 060 public RoleBasedRestGuard(Set<String> declaredRoles, String roleExpression) throws ParseException { 061 roleMatcher = new RoleMatcher(roleExpression); 062 roles = new TreeSet<>(declaredRoles == null ? roleMatcher.getRolesInExpression() : declaredRoles); 063 } 064 065 @Override 066 public boolean isRequestAllowed(RestRequest req) { 067 Set<String> userRoles = roles.stream().filter(x -> req.isUserInRole(x)).collect(Collectors.toSet()); 068 return roleMatcher.matches(userRoles); 069 } 070}