alsutton/enterprisepasswordsafe

View on GitHub
src/main/java/com/enterprisepasswordsafe/database/AuthenticationSourceDAO.java

Summary

Maintainability
A
50 mins
Test Coverage
F
0%
/*
 * Copyright (c) 2017 Carbon Security Ltd. <opensource@carbonsecurity.co.uk>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.enterprisepasswordsafe.database;

import java.security.GeneralSecurityException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;

/**
 * Data access object for the user access control.
 */

public class AuthenticationSourceDAO {

    /**
     * The SQL to get all the properties associated with a authorisation source.
     */

    private static final String GET_PROPERTIES_SQL =
        "SELECT param_name, param_value "
        + "FROM auth_sources "
        + "WHERE  source_id = ?";

    /**
     * The SQL to get all the properties associated with a authorisation source.
     */

    private static final String EXISTS_BY_NAME_SQL =
        "SELECT source_id "
        + "FROM auth_sources "
        + "WHERE param_name = '"+AuthenticationSource.NAME_PARAMETER+"' "
        + "  AND param_value = ?";

    /**
     * The SQL to get all sources.
     */

    private static final String GET_ALL =
        "SELECT source_id, param_name, param_value "
        + "FROM auth_sources "
        + "ORDER BY source_id";

    /**
     * The SQL to store a parameter about an authentication source.
     */

    private static final String STORE_SQL =
        "INSERT INTO auth_sources( source_id, param_name, param_value ) "
        + "                VALUES(         ?,          ?,           ? )";

    /**
     * The SQL to store a parameter about an authentication source.
     */

    private static final String UPDATE_SQL =
        "UPDATE auth_sources"
        + " SET param_value = ? "
        + " WHERE source_id = ? and param_name = ?";

    /**
     * SQL to get the the users who are using this authentication source.
     */

    private static final String GET_USERNAMES_SQL =
          "SELECT appusers.user_name"
        + "  FROM application_users appusers"
        + " WHERE appusers.auth_source = ? "
        + "  AND disabled <> '"+User.DELETED_VALUE+"'";

    /**
     * The SQL to delete this authentication source.
     */

    private static final String DELETE_SQL = "DELETE FROM auth_sources WHERE source_id = ? ";

    /**
     * Private constructor to prevent instantiation
     */

    private AuthenticationSourceDAO() {
        super();
    }

    /**
     * Creates a new authentication source.
     */

    public void create(final String name, final String jaasType,
                       final Map<String,String> properties)
        throws SQLException, GeneralSecurityException {
        if( existsByName(name) )  {
            throw new GeneralSecurityException("A source with that name already exists");
        }
        AuthenticationSource as = new AuthenticationSource(name, jaasType, properties);
        store(as);
    }

    /**
     * Retrieves the authentication source for a specific name.
     *
     * @param sourceId The ID of the source to retrieve.
     *
     * @return The authentication source.
     *
     * @throws SQLException Thrown if there is a problem accessing the database.
     */

    public AuthenticationSource getById(final String sourceId)
            throws SQLException {
        if (sourceId == null || sourceId.equals(AuthenticationSource.DEFAULT_SOURCE_ID)) {
            return AuthenticationSource.DEFAULT_SOURCE;
        }

        try(PreparedStatement ps = BOMFactory.getCurrentConntection().prepareStatement(GET_PROPERTIES_SQL)) {
            ps.setString(1, sourceId);
            try(ResultSet rs = ps.executeQuery()) {
                Map<String, String> props = new HashMap<>();
                while (rs.next()) {
                    String key = rs.getString(1);
                    String value = rs.getString(2);
                    if (value != null) {
                        props.put(key, value);
                    }
                }

                if (props.size() == 0) {
                    return null;
                }

                return new AuthenticationSource(sourceId, props);
            }
        }
    }

    /**
     * Retrieves the authentication source for a specific name.
     *
     * @param sourceName the name of the source to get,
     *
     * @return The authentication source.
     *
     * @throws SQLException Thrown if there is a problem accessing the database.
     */

    public boolean existsByName(final String sourceName)
            throws SQLException {
        if (sourceName == null
        ||  sourceName.equals(AuthenticationSource.DEFAULT_SOURCE.getName())) {
            return true;
        }

        try(PreparedStatement ps = BOMFactory.getCurrentConntection().prepareStatement(EXISTS_BY_NAME_SQL)) {
            ps.setString(1, sourceName);
            try(ResultSet rs = ps.executeQuery()) {
                return rs.next();
            }
        }
    }

    /**
     * Stores this authentication source in the database.
     *
     * @param source The source to store.
     *
     * @throws SQLException If there is a problem accessing the database.
     */

    public void store(final AuthenticationSource source)
        throws SQLException {
        try(PreparedStatement ps = BOMFactory.getCurrentConntection().prepareStatement(STORE_SQL)) {
            addParameterForStore(ps, source,
                    AuthenticationSource.NAME_PARAMETER, source.getName());
            addParameterForStore(ps, source,
                    AuthenticationSource.JAAS_TYPE_PARAMETER, source.getJaasType());
            for(Map.Entry<String,String> thisEntry : source.getProperties().entrySet()) {
                addParameterForStore( ps, source, thisEntry.getKey(), thisEntry.getValue() );
            }

            ps.executeBatch();
        }
    }

