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

org.casbin.spring.boot.autoconfigure.CasbinAutoConfiguration Maven / Gradle / Ivy

The newest version!
package org.casbin.spring.boot.autoconfigure;

import org.casbin.adapter.JDBCAdapter;
import org.casbin.annotation.CasbinDataSource;
import org.casbin.exception.CasbinAdapterException;
import org.casbin.exception.CasbinModelConfigNotFoundException;
import org.casbin.jcasbin.main.DistributedEnforcer;
import org.casbin.jcasbin.main.Enforcer;
import org.casbin.jcasbin.main.SyncedEnforcer;
import org.casbin.jcasbin.model.Model;
import org.casbin.jcasbin.persist.Adapter;
import org.casbin.jcasbin.persist.file_adapter.FileAdapter;
import org.casbin.spring.boot.autoconfigure.properties.CasbinDataSourceInitializationMode;
import org.casbin.spring.boot.autoconfigure.properties.CasbinExceptionProperties;
import org.casbin.spring.boot.autoconfigure.properties.CasbinProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.MetaDataAccessException;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.DatabaseMetaData;

/**
 * @author fangzhengjin
 * @version V1.0
 * @title CasbinAutoConfiguration
 * @package org.casbin.spring.boot.autoconfigure
 * @description
 * @date 2019-4-05 13:53
 */

@Configuration
@EnableConfigurationProperties({CasbinProperties.class, CasbinExceptionProperties.class, DataSourceProperties.class})
@AutoConfigureAfter({JdbcTemplateAutoConfiguration.class})
@ConditionalOnExpression("${casbin.enable-casbin:true}")
public class CasbinAutoConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(CasbinAutoConfiguration.class);

    /**
     * Automatic configuration file storage adapter
     *
     * @param properties properties
     * @return autoConfigFileAdapter
     */
    @Bean
    @ConditionalOnProperty(name = "casbin.store-type", havingValue = "file")
    @ConditionalOnMissingBean
    public Adapter autoConfigFileAdapter(CasbinProperties properties) {
        // if the file storage is chosen and the policy file location is set correctly, then create a file adapter
        if (StringUtils.hasText(properties.getPolicy())) {
            try (InputStream policyInputStream = properties.getPolicyInputStream()) {
                return new FileAdapter(policyInputStream);
            } catch (Exception ignored) {
            }
        }
        throw new CasbinAdapterException("Cannot create file adapter, because policy file is not set");
    }

    /**
     * Automatic configuration of JDBC adapter
     *
     * @param casbinDataSource     casbinDataSource
     * @param jdbcTemplate         jdbcTemplate
     * @param properties           properties
     * @param exceptionProperties  exceptionProperties
     * @param dataSourceProperties dataSourceProperties
     * @return Adapter
     * @throws Exception exception
     */
    @Bean
    @ConditionalOnProperty(name = "casbin.store-type", havingValue = "jdbc", matchIfMissing = true)
    @ConditionalOnBean(JdbcTemplate.class)
    @ConditionalOnMissingBean
    public Adapter autoConfigJdbcAdapter(
            @CasbinDataSource ObjectProvider casbinDataSource,
            JdbcTemplate jdbcTemplate,
            CasbinProperties properties,
            CasbinExceptionProperties exceptionProperties,
            DataSourceProperties dataSourceProperties
    ) throws Exception {
        JdbcTemplate jdbcTemplateToUse = getJdbcTemplate(jdbcTemplate, casbinDataSource);
        if (jdbcTemplateToUse == null || jdbcTemplateToUse.getDataSource() == null) {
            throw new CasbinAdapterException("Cannot create jdbc adapter, because jdbc template is not set");
        }
        String databaseName = getDatabaseName(jdbcTemplateToUse.getDataSource());
        CasbinDataSourceInitializationMode initializeSchema = properties.getInitializeSchema();
        boolean autoCreateTable = initializeSchema == CasbinDataSourceInitializationMode.CREATE;
        String tableName = properties.getTableName();
        logger.info("Casbin current use database product: {}", databaseName);
        // datasource properties are configed
        if (dataSourceProperties.getUrl() != null) {
            return new JDBCAdapter(dataSourceProperties.determineDriverClassName(), dataSourceProperties.getUrl(),
                    dataSourceProperties.getUsername(), dataSourceProperties.getPassword(),
                    exceptionProperties.isRemovePolicyFailed(), tableName, autoCreateTable);
        }
        // when datasource properties are not configed, use the default datasource in jdbcTemplate
        else {
            return new JDBCAdapter(jdbcTemplateToUse.getDataSource(), exceptionProperties.isRemovePolicyFailed(), tableName, autoCreateTable);
        }
    }

    /**
     * Automatic configuration of the enforcer
     *
     * @param properties properties
     * @param adapter    adapter
     * @return Enforcer
     */
    @Bean
    @ConditionalOnMissingBean
    public Enforcer enforcer(CasbinProperties properties, Adapter adapter) {
        Model model = new Model();
        try {
            String modelContext = properties.getModelContext();
            model.loadModelFromText(modelContext);
        } catch (CasbinModelConfigNotFoundException e) {
            // if the local model file address is not set or the file is not found in the default path, the default rbac configuration is used
            if (!properties.isUseDefaultModelIfModelNotSetting()) {
                throw e;
            }
            logger.info("Can't found model config file, use default model config");
            // request definition
            model.addDef("r", "r", "sub, obj, act");
            // policy definition
            model.addDef("p", "p", "sub, obj, act");
            // role definition
            model.addDef("g", "g", "_, _");
            // policy effect
            model.addDef("e", "e", "some(where (p.eft == allow))");
            // matchers
            model.addDef("m", "m", "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act");
        }
        Enforcer enforcer;
        if (properties.isUseDistributedEnforcer()) {
            enforcer = new DistributedEnforcer(model, adapter);
            logger.info("Casbin use DistributedEnforcer");
        } else if (properties.isUseSyncedEnforcer()) {
            enforcer = new SyncedEnforcer(model, adapter);
            logger.info("Casbin use SyncedEnforcer");
        } else {
            enforcer = new Enforcer(model, adapter);
        }
        enforcer.enableAutoSave(properties.isAutoSave());
        return enforcer;
    }

    /**
     * Get the current database type
     *
     * @param dataSource dataSource
     * @return String
     */
    private static String getDatabaseName(DataSource dataSource) {
        try {
            String productName = JdbcUtils.
                    commonDatabaseName(JdbcUtils.extractDatabaseMetaData(
                            dataSource, DatabaseMetaData::getDatabaseProductName
                    ));
            DatabaseDriver databaseDriver = DatabaseDriver.fromProductName(productName);
            if (databaseDriver == DatabaseDriver.UNKNOWN) {
                throw new IllegalStateException("Unable to detect database type");
            }
            return databaseDriver.getId();
        } catch (MetaDataAccessException ex) {
            throw new IllegalStateException("Unable to detect database type", ex);
        }
    }

    /**
     * Get the JdbcTemplate
     *
     * @param jdbcTemplate jdbcTemplate
     * @param dataSource   dataSource
     * @return JdbcTemplate
     */
    private static JdbcTemplate getJdbcTemplate(JdbcTemplate jdbcTemplate, ObjectProvider dataSource) {
        DataSource dataSourceIfAvailable = dataSource.getIfAvailable();
        if (dataSourceIfAvailable != null) {
            logger.info("Discover the custom Casbin data source.");
            return new JdbcTemplate(dataSourceIfAvailable);
        } else {
            logger.info("Casbin is using the data source managed by Spring.");
            return jdbcTemplate;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy