/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.nifi.registry.security.authorization.database;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.nifi.registry.security.authorization.AbstractConfigurableAccessPolicyProvider;
import org.apache.nifi.registry.security.authorization.AccessPolicy;
import org.apache.nifi.registry.security.authorization.AccessPolicyProviderInitializationContext;
import org.apache.nifi.registry.security.authorization.AuthorizerConfigurationContext;
import org.apache.nifi.registry.security.authorization.Group;
import org.apache.nifi.registry.security.authorization.RequestAction;
import org.apache.nifi.registry.security.authorization.User;
import org.apache.nifi.registry.security.authorization.annotation.AuthorizerContext;
import org.apache.nifi.registry.security.authorization.database.entity.DatabaseAccessPolicy;
import org.apache.nifi.registry.security.authorization.database.mapper.DatabaseAccessPolicyRowMapper;
import org.apache.nifi.registry.security.authorization.exception.AuthorizationAccessException;
import org.apache.nifi.registry.security.authorization.exception.UninheritableAuthorizationsException;
import org.apache.nifi.registry.security.authorization.util.AccessPolicyProviderUtils;
import org.apache.nifi.registry.security.authorization.util.InitialPolicies;
import org.apache.nifi.registry.security.authorization.util.ResourceAndAction;
import org.apache.nifi.registry.security.exception.SecurityProviderCreationException;
import org.apache.nifi.registry.security.exception.SecurityProviderDestructionException;
import org.apache.nifi.registry.security.identity.IdentityMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.util.CollectionUtils;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Implementation of {@link org.apache.nifi.registry.security.authorization.ConfigurableAccessPolicyProvider} backed by a relational database.
 */
public class DatabaseAccessPolicyProvider extends AbstractConfigurableAccessPolicyProvider {

    private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseAccessPolicyProvider.class);

    private DataSource dataSource;
    private IdentityMapper identityMapper;

    private JdbcTemplate jdbcTemplate;

    @AuthorizerContext
    public void setDataSource(final DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @AuthorizerContext
    public void setIdentityMapper(final IdentityMapper identityMapper) {
        this.identityMapper = identityMapper;
    }

    @Override
    protected void doInitialize(AccessPolicyProviderInitializationContext initializationContext) throws SecurityProviderCreationException {
        super.doInitialize(initializationContext);
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    public void doOnConfigured(final AuthorizerConfigurationContext configurationContext) throws SecurityProviderCreationException {
        final String initialAdminIdentity = AccessPolicyProviderUtils.getInitialAdminIdentity(configurationContext, identityMapper);
        final Set<String> nifiIdentities = AccessPolicyProviderUtils.getNiFiIdentities(configurationContext, identityMapper);
        final String nifiGroupName = AccessPolicyProviderUtils.getNiFiGroupName(configurationContext, identityMapper);

        if (!StringUtils.isBlank(initialAdminIdentity)) {
            LOGGER.info("Populating authorizations for Initial Admin: '" + initialAdminIdentity + "'");
            populateInitialAdmin(initialAdminIdentity);
        }

        if (!CollectionUtils.isEmpty(nifiIdentities)) {
            LOGGER.info("Populating authorizations for NiFi identities: [{}]", StringUtils.join(nifiIdentities, ";"));
            populateNiFiIdentities(nifiIdentities);
        }

        if (!StringUtils.isBlank(nifiGroupName)) {
            LOGGER.info("Populating authorizations for NiFi Group: '" + nifiGroupName + "'");
            populateNiFiGroup(nifiGroupName);
        }
    }

    private void populateInitialAdmin(final String initialAdminIdentity) {
        final User initialAdmin = getUserGroupProvider().getUserByIdentity(initialAdminIdentity);
        if (initialAdmin == null) {
            throw new SecurityProviderCreationException("Unable to locate initial admin '" + initialAdminIdentity + "' to seed policies");
        }

        for (final ResourceAndAction resourceAction : InitialPolicies.ADMIN_POLICIES) {
            populateInitialPolicy(initialAdmin, resourceAction);
        }
    }

    private void populateNiFiIdentities(final Set<String> nifiIdentities) {
        for (final String nifiIdentity : nifiIdentities) {
            final User nifiUser = getUserGroupProvider().getUserByIdentity(nifiIdentity);
            if (nifiUser == null) {
                throw new SecurityProviderCreationException("Unable to locate NiFi identity '" + nifiIdentity + "' to seed policies.");
            }

            for (final ResourceAndAction resourceAction : InitialPolicies.NIFI_POLICIES) {
                populateInitialPolicy(nifiUser, resourceAction);
            }
        }
    }

    private void populateNiFiGroup(final String nifiGroupName) {
        final Group nifiGroup = AccessPolicyProviderUtils.getGroup(nifiGroupName, getUserGroupProvider());

        for (final ResourceAndAction resourceAction : InitialPolicies.NIFI_POLICIES) {
            populateInitialPolicy(nifiGroup, resourceAction);
        }
    }

    @Override
    public void preDestruction() throws SecurityProviderDestructionException {

    }

    // ---- fingerprinting methods

    @Override
    public String getFingerprint() throws AuthorizationAccessException {
        throw new UnsupportedOperationException("Fingerprinting is not supported by this provider");
    }

    @Override
    public void inheritFingerprint(String fingerprint) throws AuthorizationAccessException {
        throw new UnsupportedOperationException("Fingerprinting is not supported by this provider");
    }

    @Override
    public void checkInheritability(String proposedFingerprint) throws AuthorizationAccessException, UninheritableAuthorizationsException {
        throw new UnsupportedOperationException("Fingerprinting is not supported by this provider");
    }

    // ---- access policy methods

    @Override
    public AccessPolicy addAccessPolicy(final AccessPolicy accessPolicy) throws AuthorizationAccessException {
        Validate.notNull(accessPolicy);

        // insert to the policy table
        final String policySql = "INSERT INTO APP_POLICY(IDENTIFIER, RESOURCE, ACTION) VALUES (?, ?, ?)";
        jdbcTemplate.update(policySql, accessPolicy.getIdentifier(), accessPolicy.getResource(), accessPolicy.getAction().toString());

        // insert to the policy-user and policy groups table
        createPolicyUserAndGroups(accessPolicy);

        return accessPolicy;
    }

    @Override
    public AccessPolicy updateAccessPolicy(final AccessPolicy accessPolicy) throws AuthorizationAccessException {
        Validate.notNull(accessPolicy);

        // determine if policy exists
        final DatabaseAccessPolicy existingPolicy = getDatabaseAcessPolicy(accessPolicy.getIdentifier());
        if (existingPolicy == null) {
            return null;
        }

        // delete any policy-user associations
        final String deletePolicyUsersSql = "DELETE FROM APP_POLICY_USER WHERE POLICY_IDENTIFIER = ?";
        jdbcTemplate.update(deletePolicyUsersSql, accessPolicy.getIdentifier());

        // delete any policy-group associations
        final String deletePolicyGroupsSql = "DELETE FROM APP_POLICY_GROUP WHERE POLICY_IDENTIFIER = ?";
        jdbcTemplate.update(deletePolicyGroupsSql, accessPolicy.getIdentifier());


        // re-create the associations
        createPolicyUserAndGroups(accessPolicy);

        return accessPolicy;
    }

    @Override
    public Set<AccessPolicy> getAccessPolicies() throws AuthorizationAccessException {
        // retrieve all the policies
        final String sql = "SELECT * FROM APP_POLICY";
        final List<DatabaseAccessPolicy> databasePolicies = jdbcTemplate.query(sql, new DatabaseAccessPolicyRowMapper());

        // retrieve all users in policies, mapped by policy id
        final Map<String,Set<String>> policyToUsers = new HashMap<>();
        jdbcTemplate.query("SELECT * FROM APP_POLICY_USER", (rs) -> {
            final String policyIdentifier = rs.getString("POLICY_IDENTIFIER");
            final String userIdentifier = rs.getString("USER_IDENTIFIER");

            final Set<String> userIdentifiers = policyToUsers.computeIfAbsent(policyIdentifier, (k) -> new HashSet<>());
            userIdentifiers.add(userIdentifier);
        });

        // retrieve all groups in policies, mapped by policy id
        final Map<String,Set<String>> policyToGroups = new HashMap<>();
        jdbcTemplate.query("SELECT * FROM APP_POLICY_GROUP", (rs) -> {
            final String policyIdentifier = rs.getString("POLICY_IDENTIFIER");
            final String groupIdentifier = rs.getString("GROUP_IDENTIFIER");

            final Set<String> groupIdentifiers = policyToGroups.computeIfAbsent(policyIdentifier, (k) -> new HashSet<>());
            groupIdentifiers.add(groupIdentifier);
        });

        // convert the database model to the api model
        final Set<AccessPolicy> policies = new HashSet<>();

        databasePolicies.forEach(p -> {
            final Set<String> userIdentifiers = policyToUsers.get(p.getIdentifier());
            final Set<String> groupIdentifiers = policyToGroups.get(p.getIdentifier());
            policies.add(mapTopAccessPolicy(p, userIdentifiers, groupIdentifiers));
        });

        return policies;
    }

    @Override
    public AccessPolicy getAccessPolicy(final String identifier) throws AuthorizationAccessException {
        Validate.notBlank(identifier);

        final DatabaseAccessPolicy databaseAccessPolicy = getDatabaseAcessPolicy(identifier);
        if (databaseAccessPolicy == null) {
            return null;
        }

        final Set<String> userIdentifiers = getPolicyUsers(identifier);
        final Set<String> groupIdentifiers = getPolicyGroups(identifier);
        return mapTopAccessPolicy(databaseAccessPolicy, userIdentifiers, groupIdentifiers);
    }

    @Override
    public AccessPolicy getAccessPolicy(final String resourceIdentifier, RequestAction action) throws AuthorizationAccessException {
        Validate.notBlank(resourceIdentifier);
        Validate.notNull(action);

        final String policySql = "SELECT * FROM APP_POLICY WHERE RESOURCE = ? AND ACTION = ?";
        final Object[] args = new Object[]{resourceIdentifier, action.toString()};
        final DatabaseAccessPolicy databaseAccessPolicy = queryForObject(policySql, args, new DatabaseAccessPolicyRowMapper());
        if (databaseAccessPolicy == null) {
            return null;
        }

        final Set<String> userIdentifiers = getPolicyUsers(databaseAccessPolicy.getIdentifier());
        final Set<String> groupIdentifiers = getPolicyGroups(databaseAccessPolicy.getIdentifier());
        return mapTopAccessPolicy(databaseAccessPolicy, userIdentifiers, groupIdentifiers);
    }

    @Override
    public AccessPolicy deleteAccessPolicy(final AccessPolicy accessPolicy) throws AuthorizationAccessException {
        Validate.notNull(accessPolicy);

        final String sql = "DELETE FROM APP_POLICY WHERE IDENTIFIER = ?";
        final int rowsUpdated = jdbcTemplate.update(sql, accessPolicy.getIdentifier());
        if (rowsUpdated <= 0) {
            return null;
        }

        return accessPolicy;
    }

    protected void createPolicyUserAndGroups(final AccessPolicy accessPolicy) {
        if (accessPolicy.getUsers() != null) {
            for (final String userIdentifier : accessPolicy.getUsers()) {
                insertPolicyUser(accessPolicy.getIdentifier(), userIdentifier);
            }
        }

        if (accessPolicy.getGroups() != null) {
            for (final String groupIdentifier : accessPolicy.getGroups()) {
                insertPolicyGroup(accessPolicy.getIdentifier(), groupIdentifier);
            }
        }
    }

    protected void insertPolicyGroup(final String policyIdentifier, final String groupIdentifier) {
        final String policyGroupSql = "INSERT INTO APP_POLICY_GROUP(POLICY_IDENTIFIER, GROUP_IDENTIFIER) VALUES (?, ?)";
        jdbcTemplate.update(policyGroupSql, policyIdentifier, groupIdentifier);
    }

    protected void insertPolicyUser(final String policyIdentifier, final String userIdentifier) {
        final String policyUserSql = "INSERT INTO APP_POLICY_USER(POLICY_IDENTIFIER, USER_IDENTIFIER) VALUES (?, ?)";
        jdbcTemplate.update(policyUserSql, policyIdentifier, userIdentifier);
    }

    protected DatabaseAccessPolicy getDatabaseAcessPolicy(final String policyIdentifier) {
        final String sql = "SELECT * FROM APP_POLICY WHERE IDENTIFIER = ?";
        return queryForObject(sql, new Object[] {policyIdentifier}, new DatabaseAccessPolicyRowMapper());
    }

    protected Set<String> getPolicyUsers(final String policyIdentifier) {
        final String sql = "SELECT * FROM APP_POLICY_USER WHERE POLICY_IDENTIFIER = ?";

        final Set<String> userIdentifiers = new HashSet<>();
        jdbcTemplate.query(sql, new Object[]{policyIdentifier}, (rs) -> {
            userIdentifiers.add(rs.getString("USER_IDENTIFIER"));
        });
        return userIdentifiers;
    }

    protected Set<String> getPolicyGroups(final String policyIdentifier) {
        final String sql = "SELECT * FROM APP_POLICY_GROUP WHERE POLICY_IDENTIFIER = ?";

        final Set<String> groupIdentifiers = new HashSet<>();
        jdbcTemplate.query(sql, new Object[]{policyIdentifier}, (rs) -> {
            groupIdentifiers.add(rs.getString("GROUP_IDENTIFIER"));
        });
        return groupIdentifiers;
    }

    protected AccessPolicy mapTopAccessPolicy(final DatabaseAccessPolicy databaseAccessPolicy, final Set<String> userIdentifiers, final Set<String> groupIdentifiers) {
        return new AccessPolicy.Builder()
                .identifier(databaseAccessPolicy.getIdentifier())
                .resource(databaseAccessPolicy.getResource())
                .action(RequestAction.valueOfValue(databaseAccessPolicy.getAction()))
                .addUsers(userIdentifiers)
                .addGroups(groupIdentifiers)
                .build();
    }

    protected void populateInitialPolicy(final User initialUser, final ResourceAndAction resourceAndAction) {
        final String userIdentifier = initialUser.getIdentifier();
        final String resourceIdentifier = resourceAndAction.getResource().getIdentifier();
        final RequestAction action = resourceAndAction.getAction();

        final AccessPolicy existingPolicy = getAccessPolicy(resourceIdentifier, action);
        if (existingPolicy == null) {
            // no policy exists for the given resource and action, so create a new one and add the given user
            // we don't need to seed the identifier here since there is only a single external DB
            final AccessPolicy accessPolicy = new AccessPolicy.Builder()
                    .identifierGenerateRandom()
                    .resource(resourceIdentifier)
                    .action(action)
                    .addUser(userIdentifier)
                    .build();

            addAccessPolicy(accessPolicy);
        } else {
            // a policy already exists for the given resource and action, so just associate the user with that policy
            if (existingPolicy.getUsers().contains(initialUser.getIdentifier())) {
                LOGGER.debug("'{}' is already part of the policy for {} {}",
                        new Object[]{initialUser.getIdentity(), action.toString(), resourceIdentifier});
            } else {
                LOGGER.debug("Adding '{}' to the policy for {} {}",
                        new Object[]{initialUser.getIdentity(), action.toString(), resourceIdentifier});
                insertPolicyUser(existingPolicy.getIdentifier(), userIdentifier);
            }
        }
    }

    protected void populateInitialPolicy(final Group initialGroup, final ResourceAndAction resourceAndAction) {
        final String resourceIdentifier = resourceAndAction.getResource().getIdentifier();
        final RequestAction action = resourceAndAction.getAction();

        final AccessPolicy existingPolicy = getAccessPolicy(resourceIdentifier, action);
        if (existingPolicy == null) {
            // no policy exists for the given resource and action, so create a new one and add the given group
            // we don't need to seed the identifier here since there is only a single external DB
            final AccessPolicy accessPolicy = new AccessPolicy.Builder()
                    .identifierGenerateRandom()
                    .resource(resourceIdentifier)
                    .action(action)
                    .addGroup(initialGroup.getIdentifier())
                    .build();

            addAccessPolicy(accessPolicy);
        } else {
            // a policy already exists for the given resource and action, so just associate the group with that policy
            insertPolicyGroup(existingPolicy.getIdentifier(), initialGroup.getIdentifier());
        }
    }

    //-- util methods

    protected <T> T queryForObject(final String sql, final Object[] args, final RowMapper<T> rowMapper) {
        try {
            return jdbcTemplate.queryForObject(sql, args, rowMapper);
        } catch(final EmptyResultDataAccessException e) {
            return null;
        }
    }

}