    /**
     * Stores a parameter in the prepared statement batch.
     *
     * @param ps The prepared statement used to store the data.
     * @param propertyName The parameter name.
     * @param value The parameter value.
     *
     * @throws SQLException thrown if there is a problem storing the data.
     */

    private void addParameterForStore(final PreparedStatement ps,
            final AuthenticationSource source, final String propertyName,
            final String value)
        throws SQLException {
        int idx = 1;
        ps.setString(idx++, source.getSourceId());
        ps.setString(idx++, propertyName);
        ps.setString(idx, value);
        ps.addBatch();
    }

    /**
     * Stores this authentication source in the database.
     *
     * @param source The source to update.
     *
     * @throws SQLException If there is a problem accessing the database.
     */

    public void update(final AuthenticationSource source)
        throws SQLException {
        try(PreparedStatement ps = BOMFactory.getCurrentConntection().prepareStatement(UPDATE_SQL)) {
            addParameterForUpdate(ps, source,
                    AuthenticationSource.NAME_PARAMETER, source.getName());
            addParameterForUpdate(ps, source,
                    AuthenticationSource.JAAS_TYPE_PARAMETER, source.getJaasType());
            for(Map.Entry<String,String> thisEntry : source.getProperties().entrySet()) {
                addParameterForUpdate( ps, source, thisEntry.getKey(), thisEntry.getValue() );
            }

            ps.executeBatch();
        }
    }

    /**
     * Stores a parameter in the prepared statement batch.
     *
     * @param ps The prepared statement to use to store the data.
     * @param propertyName The parameter name.
     * @param value The parameter value.
     *
     * @throws SQLException Thrown if there is a problem storing the data.
     */

    private void addParameterForUpdate(final PreparedStatement ps,
            final AuthenticationSource source, final String propertyName,
            final String value)
        throws SQLException {
        int idx = 1;
        ps.setString(idx++, value);
        ps.setString(idx++, source.getSourceId());
        ps.setString(idx, propertyName);
        ps.addBatch();
    }

    /**
     * Gets a List of usernames of the users who are being authenticated by this authentication source.
     *
     * @param source The source for which the usernames should be retrieved.
     *
     * @return The List of User objects.
     *
     * @throws SQLException Thrown if there is a problem with the database.
     */

    public List<String> getUsernames(final AuthenticationSource source)
        throws SQLException {
        List<String> usernames = new ArrayList<>();

        try(PreparedStatement ps = BOMFactory.getCurrentConntection().prepareStatement(GET_USERNAMES_SQL)) {
            ps.setString(1, source.getSourceId());
            try(ResultSet rs = ps.executeQuery()) {
                while (rs.next()) {
                    usernames.add(rs.getString(1));
                }
            }
        }

        return usernames;
    }

    /**
     * Delete this authentication source from the database.
     *
     * @param source The authentication source to delete
     *
     * @throws SQLException Thrown if there is a problem with the database.
     */

    public void delete(final AuthenticationSource source)
        throws SQLException {
        try(PreparedStatement ps = BOMFactory.getCurrentConntection().prepareStatement(DELETE_SQL)) {
            ps.setString(1, source.getSourceId());
            ps.executeUpdate();
        }
    }


    /**
     * Retrieves all of the AutheticationSource objects as a List.
     *
     * @return The authentication source List.
     *
     * @throws SQLException Thrown if there is a problem accessing the database
     */

    public List<AuthenticationSource> getAll()
        throws SQLException {
        try(Statement stmt = BOMFactory.getCurrentConntection().createStatement()) {
            try(ResultSet rs = stmt.executeQuery(GET_ALL)) {
                List<AuthenticationSource> sources = new ArrayList<>();
                if (rs.next()) {
                    int idx = 1;
                    String currentId = rs.getString(idx++);
                    Map<String, String> currentMap = new HashMap<>();
                    currentMap.put(rs.getString(idx++), rs.getString(idx));
                    do {
                        int rsIdx = 1;
                        String sourceId = rs.getString(rsIdx++);
                        if (!currentId.equals(sourceId)) {
                            sources.add(new AuthenticationSource(currentId,currentMap));

                            currentId = sourceId;
                            currentMap = new HashMap<>();
                        }

                        currentMap.put(rs.getString(rsIdx++), rs.getString(rsIdx));
                    } while (rs.next());
                    sources.add(new AuthenticationSource(currentId, currentMap));
                }

                Collections.sort(sources);

                return sources;
            }
        }
    }

    private static final class InstanceHolder {
        private static final AuthenticationSourceDAO INSTANCE = new AuthenticationSourceDAO();
    }

    public static AuthenticationSourceDAO getInstance() {
        return InstanceHolder.INSTANCE;
    }
}