All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mcollovati.vertx.vaadin.connect.auth.AccessAnnotationChecker Maven / Gradle / Ivy

The newest version!
/*
 * The MIT License
 * Copyright © 2016-2020 Marco Collovati ([email protected])
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.github.mcollovati.vertx.vaadin.connect.auth;

import java.io.Serializable;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.Principal;
import java.util.function.Function;
import jakarta.annotation.security.DenyAll;
import jakarta.annotation.security.PermitAll;
import jakarta.annotation.security.RolesAllowed;
import jakarta.servlet.http.HttpServletRequest;

import com.vaadin.flow.server.VaadinRequest;
import com.vaadin.flow.server.auth.AnonymousAllowed;

/**
 * Checks if a given user has access to a given method.
 * 

* Check is performed as follows when called for a method: *

    *
  1. A security annotation (see below) is searched for on that particular * method.
  2. *
  3. If a security annotation was not found on the method, checks the class * the method is declared in.
  4. *
  5. If no security annotation was found, deny access by default
  6. *
*

* The security annotations checked and their meaning are: *

    *
  • {@link AnonymousAllowed} - allows access to any logged on or not logged * in user. Public access.
  • *
  • {@link PermitAll} - allows access to any logged in user but denies access * to anonymous users.
  • *
  • {@link RolesAllowed} - allows access there is a logged in user that has * any of the roles mentioned in the annotation
  • *
  • {@link DenyAll} - denies access.
  • *
* *

* Source adapted from Vaadin Flow (https://github.com/vaadin/flow) fusion-endpoints module, * to get rid of servlet APIs. *

* @param request type */ public abstract class AccessAnnotationChecker implements Serializable { /** * Checks if the user defined by the current active servlet request (using * {@link VaadinRequest#getUserPrincipal()} and * {@link VaadinRequest#isUserInRole(String)} has access to the given * method. * * @param method the method to check access to * @return {@code true} if the user has access to the given method, * {@code false} otherwise */ public boolean hasAccess(Method method) { VaadinRequest request = VaadinRequest.getCurrent(); if (request == null) { throw new IllegalStateException( "No request is available. This method can only be used with an active VaadinRequest"); } return hasAccess(method, request); } /** * Checks if the user defined by the current active servlet request (using * {@link VaadinRequest#getUserPrincipal()} and * {@link VaadinRequest#isUserInRole(String)} has access to the given * class. * * @param cls the class to check access to * @return {@code true} if the user has access to the given method, * {@code false} otherwise */ public boolean hasAccess(Class cls) { VaadinRequest request = VaadinRequest.getCurrent(); if (request == null) { throw new IllegalStateException( "No request is available. This method can only be used with an active VaadinServletRequest"); } return hasAccess(cls, request); } /** * Checks if the user defined by the request (using * {@link VaadinRequest#getUserPrincipal()} and * {@link VaadinRequest#isUserInRole(String)} has access to the given * method. * * @param method the method to check access to * @param request the http request to use for user information * @return {@code true} if the user has access to the given method, * {@code false} otherwise */ public boolean hasAccess(Method method, UserAwareRequest request) { if (request == null) { throw new IllegalArgumentException("The request cannot be null"); } return hasAccess(method, request.getUserPrincipal(), request::isUserInRole); } /** * Checks if the user defined by the request (using * {@link UserAwareRequest#getUserPrincipal()} and * {@link UserAwareRequest#isUserInRole(String)} has access to the given * class. * * @param cls the class to check access to * @param request the http request to use for user information * @return {@code true} if the user has access to the given method, * {@code false} otherwise */ public boolean hasAccess(Class cls, UserAwareRequest request) { if (request == null) { throw new IllegalArgumentException("The request cannot be null"); } return hasAccess(cls, request.getUserPrincipal(), request::isUserInRole); } /** * Checks if the user defined by the request (adapting request to {@link UserAwareRequest} * and using {@link UserAwareRequest#getUserPrincipal()} and * {@link UserAwareRequest#isUserInRole(String)} has access to the given * method. * * @param method the method to check access to * @param request the http request to use for user information * @return {@code true} if the user has access to the given method, * {@code false} otherwise */ public boolean hasAccess(Method method, REQUEST request) { if (request == null) { throw new IllegalArgumentException("The request cannot be null"); } return hasAccess(method, adaptRequest(request)); } /** * Checks if the user defined by the request (adapting request to {@link UserAwareRequest} * and using {@link HttpServletRequest#getUserPrincipal()} and * {@link HttpServletRequest#isUserInRole(String)} has access to the given * class. * * @param cls the class to check access to * @param request the http request to use for user information * @return {@code true} if the user has access to the given method, * {@code false} otherwise */ public boolean hasAccess(Class cls, REQUEST request) { if (request == null) { throw new IllegalArgumentException("The request cannot be null"); } return hasAccess(cls, adaptRequest(request)); } /** * Checks if the user defined by the request (using * {@link VaadinRequest#getUserPrincipal()} and * {@link VaadinRequest#isUserInRole(String)} has access to the given * method. * * @param method the method to check access to * @param request the http request to use for user information * @return {@code true} if the user has access to the given method, * {@code false} otherwise */ public boolean hasAccess(Method method, VaadinRequest request) { if (request == null) { throw new IllegalArgumentException("The request cannot be null"); } return hasAccess(method, request.getUserPrincipal(), request::isUserInRole); } /** * Checks if the user defined by the request (using * {@link VaadinRequest#getUserPrincipal()} and * {@link VaadinRequest#isUserInRole(String)} has access to the given * class. * * @param cls the class to check access to * @param request the http request to use for user information * @return {@code true} if the user has access to the given method, * {@code false} otherwise */ public boolean hasAccess(Class cls, VaadinRequest request) { if (request == null) { throw new IllegalArgumentException("The request cannot be null"); } return hasAccess(cls, request.getUserPrincipal(), request::isUserInRole); } protected abstract UserAwareRequest adaptRequest(REQUEST request); /** * Checks if the user defined by the given {@link Principal} and role * checker has access to the given method. * * @param method the method to check access to * @param principal the principal of the user * @param roleChecker a function that can answer if a user has a given role * @return {@code true} if the user has access to the given method, * {@code false} otherwise */ public boolean hasAccess(Method method, Principal principal, Function roleChecker) { return hasAccess(getSecurityTarget(method), principal, roleChecker); } /** * Checks if the user defined by the given {@link Principal} and role * checker has access to the given class. * * @param cls the class to check access to * @param principal the principal of the user * @param roleChecker a function that can answer if a user has a given role * @return {@code true} if the user has access to the given method, * {@code false} otherwise */ public boolean hasAccess(Class cls, Principal principal, Function roleChecker) { return hasAccess(getSecurityTarget(cls), principal, roleChecker); } /** * Gets the method or class to check for security restrictions. * * @param method the method to look up * @return the entity that is responsible for security settings for the * method passed * @throws IllegalArgumentException if the method is not public */ public AnnotatedElement getSecurityTarget(Method method) { if (!Modifier.isPublic(method.getModifiers())) { throw new IllegalArgumentException( String.format("The method '%s' is not public hence cannot have a security target", method)); } return hasSecurityAnnotation(method) ? method : method.getDeclaringClass(); } /** * Gets the class to check for security restrictions. * * @param cls the class to check * @return the entity that is responsible for security settings for the * method passed * @throws IllegalArgumentException if the method is not public */ public AnnotatedElement getSecurityTarget(Class cls) { return cls; } private boolean hasAccess( AnnotatedElement annotatedClassOrMethod, Principal principal, Function roleChecker) { if (annotatedClassOrMethod.isAnnotationPresent(DenyAll.class)) { return false; } if (annotatedClassOrMethod.isAnnotationPresent(AnonymousAllowed.class)) { return true; } if (principal == null) { return false; } RolesAllowed rolesAllowed = annotatedClassOrMethod.getAnnotation(RolesAllowed.class); if (rolesAllowed == null) { return annotatedClassOrMethod.isAnnotationPresent(PermitAll.class); } else { return roleAllowed(rolesAllowed, roleChecker); } } private boolean roleAllowed(RolesAllowed rolesAllowed, Function roleChecker) { for (String role : rolesAllowed.value()) { if (roleChecker.apply(role)) { return true; } } return false; } private boolean hasSecurityAnnotation(Method method) { return method.isAnnotationPresent(AnonymousAllowed.class) || method.isAnnotationPresent(PermitAll.class) || method.isAnnotationPresent(DenyAll.class) || method.isAnnotationPresent(RolesAllowed.class); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy