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

yakworks.security.gorm.AsyncSecureService.groovy Maven / Gradle / Ivy

The newest version!
/*
* Copyright 2019 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License")
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
package yakworks.security.gorm

import java.util.function.Consumer
import java.util.function.Supplier

import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j

import org.grails.datastore.mapping.core.Datastore
import org.springframework.security.core.Authentication
import org.springframework.security.core.context.SecurityContextHolder

import gorm.tools.async.AsyncService

/**
 * AsyncService that copies the authentication to context while in the new thread
 * see https://github.com/spring-projects/spring-security/issues/6856
 * MODE_INHERITABLETHREADLOCAL does not work with our CompletbaleFutures,
 * It also makes it insecure as the prior user is used during auth check during rest
 */
@Slf4j
@CompileStatic
class AsyncSecureService extends AsyncService  {

    static Authentication authentication(){
        SecurityContextHolder.context.authentication
    }

    static void setAuth(Authentication auth){
        SecurityContextHolder.context.authentication = auth
    }

    @Override
    public  Supplier wrapSupplier(Supplier sup) {
        def authentication = authentication()
        return new Supplier() {
            @Override
            T get() {
                setAuth(authentication)
                return sup.get()
            }
        }
    }

    @Override
    public  Supplier wrapSupplierTrx(Datastore ds, Supplier sup) {
        wrapSupplier(super.wrapSupplierTrx(ds, sup))
    }

    @Override
    public  Supplier wrapSupplierSession(Datastore ds, Supplier sup) {
        wrapSupplier(super.wrapSupplierSession(ds, sup))
    }

    /**
     * wrap the consumer, can be overriden in super which is is done in AsyncSecureService
     */
    @Override
    public  Consumer wrapConsumer(Consumer consumer) {
        def authentication = authentication()
        return new Consumer() {
            @Override
            void accept(T item) {
                setAuth(authentication)
                consumer.accept(item)
            }
        }
    }

    @Override
    public  Consumer wrapConsumerTrx(Datastore ds, Consumer consumer) {
        wrapConsumer(super.wrapConsumerTrx(ds, consumer))
    }

    @Override
    public  Consumer wrapConsumerSession(Datastore ds, Consumer consumer) {
        wrapConsumer(super.wrapConsumerSession(ds, consumer))
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy