From adf7e6616c2a8d6f60207059288423f693509928 Mon Sep 17 00:00:00 2001 From: DUVAL Thomas Date: Thu, 16 Jun 2016 14:50:31 +0200 Subject: Add new version of aaa Change-Id: I94d72011e6019e66c98f46d11436a5cb33ff295d --- .../opendaylight/aaa/h2/config/IdmLightConfig.java | 133 +++++++++ .../aaa/h2/persistence/AbstractStore.java | 187 ++++++++++++ .../aaa/h2/persistence/DomainStore.java | 166 +++++++++++ .../aaa/h2/persistence/GrantStore.java | 158 +++++++++++ .../opendaylight/aaa/h2/persistence/H2Store.java | 316 +++++++++++++++++++++ .../opendaylight/aaa/h2/persistence/RoleStore.java | 151 ++++++++++ .../aaa/h2/persistence/StoreException.java | 29 ++ .../opendaylight/aaa/h2/persistence/UserStore.java | 202 +++++++++++++ .../authn/h2/store/rev151128/AAAH2StoreModule.java | 49 ++++ .../store/rev151128/AAAH2StoreModuleFactory.java | 29 ++ .../resources/initial/08-aaa-h2-store-config.xml | 26 ++ .../aaa-h2-store/src/main/yang/aaa-h2-store.yang | 28 ++ .../aaa/h2/persistence/DomainStoreTest.java | 76 +++++ .../aaa/h2/persistence/GrantStoreTest.java | 76 +++++ .../aaa/h2/persistence/H2StoreTest.java | 187 ++++++++++++ .../aaa/h2/persistence/RoleStoreTest.java | 76 +++++ .../aaa/h2/persistence/UserStoreTest.java | 79 ++++++ 17 files changed, 1968 insertions(+) create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/config/IdmLightConfig.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/AbstractStore.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/DomainStore.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/GrantStore.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/H2Store.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/RoleStore.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/StoreException.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/UserStore.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/h2/store/rev151128/AAAH2StoreModule.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/h2/store/rev151128/AAAH2StoreModuleFactory.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/resources/initial/08-aaa-h2-store-config.xml create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/main/yang/aaa-h2-store.yang create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/DomainStoreTest.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/GrantStoreTest.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/H2StoreTest.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/RoleStoreTest.java create mode 100644 odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/UserStoreTest.java (limited to 'odl-aaa-moon/aaa/aaa-h2-store/src') diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/config/IdmLightConfig.java b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/config/IdmLightConfig.java new file mode 100644 index 00000000..a35ca48f --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/config/IdmLightConfig.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.config; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Responsible for providing configuration properties for the IDMLight/H2 + * data store implementation. + * + * @author peter.mellquist@hp.com + * + */ +public class IdmLightConfig { + + private static final Logger LOG = LoggerFactory.getLogger(IdmLightConfig.class); + + /** + * The default timeout for db connections in seconds. + */ + private static final int DEFAULT_DB_TIMEOUT = 3; + + /** + * The default password for the database + */ + private static final String DEFAULT_PASSWORD = "bar"; + + /** + * The default username for the database + */ + private static final String DEFAULT_USERNAME = "foo"; + + /** + * The default driver for the databse is H2; a pure-java implementation + * of JDBC. + */ + private static final String DEFAULT_JDBC_DRIVER = "org.h2.Driver"; + + /** + * The default connection string includes the intention to use h2 as + * the JDBC driver, and the path for the file is located relative to + * KARAF_HOME. + */ + private static final String DEFAULT_CONNECTION_STRING = "jdbc:h2:./"; + + /** + * The default filename for the database file. + */ + private static final String DEFAULT_IDMLIGHT_DB_FILENAME = "idmlight.db"; + + /** + * The database filename + */ + private String dbName; + + /** + * the database connection string + */ + private String dbPath; + + /** + * The database driver (i.e., H2) + */ + private String dbDriver; + + /** + * The database password. This is not the same as AAA credentials! + */ + private String dbUser; + + /** + * The database username. This is not the same as AAA credentials! + */ + private String dbPwd; + + /** + * Timeout for database connections in seconds + */ + private int dbValidTimeOut; + + /** + * Creates an valid database configuration using default values. + */ + public IdmLightConfig() { + // TODO make this configurable + dbName = DEFAULT_IDMLIGHT_DB_FILENAME; + dbPath = DEFAULT_CONNECTION_STRING + dbName; + dbDriver = DEFAULT_JDBC_DRIVER; + dbUser = DEFAULT_USERNAME; + dbPwd = DEFAULT_PASSWORD; + dbValidTimeOut = DEFAULT_DB_TIMEOUT; + } + + /** + * Outputs some debugging information surrounding idmlight config + */ + public void log() { + LOG.info("DB Path : {}", dbPath); + LOG.info("DB Driver : {}", dbDriver); + LOG.info("DB Valid Time Out : {}", dbValidTimeOut); + } + + public String getDbName() { + return this.dbName; + } + + public String getDbPath() { + return this.dbPath; + } + + public String getDbDriver() { + return this.dbDriver; + } + + public String getDbUser() { + return this.dbUser; + } + + public String getDbPwd() { + return this.dbPwd; + } + + public int getDbValidTimeOut() { + return this.dbValidTimeOut; + } +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/AbstractStore.java b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/AbstractStore.java new file mode 100644 index 00000000..ba00eb84 --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/AbstractStore.java @@ -0,0 +1,187 @@ +/* + * Copyright © 2016 Red Hat, Inc. and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.aaa.h2.persistence; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Base class for H2 stores. + */ +abstract class AbstractStore { + /** + * Logger. + */ + private static final Logger LOG = LoggerFactory.getLogger(AbstractStore.class); + + /** + * The name of the table used to represent this store. + */ + private final String tableName; + + /** + * Database connection, only used for tests. + */ + Connection dbConnection = null; + + /** + * Table types we're interested in (when checking tables' existence). + */ + public static final String[] TABLE_TYPES = new String[] { "TABLE" }; + + /** + * Creates an instance. + * + * @param tableName The name of the table being managed. + */ + protected AbstractStore(String tableName) { + this.tableName = tableName; + } + + /** + * Returns a database connection. It is the caller's responsibility to close it. If the managed table does not + * exist, it will be created (using {@link #getTableCreationStatement()}). + * + * @return A database connection. + * + * @throws StoreException if an error occurs. + */ + protected Connection dbConnect() throws StoreException { + Connection conn = H2Store.getConnection(dbConnection); + try { + // Ensure table check/creation is atomic + synchronized (this) { + DatabaseMetaData dbm = conn.getMetaData(); + try (ResultSet rs = dbm.getTables(null, null, tableName, TABLE_TYPES)) { + if (rs.next()) { + LOG.debug("Table {} already exists", tableName); + } else { + LOG.info("Table {} does not exist, creating it", tableName); + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate(getTableCreationStatement()); + } + } + } + } + } catch (SQLException e) { + LOG.error("Error connecting to the H2 database", e); + throw new StoreException("Cannot connect to database server", e); + } + return conn; + } + + /** + * Empties the store. + * + * @throws StoreException if a connection error occurs. + */ + protected void dbClean() throws StoreException { + try (Connection c = dbConnect()) { + // The table name can't be a parameter in a prepared statement + String sql = "DELETE FROM " + tableName; + c.createStatement().execute(sql); + } catch (SQLException e) { + LOG.error("Error clearing table {}", tableName, e); + throw new StoreException("Error clearing table " + tableName, e); + } + } + + /** + * Returns the SQL code required to create the managed table. + * + * @return The SQL table creation statement. + */ + protected abstract String getTableCreationStatement(); + + /** + * Lists all the stored items. + * + * @return The stored item. + * + * @throws StoreException if an error occurs. + */ + protected List listAll() throws StoreException { + List result = new ArrayList<>(); + String query = "SELECT * FROM " + tableName; + try (Connection conn = dbConnect(); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(query)) { + while (rs.next()) { + result.add(fromResultSet(rs)); + } + } catch (SQLException e) { + LOG.error("Error listing all items from {}", tableName, e); + throw new StoreException(e); + } + return result; + } + + /** + * Lists the stored items returned by the given statement. + * + * @param ps The statement (which must be ready for execution). It is the caller's reponsibility to close this. + * + * @return The stored items. + * + * @throws StoreException if an error occurs. + */ + protected List listFromStatement(PreparedStatement ps) throws StoreException { + List result = new ArrayList<>(); + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + result.add(fromResultSet(rs)); + } + } catch (SQLException e) { + LOG.error("Error listing matching items from {}", tableName, e); + throw new StoreException(e); + } + return result; + } + + /** + * Extracts the first item returned by the given statement, if any. + * + * @param ps The statement (which must be ready for execution). It is the caller's reponsibility to close this. + * + * @return The first item, or {@code null} if none. + * + * @throws StoreException if an error occurs. + */ + protected T firstFromStatement(PreparedStatement ps) throws StoreException { + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + return fromResultSet(rs); + } else { + return null; + } + } catch (SQLException e) { + LOG.error("Error listing first matching item from {}", tableName, e); + throw new StoreException(e); + } + } + + /** + * Converts a single row in a result set to an instance of the managed type. + * + * @param rs The result set (which is ready for extraction; {@link ResultSet#next()} must not be called). + * + * @return The corresponding instance. + * + * @throws SQLException if an error occurs. + */ + protected abstract T fromResultSet(ResultSet rs) throws SQLException; +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/DomainStore.java b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/DomainStore.java new file mode 100644 index 00000000..aa8f4b30 --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/DomainStore.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2014, 2016 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.persistence; + +import com.google.common.base.Preconditions; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.opendaylight.aaa.api.model.Domain; +import org.opendaylight.aaa.api.model.Domains; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author peter.mellquist@hp.com + * + */ +public class DomainStore extends AbstractStore { + private static final Logger LOG = LoggerFactory.getLogger(DomainStore.class); + + protected final static String SQL_ID = "domainid"; + protected final static String SQL_NAME = "name"; + protected final static String SQL_DESCR = "description"; + protected final static String SQL_ENABLED = "enabled"; + private static final String TABLE_NAME = "DOMAINS"; + + protected DomainStore() { + super(TABLE_NAME); + } + + @Override + protected String getTableCreationStatement() { + return "CREATE TABLE DOMAINS " + + "(domainid VARCHAR(128) PRIMARY KEY," + + "name VARCHAR(128) UNIQUE NOT NULL, " + + "description VARCHAR(128) , " + + "enabled INTEGER NOT NULL)"; + } + + @Override + protected Domain fromResultSet(ResultSet rs) throws SQLException { + Domain domain = new Domain(); + domain.setDomainid(rs.getString(SQL_ID)); + domain.setName(rs.getString(SQL_NAME)); + domain.setDescription(rs.getString(SQL_DESCR)); + domain.setEnabled(rs.getInt(SQL_ENABLED) == 1); + return domain; + } + + protected Domains getDomains() throws StoreException { + Domains domains = new Domains(); + domains.setDomains(listAll()); + return domains; + } + + protected Domains getDomains(String domainName) throws StoreException { + LOG.debug("getDomains for: {}", domainName); + Domains domains = new Domains(); + try (Connection conn = dbConnect(); + PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM DOMAINS WHERE name = ?")) { + pstmt.setString(1, domainName); + LOG.debug("query string: {}", pstmt.toString()); + domains.setDomains(listFromStatement(pstmt)); + } catch (SQLException e) { + LOG.error("Error listing domains matching {}", domainName, e); + throw new StoreException("Error listing domains", e); + } + return domains; + } + + protected Domain getDomain(String id) throws StoreException { + try (Connection conn = dbConnect(); + PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM DOMAINS WHERE domainid = ? ")) { + pstmt.setString(1, id); + LOG.debug("query string: {}", pstmt.toString()); + return firstFromStatement(pstmt); + } catch (SQLException e) { + LOG.error("Error retrieving domain {}", id, e); + throw new StoreException("Error loading domain", e); + } + } + + protected Domain createDomain(Domain domain) throws StoreException { + Preconditions.checkNotNull(domain); + Preconditions.checkNotNull(domain.getName()); + Preconditions.checkNotNull(domain.isEnabled()); + String query = "insert into DOMAINS (domainid,name,description,enabled) values(?, ?, ?, ?)"; + try (Connection conn = dbConnect(); + PreparedStatement statement = conn.prepareStatement(query)) { + statement.setString(1, domain.getName()); + statement.setString(2, domain.getName()); + statement.setString(3, domain.getDescription()); + statement.setInt(4, domain.isEnabled() ? 1 : 0); + int affectedRows = statement.executeUpdate(); + if (affectedRows == 0) { + throw new StoreException("Creating domain failed, no rows affected."); + } + domain.setDomainid(domain.getName()); + return domain; + } catch (SQLException e) { + LOG.error("Error creating domain {}", domain.getName(), e); + throw new StoreException("Error creating domain", e); + } + } + + protected Domain putDomain(Domain domain) throws StoreException { + Domain savedDomain = this.getDomain(domain.getDomainid()); + if (savedDomain == null) { + return null; + } + + if (domain.getDescription() != null) { + savedDomain.setDescription(domain.getDescription()); + } + if (domain.getName() != null) { + savedDomain.setName(domain.getName()); + } + if (domain.isEnabled() != null) { + savedDomain.setEnabled(domain.isEnabled()); + } + + String query = "UPDATE DOMAINS SET description = ?, enabled = ? WHERE domainid = ?"; + try (Connection conn = dbConnect(); + PreparedStatement statement = conn.prepareStatement(query)) { + statement.setString(1, savedDomain.getDescription()); + statement.setInt(2, savedDomain.isEnabled() ? 1 : 0); + statement.setString(3, savedDomain.getDomainid()); + statement.executeUpdate(); + } catch (SQLException e) { + LOG.error("Error updating domain {}", domain.getDomainid(), e); + throw new StoreException("Error updating domain", e); + } + + return savedDomain; + } + + protected Domain deleteDomain(String domainid) throws StoreException { + domainid = StringEscapeUtils.escapeHtml4(domainid); + Domain deletedDomain = this.getDomain(domainid); + if (deletedDomain == null) { + return null; + } + String query = String.format("DELETE FROM DOMAINS WHERE domainid = '%s'", domainid); + try (Connection conn = dbConnect(); + Statement statement = conn.createStatement()) { + int deleteCount = statement.executeUpdate(query); + LOG.debug("deleted {} records", deleteCount); + return deletedDomain; + } catch (SQLException e) { + LOG.error("Error deleting domain {}", domainid, e); + throw new StoreException("Error deleting domain", e); + } + } +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/GrantStore.java b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/GrantStore.java new file mode 100644 index 00000000..ee86e0ba --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/GrantStore.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2014, 2016 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.persistence; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.opendaylight.aaa.api.IDMStoreUtil; +import org.opendaylight.aaa.api.model.Grant; +import org.opendaylight.aaa.api.model.Grants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author peter.mellquist@hp.com + * + */ +public class GrantStore extends AbstractStore { + private static final Logger LOG = LoggerFactory.getLogger(GrantStore.class); + + protected final static String SQL_ID = "grantid"; + protected final static String SQL_TENANTID = "domainid"; + protected final static String SQL_USERID = "userid"; + protected final static String SQL_ROLEID = "roleid"; + private static final String TABLE_NAME = "GRANTS"; + + protected GrantStore() { + super(TABLE_NAME); + } + + @Override + protected String getTableCreationStatement() { + return "CREATE TABLE GRANTS " + + "(grantid VARCHAR(128) PRIMARY KEY," + + "domainid VARCHAR(128) NOT NULL, " + + "userid VARCHAR(128) NOT NULL, " + + "roleid VARCHAR(128) NOT NULL)"; + } + + protected Grant fromResultSet(ResultSet rs) throws SQLException { + Grant grant = new Grant(); + try { + grant.setGrantid(rs.getString(SQL_ID)); + grant.setDomainid(rs.getString(SQL_TENANTID)); + grant.setUserid(rs.getString(SQL_USERID)); + grant.setRoleid(rs.getString(SQL_ROLEID)); + } catch (SQLException sqle) { + LOG.error("SQL Exception: ", sqle); + throw sqle; + } + return grant; + } + + protected Grants getGrants(String did, String uid) throws StoreException { + Grants grants = new Grants(); + try (Connection conn = dbConnect(); + PreparedStatement pstmt = conn + .prepareStatement("SELECT * FROM grants WHERE domainid = ? AND userid = ?")) { + pstmt.setString(1, did); + pstmt.setString(2, uid); + LOG.debug("query string: {}", pstmt.toString()); + grants.setGrants(listFromStatement(pstmt)); + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + return grants; + } + + protected Grants getGrants(String userid) throws StoreException { + Grants grants = new Grants(); + try (Connection conn = dbConnect(); + PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM GRANTS WHERE userid = ? ")) { + pstmt.setString(1, userid); + LOG.debug("query string: {}", pstmt.toString()); + grants.setGrants(listFromStatement(pstmt)); + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + return grants; + } + + protected Grant getGrant(String id) throws StoreException { + try (Connection conn = dbConnect(); + PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM GRANTS WHERE grantid = ? ")) { + pstmt.setString(1, id); + LOG.debug("query string: ", pstmt.toString()); + return firstFromStatement(pstmt); + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + } + + protected Grant getGrant(String did, String uid, String rid) throws StoreException { + try (Connection conn = dbConnect(); + PreparedStatement pstmt = conn + .prepareStatement("SELECT * FROM GRANTS WHERE domainid = ? AND userid = ? AND roleid = ? ")) { + pstmt.setString(1, did); + pstmt.setString(2, uid); + pstmt.setString(3, rid); + LOG.debug("query string: {}", pstmt.toString()); + return firstFromStatement(pstmt); + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + } + + protected Grant createGrant(Grant grant) throws StoreException { + String query = "insert into grants (grantid,domainid,userid,roleid) values(?,?,?,?)"; + try (Connection conn = dbConnect(); + PreparedStatement statement = conn.prepareStatement(query)) { + statement.setString( + 1, + IDMStoreUtil.createGrantid(grant.getUserid(), grant.getDomainid(), + grant.getRoleid())); + statement.setString(2, grant.getDomainid()); + statement.setString(3, grant.getUserid()); + statement.setString(4, grant.getRoleid()); + int affectedRows = statement.executeUpdate(); + if (affectedRows == 0) { + throw new StoreException("Creating grant failed, no rows affected."); + } + grant.setGrantid(IDMStoreUtil.createGrantid(grant.getUserid(), grant.getDomainid(), + grant.getRoleid())); + return grant; + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + } + + protected Grant deleteGrant(String grantid) throws StoreException { + grantid = StringEscapeUtils.escapeHtml4(grantid); + Grant savedGrant = this.getGrant(grantid); + if (savedGrant == null) { + return null; + } + + String query = String.format("DELETE FROM GRANTS WHERE grantid = '%s'", grantid); + try (Connection conn = dbConnect(); + Statement statement = conn.createStatement()) { + int deleteCount = statement.executeUpdate(query); + LOG.debug("deleted {} records", deleteCount); + return savedGrant; + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + } +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/H2Store.java b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/H2Store.java new file mode 100644 index 00000000..da40a17b --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/H2Store.java @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2015 Cisco Systems and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.persistence; + +import java.sql.Connection; +import java.sql.DriverManager; + +import org.opendaylight.aaa.api.IDMStoreException; +import org.opendaylight.aaa.api.IDMStoreUtil; +import org.opendaylight.aaa.api.IIDMStore; +import org.opendaylight.aaa.api.model.Domain; +import org.opendaylight.aaa.api.model.Domains; +import org.opendaylight.aaa.api.model.Grant; +import org.opendaylight.aaa.api.model.Grants; +import org.opendaylight.aaa.api.model.Role; +import org.opendaylight.aaa.api.model.Roles; +import org.opendaylight.aaa.api.model.User; +import org.opendaylight.aaa.api.model.Users; +import org.opendaylight.aaa.h2.config.IdmLightConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class H2Store implements IIDMStore { + + private static final Logger LOG = LoggerFactory.getLogger(H2Store.class); + + private static IdmLightConfig config = new IdmLightConfig(); + private DomainStore domainStore = new DomainStore(); + private UserStore userStore = new UserStore(); + private RoleStore roleStore = new RoleStore(); + private GrantStore grantStore = new GrantStore(); + + public H2Store() { + } + + public static Connection getConnection(Connection existingConnection) throws StoreException { + Connection connection = existingConnection; + try { + if (existingConnection == null || existingConnection.isClosed()) { + new org.h2.Driver(); + connection = DriverManager.getConnection(config.getDbPath(), config.getDbUser(), + config.getDbPwd()); + } + } catch (Exception e) { + throw new StoreException("Cannot connect to database server" + e); + } + + return connection; + } + + public static IdmLightConfig getConfig() { + return config; + } + + @Override + public Domain writeDomain(Domain domain) throws IDMStoreException { + try { + return domainStore.createDomain(domain); + } catch (StoreException e) { + LOG.error("StoreException encountered while writing domain", e); + throw new IDMStoreException(e); + } + } + + @Override + public Domain readDomain(String domainid) throws IDMStoreException { + try { + return domainStore.getDomain(domainid); + } catch (StoreException e) { + LOG.error("StoreException encountered while reading domain", e); + throw new IDMStoreException(e); + } + } + + @Override + public Domain deleteDomain(String domainid) throws IDMStoreException { + try { + return domainStore.deleteDomain(domainid); + } catch (StoreException e) { + LOG.error("StoreException encountered while deleting domain", e); + throw new IDMStoreException(e); + } + } + + @Override + public Domain updateDomain(Domain domain) throws IDMStoreException { + try { + return domainStore.putDomain(domain); + } catch (StoreException e) { + LOG.error("StoreException encountered while updating domain", e); + throw new IDMStoreException(e); + } + } + + @Override + public Domains getDomains() throws IDMStoreException { + try { + return domainStore.getDomains(); + } catch (StoreException e) { + LOG.error("StoreException encountered while reading domains", e); + throw new IDMStoreException(e); + } + } + + @Override + public Role writeRole(Role role) throws IDMStoreException { + try { + return roleStore.createRole(role); + } catch (StoreException e) { + LOG.error("StoreException encountered while writing role", e); + throw new IDMStoreException(e); + } + } + + @Override + public Role readRole(String roleid) throws IDMStoreException { + try { + return roleStore.getRole(roleid); + } catch (StoreException e) { + LOG.error("StoreException encountered while reading role", e); + throw new IDMStoreException(e); + } + } + + @Override + public Role deleteRole(String roleid) throws IDMStoreException { + try { + return roleStore.deleteRole(roleid); + } catch (StoreException e) { + LOG.error("StoreException encountered while deleting role", e); + throw new IDMStoreException(e); + } + } + + @Override + public Role updateRole(Role role) throws IDMStoreException { + try { + return roleStore.putRole(role); + } catch (StoreException e) { + LOG.error("StoreException encountered while updating role", e); + throw new IDMStoreException(e); + } + } + + @Override + public Roles getRoles() throws IDMStoreException { + try { + return roleStore.getRoles(); + } catch (StoreException e) { + LOG.error("StoreException encountered while getting roles", e); + throw new IDMStoreException(e); + } + } + + @Override + public User writeUser(User user) throws IDMStoreException { + try { + return userStore.createUser(user); + } catch (StoreException e) { + LOG.error("StoreException encountered while writing user", e); + throw new IDMStoreException(e); + } + } + + @Override + public User readUser(String userid) throws IDMStoreException { + try { + return userStore.getUser(userid); + } catch (StoreException e) { + LOG.error("StoreException encountered while reading user", e); + throw new IDMStoreException(e); + } + } + + @Override + public User deleteUser(String userid) throws IDMStoreException { + try { + return userStore.deleteUser(userid); + } catch (StoreException e) { + LOG.error("StoreException encountered while deleting user", e); + throw new IDMStoreException(e); + } + } + + @Override + public User updateUser(User user) throws IDMStoreException { + try { + return userStore.putUser(user); + } catch (StoreException e) { + LOG.error("StoreException encountered while updating user", e); + throw new IDMStoreException(e); + } + } + + @Override + public Users getUsers(String username, String domain) throws IDMStoreException { + try { + return userStore.getUsers(username, domain); + } catch (StoreException e) { + LOG.error("StoreException encountered while reading users", e); + throw new IDMStoreException(e); + } + } + + @Override + public Users getUsers() throws IDMStoreException { + try { + return userStore.getUsers(); + } catch (StoreException e) { + LOG.error("StoreException encountered while reading users", e); + throw new IDMStoreException(e); + } + } + + @Override + public Grant writeGrant(Grant grant) throws IDMStoreException { + try { + return grantStore.createGrant(grant); + } catch (StoreException e) { + LOG.error("StoreException encountered while writing grant", e); + throw new IDMStoreException(e); + } + } + + @Override + public Grant readGrant(String grantid) throws IDMStoreException { + try { + return grantStore.getGrant(grantid); + } catch (StoreException e) { + LOG.error("StoreException encountered while reading grant", e); + throw new IDMStoreException(e); + } + } + + @Override + public Grant deleteGrant(String grantid) throws IDMStoreException { + try { + return grantStore.deleteGrant(grantid); + } catch (StoreException e) { + LOG.error("StoreException encountered while deleting grant", e); + throw new IDMStoreException(e); + } + } + + @Override + public Grants getGrants(String domainid, String userid) throws IDMStoreException { + try { + return grantStore.getGrants(domainid, userid); + } catch (StoreException e) { + LOG.error("StoreException encountered while getting grants", e); + throw new IDMStoreException(e); + } + } + + @Override + public Grants getGrants(String userid) throws IDMStoreException { + try { + return grantStore.getGrants(userid); + } catch (StoreException e) { + LOG.error("StoreException encountered while getting grants", e); + throw new IDMStoreException(e); + } + } + + @Override + public Grant readGrant(String domainid, String userid, String roleid) throws IDMStoreException { + return readGrant(IDMStoreUtil.createGrantid(userid, domainid, roleid)); + } + + public static Domain createDomain(String domainName, boolean enable) throws StoreException { + DomainStore ds = new DomainStore(); + Domain d = new Domain(); + d.setName(domainName); + d.setEnabled(enable); + return ds.createDomain(d); + } + + public static User createUser(String name, String password, String domain, String description, + String email, boolean enabled, String SALT) throws StoreException { + UserStore us = new UserStore(); + User u = new User(); + u.setName(name); + u.setDomainid(domain); + u.setDescription(description); + u.setEmail(email); + u.setEnabled(enabled); + u.setPassword(password); + u.setSalt(SALT); + return us.createUser(u); + } + + public static Role createRole(String name, String domain, String description) + throws StoreException { + RoleStore rs = new RoleStore(); + Role r = new Role(); + r.setDescription(description); + r.setName(name); + r.setDomainid(domain); + return rs.createRole(r); + } + + public static Grant createGrant(String domain, String user, String role) throws StoreException { + GrantStore gs = new GrantStore(); + Grant g = new Grant(); + g.setDomainid(domain); + g.setRoleid(role); + g.setUserid(user); + return gs.createGrant(g); + } +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/RoleStore.java b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/RoleStore.java new file mode 100644 index 00000000..e7defa4a --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/RoleStore.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2014, 2016 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.persistence; + +import com.google.common.base.Preconditions; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.opendaylight.aaa.api.IDMStoreUtil; +import org.opendaylight.aaa.api.model.Role; +import org.opendaylight.aaa.api.model.Roles; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author peter.mellquist@hp.com + * + */ +public class RoleStore extends AbstractStore { + private static final Logger LOG = LoggerFactory.getLogger(RoleStore.class); + + protected final static String SQL_ID = "roleid"; + protected final static String SQL_DOMAIN_ID = "domainid"; + protected final static String SQL_NAME = "name"; + protected final static String SQL_DESCR = "description"; + private static final String TABLE_NAME = "ROLES"; + + protected RoleStore() { + super(TABLE_NAME); + } + + @Override + protected String getTableCreationStatement() { + return "CREATE TABLE ROLES " + + "(roleid VARCHAR(128) PRIMARY KEY," + + "name VARCHAR(128) NOT NULL, " + + "domainid VARCHAR(128) NOT NULL, " + + "description VARCHAR(128) NOT NULL)"; + } + + protected Role fromResultSet(ResultSet rs) throws SQLException { + Role role = new Role(); + try { + role.setRoleid(rs.getString(SQL_ID)); + role.setDomainid(rs.getString(SQL_DOMAIN_ID)); + role.setName(rs.getString(SQL_NAME)); + role.setDescription(rs.getString(SQL_DESCR)); + } catch (SQLException sqle) { + LOG.error("SQL Exception: ", sqle); + throw sqle; + } + return role; + } + + protected Roles getRoles() throws StoreException { + Roles roles = new Roles(); + roles.setRoles(listAll()); + return roles; + } + + protected Role getRole(String id) throws StoreException { + try (Connection conn = dbConnect(); + PreparedStatement pstmt = conn + .prepareStatement("SELECT * FROM ROLES WHERE roleid = ? ")) { + pstmt.setString(1, id); + LOG.debug("query string: {}", pstmt.toString()); + return firstFromStatement(pstmt); + } catch (SQLException s) { + throw new StoreException("SQL Exception: " + s); + } + } + + protected Role createRole(Role role) throws StoreException { + Preconditions.checkNotNull(role); + Preconditions.checkNotNull(role.getName()); + Preconditions.checkNotNull(role.getDomainid()); + String query = "insert into roles (roleid,domainid,name,description) values(?,?,?,?)"; + try (Connection conn = dbConnect(); + PreparedStatement statement = conn.prepareStatement(query)) { + role.setRoleid(IDMStoreUtil.createRoleid(role.getName(), role.getDomainid())); + statement.setString(1, role.getRoleid()); + statement.setString(2, role.getDomainid()); + statement.setString(3, role.getName()); + statement.setString(4, role.getDescription()); + int affectedRows = statement.executeUpdate(); + if (affectedRows == 0) { + throw new StoreException("Creating role failed, no rows affected."); + } + return role; + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + } + + protected Role putRole(Role role) throws StoreException { + + Role savedRole = this.getRole(role.getRoleid()); + if (savedRole == null) { + return null; + } + + if (role.getDescription() != null) { + savedRole.setDescription(role.getDescription()); + } + if (role.getName() != null) { + savedRole.setName(role.getName()); + } + + String query = "UPDATE roles SET description = ? WHERE roleid = ?"; + try (Connection conn = dbConnect(); + PreparedStatement statement = conn.prepareStatement(query)) { + statement.setString(1, savedRole.getDescription()); + statement.setString(2, savedRole.getRoleid()); + statement.executeUpdate(); + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + + return savedRole; + } + + protected Role deleteRole(String roleid) throws StoreException { + roleid = StringEscapeUtils.escapeHtml4(roleid); + Role savedRole = this.getRole(roleid); + if (savedRole == null) { + return null; + } + + String query = String.format("DELETE FROM ROLES WHERE roleid = '%s'", roleid); + try (Connection conn = dbConnect(); + Statement statement = conn.createStatement()) { + int deleteCount = statement.executeUpdate(query); + LOG.debug("deleted {} records", deleteCount); + return savedRole; + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + } +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/StoreException.java b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/StoreException.java new file mode 100644 index 00000000..7d2f2b9a --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/StoreException.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014, 2016 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.persistence; + +/** + * Exception indicating an error in an H2 data store. + * + * @author peter.mellquist@hp.com + */ + +public class StoreException extends Exception { + public StoreException(String message) { + super(message); + } + + public StoreException(String message, Throwable cause) { + super(message, cause); + } + + public StoreException(Throwable cause) { + super(cause); + } +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/UserStore.java b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/UserStore.java new file mode 100644 index 00000000..96b8013f --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/aaa/h2/persistence/UserStore.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2014, 2016 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.persistence; + +import com.google.common.base.Preconditions; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.opendaylight.aaa.api.IDMStoreUtil; +import org.opendaylight.aaa.api.SHA256Calculator; +import org.opendaylight.aaa.api.model.User; +import org.opendaylight.aaa.api.model.Users; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author peter.mellquist@hp.com + * + */ +public class UserStore extends AbstractStore { + private static final Logger LOG = LoggerFactory.getLogger(UserStore.class); + + protected final static String SQL_ID = "userid"; + protected final static String SQL_DOMAIN_ID = "domainid"; + protected final static String SQL_NAME = "name"; + protected final static String SQL_EMAIL = "email"; + protected final static String SQL_PASSWORD = "password"; + protected final static String SQL_DESCR = "description"; + protected final static String SQL_ENABLED = "enabled"; + protected final static String SQL_SALT = "salt"; + private static final String TABLE_NAME = "USERS"; + + protected UserStore() { + super(TABLE_NAME); + } + + @Override + protected String getTableCreationStatement() { + return "CREATE TABLE users " + + "(userid VARCHAR(128) PRIMARY KEY," + + "name VARCHAR(128) NOT NULL, " + + "domainid VARCHAR(128) NOT NULL, " + + "email VARCHAR(128) NOT NULL, " + + "password VARCHAR(128) NOT NULL, " + + "description VARCHAR(128) NOT NULL, " + + "salt VARCHAR(15) NOT NULL, " + + "enabled INTEGER NOT NULL)"; + } + + @Override + protected User fromResultSet(ResultSet rs) throws SQLException { + User user = new User(); + try { + user.setUserid(rs.getString(SQL_ID)); + user.setDomainid(rs.getString(SQL_DOMAIN_ID)); + user.setName(rs.getString(SQL_NAME)); + user.setEmail(rs.getString(SQL_EMAIL)); + user.setPassword(rs.getString(SQL_PASSWORD)); + user.setDescription(rs.getString(SQL_DESCR)); + user.setEnabled(rs.getInt(SQL_ENABLED) == 1); + user.setSalt(rs.getString(SQL_SALT)); + } catch (SQLException sqle) { + LOG.error("SQL Exception: ", sqle); + throw sqle; + } + return user; + } + + protected Users getUsers() throws StoreException { + Users users = new Users(); + users.setUsers(listAll()); + return users; + } + + protected Users getUsers(String username, String domain) throws StoreException { + LOG.debug("getUsers for: {} in domain {}", username, domain); + + Users users = new Users(); + try (Connection conn = dbConnect(); + PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM USERS WHERE userid = ? ")) { + pstmt.setString(1, IDMStoreUtil.createUserid(username, domain)); + LOG.debug("query string: {}", pstmt.toString()); + users.setUsers(listFromStatement(pstmt)); + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + return users; + } + + protected User getUser(String id) throws StoreException { + try (Connection conn = dbConnect(); + PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM USERS WHERE userid = ? ")) { + pstmt.setString(1, id); + LOG.debug("query string: {}", pstmt.toString()); + return firstFromStatement(pstmt); + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + } + + protected User createUser(User user) throws StoreException { + Preconditions.checkNotNull(user); + Preconditions.checkNotNull(user.getName()); + Preconditions.checkNotNull(user.getDomainid()); + + user.setSalt(SHA256Calculator.generateSALT()); + String query = "insert into users (userid,domainid,name,email,password,description,enabled,salt) values(?,?,?,?,?,?,?,?)"; + try (Connection conn = dbConnect(); + PreparedStatement statement = conn.prepareStatement(query)) { + user.setUserid(IDMStoreUtil.createUserid(user.getName(), user.getDomainid())); + statement.setString(1, user.getUserid()); + statement.setString(2, user.getDomainid()); + statement.setString(3, user.getName()); + statement.setString(4, user.getEmail()); + statement.setString(5, SHA256Calculator.getSHA256(user.getPassword(), user.getSalt())); + statement.setString(6, user.getDescription()); + statement.setInt(7, user.isEnabled() ? 1 : 0); + statement.setString(8, user.getSalt()); + int affectedRows = statement.executeUpdate(); + if (affectedRows == 0) { + throw new StoreException("Creating user failed, no rows affected."); + } + return user; + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + } + + protected User putUser(User user) throws StoreException { + + User savedUser = this.getUser(user.getUserid()); + if (savedUser == null) { + return null; + } + + if (user.getDescription() != null) { + savedUser.setDescription(user.getDescription()); + } + if (user.getName() != null) { + savedUser.setName(user.getName()); + } + if (user.isEnabled() != null) { + savedUser.setEnabled(user.isEnabled()); + } + if (user.getEmail() != null) { + savedUser.setEmail(user.getEmail()); + } + if (user.getPassword() != null) { + // If a new salt is provided, use it. Otherwise, derive salt from existing. + String salt = user.getSalt(); + if (salt == null) { + salt = savedUser.getSalt(); + } + savedUser.setPassword(SHA256Calculator.getSHA256(user.getPassword(), salt)); + } + + String query = "UPDATE users SET email = ?, password = ?, description = ?, enabled = ? WHERE userid = ?"; + try (Connection conn = dbConnect(); + PreparedStatement statement = conn.prepareStatement(query)) { + statement.setString(1, savedUser.getEmail()); + statement.setString(2, savedUser.getPassword()); + statement.setString(3, savedUser.getDescription()); + statement.setInt(4, savedUser.isEnabled() ? 1 : 0); + statement.setString(5, savedUser.getUserid()); + statement.executeUpdate(); + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + + return savedUser; + } + + protected User deleteUser(String userid) throws StoreException { + userid = StringEscapeUtils.escapeHtml4(userid); + User savedUser = this.getUser(userid); + if (savedUser == null) { + return null; + } + + String query = String.format("DELETE FROM USERS WHERE userid = '%s'", userid); + try (Connection conn = dbConnect(); + Statement statement = conn.createStatement()) { + int deleteCount = statement.executeUpdate(query); + LOG.debug("deleted {} records", deleteCount); + return savedUser; + } catch (SQLException s) { + throw new StoreException("SQL Exception : " + s); + } + } +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/h2/store/rev151128/AAAH2StoreModule.java b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/h2/store/rev151128/AAAH2StoreModule.java new file mode 100644 index 00000000..fe7dd2a6 --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/h2/store/rev151128/AAAH2StoreModule.java @@ -0,0 +1,49 @@ +package org.opendaylight.yang.gen.v1.config.aaa.authn.h2.store.rev151128; + +import org.opendaylight.aaa.api.IIDMStore; +import org.opendaylight.aaa.h2.persistence.H2Store; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AAAH2StoreModule extends org.opendaylight.yang.gen.v1.config.aaa.authn.h2.store.rev151128.AbstractAAAH2StoreModule { + + private BundleContext bundleContext; + private static final Logger LOG = LoggerFactory.getLogger(AAAH2StoreModule.class); + + public AAAH2StoreModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public AAAH2StoreModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.config.aaa.authn.h2.store.rev151128.AAAH2StoreModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public java.lang.AutoCloseable createInstance() { + final H2Store h2Store = new H2Store(); + final ServiceRegistration serviceRegistration = bundleContext.registerService(IIDMStore.class.getName(), h2Store, null); + LOG.info("AAA H2 Store Initialized"); + return new AutoCloseable() { + @Override + public void close() throws Exception { + serviceRegistration.unregister(); + } + }; + } + + /** + * @param bundleContext + */ + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + /** + * @return the bundleContext + */ + public BundleContext getBundleContext() { + return bundleContext; + } +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/h2/store/rev151128/AAAH2StoreModuleFactory.java b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/h2/store/rev151128/AAAH2StoreModuleFactory.java new file mode 100644 index 00000000..dc9e7f99 --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/h2/store/rev151128/AAAH2StoreModuleFactory.java @@ -0,0 +1,29 @@ +/* +* Generated file +* +* Generated from: yang module name: aaa-h2-store yang module local name: aaa-h2-store +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Sat Nov 28 11:00:15 PST 2015 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.yang.gen.v1.config.aaa.authn.h2.store.rev151128; + +import org.opendaylight.controller.config.api.DependencyResolver; +import org.osgi.framework.BundleContext; + +public class AAAH2StoreModuleFactory extends org.opendaylight.yang.gen.v1.config.aaa.authn.h2.store.rev151128.AbstractAAAH2StoreModuleFactory { + @Override + public AAAH2StoreModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, AAAH2StoreModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) { + AAAH2StoreModule module = super.instantiateModule(instanceName, dependencyResolver, oldModule, oldInstance, bundleContext); + module.setBundleContext(bundleContext); + return module; + } + + @Override + public AAAH2StoreModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) { + AAAH2StoreModule module = super.instantiateModule(instanceName, dependencyResolver, bundleContext); + module.setBundleContext(bundleContext); + return module; + } +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/resources/initial/08-aaa-h2-store-config.xml b/odl-aaa-moon/aaa/aaa-h2-store/src/main/resources/initial/08-aaa-h2-store-config.xml new file mode 100644 index 00000000..cfe60812 --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/resources/initial/08-aaa-h2-store-config.xml @@ -0,0 +1,26 @@ + + + + + + + + + authn:aaa-h2-store + aaa-h2-store + + + + + + config:aaa:authn:h2:store?module=aaa-h2-store&revision=2015-11-28 + + + + diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/main/yang/aaa-h2-store.yang b/odl-aaa-moon/aaa/aaa-h2-store/src/main/yang/aaa-h2-store.yang new file mode 100644 index 00000000..af2d9bdc --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/main/yang/aaa-h2-store.yang @@ -0,0 +1,28 @@ +module aaa-h2-store { + yang-version 1; + namespace "config:aaa:authn:h2:store"; + prefix "aaa-h2-store"; + organization "OpenDayLight"; + + import config { prefix config; revision-date 2013-04-05; } + import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; } + + contact "saichler@gmail.com"; + + revision 2015-11-28 { + description + "Initial revision."; + } + + identity aaa-h2-store { + base config:module-type; + config:java-name-prefix AAAH2Store; + } + + augment "/config:modules/config:module/config:configuration" { + case aaa-h2-store { + when "/config:modules/config:module/config:type = 'aaa-h2-store'"; + } + } + +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/DomainStoreTest.java b/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/DomainStoreTest.java new file mode 100644 index 00000000..f11a99eb --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/DomainStoreTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.persistence; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.opendaylight.aaa.api.model.Domains; +import org.opendaylight.aaa.h2.persistence.DomainStore; + +public class DomainStoreTest { + + Connection connectionMock = mock(Connection.class); + private final DomainStore domainStoreUnderTest = new DomainStore(); + + @Before + public void setup() { + domainStoreUnderTest.dbConnection = connectionMock; + } + + @After + public void teardown() { + // dts.destroy(); + } + + @Test + public void getDomainsTest() throws SQLException, Exception { + // Setup Mock Behavior + String[] tableTypes = { "TABLE" }; + Mockito.when(connectionMock.isClosed()).thenReturn(false); + DatabaseMetaData dbmMock = mock(DatabaseMetaData.class); + Mockito.when(connectionMock.getMetaData()).thenReturn(dbmMock); + ResultSet rsUserMock = mock(ResultSet.class); + Mockito.when(dbmMock.getTables(null, null, "DOMAINS", tableTypes)).thenReturn(rsUserMock); + Mockito.when(rsUserMock.next()).thenReturn(true); + + Statement stmtMock = mock(Statement.class); + Mockito.when(connectionMock.createStatement()).thenReturn(stmtMock); + + ResultSet rsMock = getMockedResultSet(); + Mockito.when(stmtMock.executeQuery(anyString())).thenReturn(rsMock); + + // Run Test + Domains domains = domainStoreUnderTest.getDomains(); + + // Verify + assertTrue(domains.getDomains().size() == 1); + verify(stmtMock).close(); + } + + public ResultSet getMockedResultSet() throws SQLException { + ResultSet rsMock = mock(ResultSet.class); + Mockito.when(rsMock.next()).thenReturn(true).thenReturn(false); + Mockito.when(rsMock.getInt(DomainStore.SQL_ID)).thenReturn(1); + Mockito.when(rsMock.getString(DomainStore.SQL_NAME)).thenReturn("DomainName_1"); + Mockito.when(rsMock.getString(DomainStore.SQL_DESCR)).thenReturn("Desc_1"); + Mockito.when(rsMock.getInt(DomainStore.SQL_ENABLED)).thenReturn(1); + return rsMock; + } +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/GrantStoreTest.java b/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/GrantStoreTest.java new file mode 100644 index 00000000..168b67e2 --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/GrantStoreTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, 2016 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.persistence; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.opendaylight.aaa.api.model.Grants; + +public class GrantStoreTest { + + Connection connectionMock = mock(Connection.class); + private final GrantStore grantStoreUnderTest = new GrantStore(); + private String did = "5"; + private String uid = "5"; + + @Before + public void setup() { + grantStoreUnderTest.dbConnection = connectionMock; + } + + @Test + public void getGrantsTest() throws Exception { + // Setup Mock Behavior + String[] tableTypes = { "TABLE" }; + Mockito.when(connectionMock.isClosed()).thenReturn(false); + DatabaseMetaData dbmMock = mock(DatabaseMetaData.class); + Mockito.when(connectionMock.getMetaData()).thenReturn(dbmMock); + ResultSet rsUserMock = mock(ResultSet.class); + Mockito.when(dbmMock.getTables(null, null, "GRANTS", tableTypes)).thenReturn(rsUserMock); + Mockito.when(rsUserMock.next()).thenReturn(true); + + PreparedStatement pstmtMock = mock(PreparedStatement.class); + Mockito.when(connectionMock.prepareStatement(anyString())).thenReturn(pstmtMock); + + ResultSet rsMock = getMockedResultSet(); + Mockito.when(pstmtMock.executeQuery()).thenReturn(rsMock); + + // Run Test + Grants grants = grantStoreUnderTest.getGrants(did, uid); + + // Verify + assertTrue(grants.getGrants().size() == 1); + verify(pstmtMock).close(); + } + + public ResultSet getMockedResultSet() throws SQLException { + ResultSet rsMock = mock(ResultSet.class); + Mockito.when(rsMock.next()).thenReturn(true).thenReturn(false); + Mockito.when(rsMock.getInt(GrantStore.SQL_ID)).thenReturn(1); + Mockito.when(rsMock.getString(GrantStore.SQL_TENANTID)).thenReturn(did); + Mockito.when(rsMock.getString(GrantStore.SQL_USERID)).thenReturn(uid); + Mockito.when(rsMock.getString(GrantStore.SQL_ROLEID)).thenReturn("Role_1"); + + return rsMock; + + } + +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/H2StoreTest.java b/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/H2StoreTest.java new file mode 100644 index 00000000..f583a302 --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/H2StoreTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.persistence; + +import java.io.File; +import java.sql.SQLException; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.aaa.api.IDMStoreUtil; +import org.opendaylight.aaa.api.IIDMStore; +import org.opendaylight.aaa.api.model.Domain; +import org.opendaylight.aaa.api.model.Grant; +import org.opendaylight.aaa.api.model.Role; +import org.opendaylight.aaa.api.model.User; + +public class H2StoreTest { + @BeforeClass + public static void start() { + File f = new File("idmlight.db.mv.db"); + if (f.exists()) { + f.delete(); + } + f = new File("idmlight.db.trace.db"); + if (f.exists()) { + f.delete(); + } + } + + @AfterClass + public static void end() { + File f = new File("idmlight.db.mv.db"); + if (f.exists()) { + f.delete(); + } + f = new File("idmlight.db.trace.db"); + if (f.exists()) { + f.delete(); + } + } + + @Before + public void before() throws StoreException, SQLException { + UserStore us = new UserStore(); + us.dbClean(); + DomainStore ds = new DomainStore(); + ds.dbClean(); + RoleStore rs = new RoleStore(); + rs.dbClean(); + GrantStore gs = new GrantStore(); + gs.dbClean(); + } + + @Test + public void testCreateDefaultDomain() throws StoreException { + Domain d = new Domain(); + Assert.assertEquals(true, d != null); + DomainStore ds = new DomainStore(); + d.setName(IIDMStore.DEFAULT_DOMAIN); + d.setEnabled(true); + d = ds.createDomain(d); + Assert.assertEquals(true, d != null); + } + + @Test + public void testCreateTempRole() throws StoreException { + Role role = H2Store.createRole("temp", "temp domain", "Temp Testing role"); + Assert.assertEquals(true, role != null); + } + + @Test + public void testCreateUser() throws StoreException { + User user = H2Store.createUser("test", "pass", "domain", "desc", "email", true, "SALT"); + Assert.assertEquals(true, user != null); + } + + @Test + public void testCreateGrant() throws StoreException { + Domain d = H2Store.createDomain("sdn", true); + Role role = H2Store.createRole("temp", "temp domain", "Temp Testing role"); + User user = H2Store.createUser("test", "pass", "domain", "desc", "email", true, "SALT"); + Grant g = H2Store.createGrant(d.getDomainid(), user.getUserid(), role.getRoleid()); + Assert.assertEquals(true, g != null); + } + + @Test + public void testUpdatingUserEmail() throws StoreException { + UserStore us = new UserStore(); + Domain d = H2Store.createDomain("sdn", true); + User user = H2Store.createUser("test", "pass", d.getDomainid(), "desc", "email", true, + "SALT"); + + user.setName("test"); + user = us.putUser(user); + Assert.assertEquals(true, user != null); + + user.setEmail("Test@Test.com"); + user = us.putUser(user); + + user = new User(); + user.setName("test"); + user.setDomainid(d.getDomainid()); + user = us.getUser(IDMStoreUtil.createUserid(user.getName(), user.getDomainid())); + + Assert.assertEquals("Test@Test.com", user.getEmail()); + } + /* + * @Test public void testCreateUserViaAPI() throws StoreException { Domain d + * = StoreBuilder.createDomain("sdn",true); + * + * User user = new User(); user.setName("Hello"); user.setPassword("Hello"); + * user.setDomainid(d.getDomainid()); UserHandler h = new UserHandler(); + * h.createUser(null, user); + * + * User u = new User(); u.setName("Hello"); u.setDomainid(d.getDomainid()); + * UserStore us = new UserStore(); u = + * us.getUser(IDMStoreUtil.createUserid(u.getName(),u.getDomainid())); + * + * Assert.assertEquals(true, u != null); } + * + * @Test public void testUpdateUserViaAPI() throws StoreException { Domain d + * = StoreBuilder.createDomain("sdn",true); + * + * User user = new User(); user.setName("Hello"); user.setPassword("Hello"); + * user.setDomainid(d.getDomainid()); UserHandler h = new UserHandler(); + * h.createUser(null, user); + * + * user.setEmail("Hello@Hello.com"); user.setPassword("Test123"); + * h.putUser(null, user, "" + user.getUserid()); + * + * UserStore us = new UserStore(); + * + * User u = new User(); u.setName("Hello"); u.setDomainid(d.getDomainid()); + * u = us.getUser(IDMStoreUtil.createUserid(u.getName(),u.getDomainid())); + * + * Assert.assertEquals("Hello@Hello.com", u.getEmail()); + * + * String hash = SHA256Calculator.getSHA256("Test123", u.getSalt()); + * Assert.assertEquals(u.getPassword(), hash); } + * + * @Test public void testUpdateUserRoleViaAPI() throws StoreException { + * Domain d = StoreBuilder.createDomain("sdn",true); Role role1 = + * StoreBuilder.createRole("temp1",d.getDomainid(),"Temp Testing role"); + * Role role2 = + * StoreBuilder.createRole("temp2",d.getDomainid(),"Temp Testing role"); + * + * User user = new User(); user.setName("Hello"); user.setPassword("Hello"); + * user.setDomainid(d.getDomainid()); + * + * UserHandler h = new UserHandler(); h.createUser(null, user); + * + * user.setEmail("Hello@Hello.com"); user.setPassword("Test123"); + * h.putUser(null, user, user.getUserid()); + * + * Grant g = new Grant(); g.setUserid(user.getUserid()); + * g.setDomainid(d.getDomainid()); g.setRoleid(role1.getRoleid()); + * GrantStore gs = new GrantStore(); g = gs.createGrant(g); + * + * Assert.assertEquals(true, g != null); Assert.assertEquals(g.getRoleid(), + * role1.getRoleid()); + * + * g = gs.deleteGrant(IDMStoreUtil.createGrantid(user.getUserid(), + * d.getDomainid(), role1.getRoleid())); g.setRoleid(role2.getRoleid()); g = + * gs.createGrant(g); + * + * Assert.assertEquals(true, g != null); Assert.assertEquals(g.getRoleid(), + * role2.getRoleid()); + * + * User u = new User(); u.setName("Hello"); u.setDomainid(d.getDomainid()); + * UserStore us = new UserStore(); u = + * us.getUser(IDMStoreUtil.createUserid(u.getName(),u.getDomainid())); + * + * Assert.assertEquals("Hello@Hello.com", u.getEmail()); + * + * String hash = SHA256Calculator.getSHA256("Test123", u.getSalt()); + * Assert.assertEquals(true, hash.equals(u.getPassword())); } + */ +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/RoleStoreTest.java b/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/RoleStoreTest.java new file mode 100644 index 00000000..37cb17a6 --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/RoleStoreTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.persistence; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.opendaylight.aaa.api.model.Roles; +import org.opendaylight.aaa.h2.persistence.RoleStore; + +public class RoleStoreTest { + + Connection connectionMock = mock(Connection.class); + private final RoleStore RoleStoreUnderTest = new RoleStore(); + + @Before + public void setup() { + RoleStoreUnderTest.dbConnection = connectionMock; + } + + @After + public void teardown() { + // dts.destroy(); + } + + @Test + public void getRolesTest() throws SQLException, Exception { + // Setup Mock Behavior + String[] tableTypes = { "TABLE" }; + Mockito.when(connectionMock.isClosed()).thenReturn(false); + DatabaseMetaData dbmMock = mock(DatabaseMetaData.class); + Mockito.when(connectionMock.getMetaData()).thenReturn(dbmMock); + ResultSet rsUserMock = mock(ResultSet.class); + Mockito.when(dbmMock.getTables(null, null, "ROLES", tableTypes)).thenReturn(rsUserMock); + Mockito.when(rsUserMock.next()).thenReturn(true); + + Statement stmtMock = mock(Statement.class); + Mockito.when(connectionMock.createStatement()).thenReturn(stmtMock); + + ResultSet rsMock = getMockedResultSet(); + Mockito.when(stmtMock.executeQuery(anyString())).thenReturn(rsMock); + + // Run Test + Roles roles = RoleStoreUnderTest.getRoles(); + + // Verify + assertTrue(roles.getRoles().size() == 1); + verify(stmtMock).close(); + + } + + public ResultSet getMockedResultSet() throws SQLException { + ResultSet rsMock = mock(ResultSet.class); + Mockito.when(rsMock.next()).thenReturn(true).thenReturn(false); + Mockito.when(rsMock.getInt(RoleStore.SQL_ID)).thenReturn(1); + Mockito.when(rsMock.getString(RoleStore.SQL_NAME)).thenReturn("RoleName_1"); + Mockito.when(rsMock.getString(RoleStore.SQL_DESCR)).thenReturn("Desc_1"); + return rsMock; + } +} diff --git a/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/UserStoreTest.java b/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/UserStoreTest.java new file mode 100644 index 00000000..e214c261 --- /dev/null +++ b/odl-aaa-moon/aaa/aaa-h2-store/src/test/java/org/opendaylight/aaa/h2/persistence/UserStoreTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.aaa.h2.persistence; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.opendaylight.aaa.api.model.Users; +import org.opendaylight.aaa.h2.persistence.UserStore; + +public class UserStoreTest { + + Connection connectionMock = mock(Connection.class); + private final UserStore userStoreUnderTest = new UserStore(); + + @Before + public void setup() { + userStoreUnderTest.dbConnection = connectionMock; + } + + @After + public void teardown() { + // dts.destroy(); + } + + @Test + public void getUsersTest() throws SQLException, Exception { + // Setup Mock Behavior + String[] tableTypes = { "TABLE" }; + Mockito.when(connectionMock.isClosed()).thenReturn(false); + DatabaseMetaData dbmMock = mock(DatabaseMetaData.class); + Mockito.when(connectionMock.getMetaData()).thenReturn(dbmMock); + ResultSet rsUserMock = mock(ResultSet.class); + Mockito.when(dbmMock.getTables(null, null, "USERS", tableTypes)).thenReturn(rsUserMock); + Mockito.when(rsUserMock.next()).thenReturn(true); + + Statement stmtMock = mock(Statement.class); + Mockito.when(connectionMock.createStatement()).thenReturn(stmtMock); + + ResultSet rsMock = getMockedResultSet(); + Mockito.when(stmtMock.executeQuery(anyString())).thenReturn(rsMock); + + // Run Test + Users users = userStoreUnderTest.getUsers(); + + // Verify + assertTrue(users.getUsers().size() == 1); + verify(stmtMock).close(); + + } + + public ResultSet getMockedResultSet() throws SQLException { + ResultSet rsMock = mock(ResultSet.class); + Mockito.when(rsMock.next()).thenReturn(true).thenReturn(false); + Mockito.when(rsMock.getInt(UserStore.SQL_ID)).thenReturn(1); + Mockito.when(rsMock.getString(UserStore.SQL_NAME)).thenReturn("Name_1"); + Mockito.when(rsMock.getString(UserStore.SQL_EMAIL)).thenReturn("Name_1@company.com"); + Mockito.when(rsMock.getString(UserStore.SQL_PASSWORD)).thenReturn("Pswd_1"); + Mockito.when(rsMock.getString(UserStore.SQL_DESCR)).thenReturn("Desc_1"); + Mockito.when(rsMock.getInt(UserStore.SQL_ENABLED)).thenReturn(1); + return rsMock; + } +} -- cgit 1.2.3-korg