Delsh
Delsh

Reputation: 67

Implement voter that grabs path variable from url

I am trying to implement this: https://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/el-access.html#el-access-web-path-variables but the teacher is explicitly telling us to use spring-security 4.0.4 (because of conflicting transitive dependencies with spring framework 4.2.5) and I've searched extensively on how to create an AccessDecisionVoter that can grab a path variable but so far this is the only thing that i came into what is the actual type of object parameter in vote method of spring security access decision voter which i don't know if it's indeed the best way to do it since this answer was intended for Spring Security 3.1.

Upvotes: 0

Views: 136

Answers (1)

Delsh
Delsh

Reputation: 67

Solved it by coding my own AccessDecisionVoter:

public class CourseVoter implements AccessDecisionVoter<FilterInvocation> {

    @Autowired
    private CourseService courseService;

    @Autowired
    private AuthFacade authFacade;

    @Autowired
    private FileService fileService;

    static final Pattern GET_FILE_PATTERN = Pattern.compile("/files/(\\d+)");
    static final Pattern UPLOAD_FILE_PATTERN = Pattern.compile("/course/(\\d+)/files");
    static final Pattern UPLOAD_ANNOUNCEMENT_PATTERN = Pattern.compile("/course/(\\d+)/announcements");
    static final Pattern GET_COURSE_PATTERN = Pattern.compile("/course/(\\d+)");

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return false;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return clazz.isAssignableFrom(FilterInvocation.class);
    }

    @Override
    public int vote(Authentication authentication, FilterInvocation fi, Collection<ConfigAttribute> attributes) {
        final String url = fi.getRequestUrl();
        final String method = fi.getHttpRequest().getMethod();
        Matcher getCourseMatcher = GET_COURSE_PATTERN.matcher(url);
        Matcher getFileMatcher = GET_FILE_PATTERN.matcher(url);
        Matcher uploadFileMatcher = UPLOAD_FILE_PATTERN.matcher(url);
        Matcher uploadAnnouncementMatcher = UPLOAD_ANNOUNCEMENT_PATTERN.matcher(url);
        if(getFileMatcher.find()) return voteFileAccess(authentication, getMappingValue(getFileMatcher));
        if(method.equals("POST") && uploadAnnouncementMatcher.find()) return voteCoursePrivileges(authentication, getMappingValue(uploadAnnouncementMatcher));
        if(method.equals("POST") && uploadFileMatcher.find()) return voteCoursePrivileges(authentication, getMappingValue(uploadFileMatcher));
        if(getCourseMatcher.find()) return voteCourseAccess(authentication, getMappingValue(getCourseMatcher));
        return ACCESS_ABSTAIN;
    }

    private Long getMappingValue(Matcher m) {
        return Long.valueOf(m.group(1));
    }

    private boolean isAdminOrAnonymous(Authentication authentication) {
        if(authentication instanceof AnonymousAuthenticationToken) return true;
        User user = authFacade.getCurrentUser();
        return user.isAdmin();
    }

    private int voteFileAccess(Authentication authentication, Long fileId) {
        if(isAdminOrAnonymous(authentication)) return ACCESS_DENIED;
        return fileService.hasAccess(fileId, authFacade.getCurrentUserId()) ? ACCESS_GRANTED : ACCESS_DENIED;
    }

    private int voteCourseAccess(Authentication authentication, Long courseId) {
        if(isAdminOrAnonymous(authentication)) return ACCESS_DENIED;
        return courseService.belongs(authFacade.getCurrentUserId(), courseId) ? ACCESS_GRANTED : ACCESS_DENIED;
    }

    private int voteCoursePrivileges(Authentication authentication, Long courseId) {
        if(isAdminOrAnonymous(authentication)) return ACCESS_DENIED;
        return courseService.isPrivileged(authFacade.getCurrentUserId(), courseId) ? ACCESS_GRANTED : ACCESS_DENIED;
    }
}

Upvotes: 1

Related Questions