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