2 * This document is a part of the source code and related artifacts
\r
3 * for CollectionSpace, an open source collections management system
\r
4 * for museums and related institutions:
\r
6 * http://www.collectionspace.org
\r
7 * http://wiki.collectionspace.org
\r
9 * Copyright 2009 University of California at Berkeley
\r
11 * Licensed under the Educational Community License (ECL), Version 2.0.
\r
12 * You may not use this file except in compliance with this License.
\r
14 * You may obtain a copy of the ECL 2.0 License at
\r
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
\r
18 package org.collectionspace.services.report.nuxeo;
\r
20 import java.sql.Connection;
\r
21 import java.sql.SQLException;
\r
22 import java.sql.Statement;
\r
23 import java.util.List;
\r
25 import org.collectionspace.services.common.ServiceMain;
\r
26 import org.collectionspace.services.common.api.Tools;
\r
27 import org.collectionspace.services.common.init.IInitHandler;
\r
28 import org.collectionspace.services.common.init.InitHandler;
\r
29 import org.collectionspace.services.common.storage.DatabaseProductType;
\r
30 import org.collectionspace.services.common.storage.JDBCTools;
\r
32 import org.collectionspace.services.config.service.InitHandler.Params.Field;
\r
33 import org.collectionspace.services.config.service.InitHandler.Params.Property;
\r
34 import org.collectionspace.services.config.service.ServiceBindingType;
\r
36 import org.slf4j.Logger;
\r
37 import org.slf4j.LoggerFactory;
\r
40 * ReportPostInitHandler, post-init action to add grant reader access to DB
\r
42 * In the configuration file, looks for a single Field declaration
\r
43 * with a param value that has the name of the reader account/role.
\r
44 * If not specified, it will assume 'reader';
\r
46 * $LastChangedRevision: 5103 $
\r
47 * $LastChangedDate: 2011-06-23 16:50:06 -0700 (Thu, 23 Jun 2011) $
\r
49 public class ReportPostInitHandler extends InitHandler implements IInitHandler {
\r
51 final Logger logger = LoggerFactory.getLogger(ReportPostInitHandler.class);
\r
52 public static final String DATABASE_SELECT_PRIVILEGE_NAME = "SELECT";
\r
54 // Currently retained for backward compatibility
\r
55 public static final String READER_ROLE_NAME_KEY = "readerRoleName";
\r
56 public static final String DEFAULT_READER_ROLE_NAME = "reader" + ServiceMain.getInstance().getCspaceInstanceId();
\r
57 private String readerRoleName = DEFAULT_READER_ROLE_NAME;
\r
59 public static final String REPORTER_ROLE_NAME_KEY = "reporterRoleName";
\r
60 public static final String DEFAULT_REPORTER_ROLE_NAME = "reporter" + ServiceMain.getInstance().getCspaceInstanceId();
\r
61 private String reporterRoleName = DEFAULT_REPORTER_ROLE_NAME;
\r
63 /** See the class javadoc for this class: it shows the syntax supported in the configuration params.
\r
66 public void onRepositoryInitialized(String dataSourceName,
\r
67 String repositoryName,
\r
68 String cspaceInstanceId,
\r
69 ServiceBindingType sbt,
\r
70 List<Field> fields,
\r
71 List<Property> propertyList) throws Exception {
\r
72 //Check for existing privileges, and if not there, grant them
\r
73 for(Property prop : propertyList) {
\r
74 if(REPORTER_ROLE_NAME_KEY.equals(prop.getKey())) {
\r
75 String value = prop.getValue();
\r
76 if(Tools.notEmpty(value) && !DEFAULT_REPORTER_ROLE_NAME.equals(value)){
\r
77 reporterRoleName = value + ServiceMain.getInstance().getCspaceInstanceId();
\r
78 logger.debug("ReportPostInitHandler: overriding reporterRoleName default value to use: "
\r
82 // FIXME: Currently retained for backward compatibility; remove this block when appropriate
\r
83 if(READER_ROLE_NAME_KEY.equals(prop.getKey())) {
\r
84 String value = prop.getValue();
\r
85 if(Tools.notEmpty(value) && !DEFAULT_READER_ROLE_NAME.equals(value)){
\r
86 readerRoleName = value + ServiceMain.getInstance().getCspaceInstanceId();
\r
87 logger.debug("ReportPostInitHandler: overriding readerRoleName default value to use: "
\r
92 String privilegeName = DATABASE_SELECT_PRIVILEGE_NAME;
\r
93 grantPrivilegeToDatabaseRole(dataSourceName, repositoryName, cspaceInstanceId, privilegeName, reporterRoleName);
\r
94 // FIXME: Currently retained for backward compatibility; remove the following line when appropriate
\r
95 grantPrivilegeToDatabaseRole(dataSourceName, repositoryName, cspaceInstanceId, privilegeName, readerRoleName);
\r
98 // FIXME: This method might be refactorable / movable to the
\r
99 // org.collectionspace.services.common.storage.JDBCTools class.
\r
100 // If so, any database privilege constants here should be moved with it.
\r
101 private void grantPrivilegeToDatabaseRole(String dataSourceName, String repositoryName, String cspaceInstanceId,
\r
102 String privilegeName, String roleName) {
\r
103 Connection conn = null;
\r
104 Statement stmt = null;
\r
107 DatabaseProductType databaseProductType = JDBCTools.getDatabaseProductType(dataSourceName, repositoryName,
\r
109 if (databaseProductType == DatabaseProductType.MYSQL) {
\r
110 // Nothing to do: MYSQL already does wildcard grants in init_db.sql
\r
111 } else if(databaseProductType != DatabaseProductType.POSTGRESQL) {
\r
112 throw new Exception("Unrecognized database system " + databaseProductType);
\r
114 String databaseName = JDBCTools.getDatabaseName(repositoryName, cspaceInstanceId);
\r
115 conn = JDBCTools.getConnection(dataSourceName, databaseName);
\r
116 stmt = conn.createStatement();
\r
117 // FIXME: Check first that role exists before executing the grant
\r
118 sql = String.format("GRANT %s ON ALL TABLES IN SCHEMA public TO %s", privilegeName, roleName);
\r
122 } catch (SQLException sqle) {
\r
123 SQLException tempException = sqle;
\r
124 while (null != tempException) { // SQLExceptions can be chained. Loop to log all.
\r
125 logger.debug("SQL Exception: " + sqle.getLocalizedMessage());
\r
126 tempException = tempException.getNextException();
\r
128 logger.debug("ReportPostInitHandler: SQL problem in executeQuery: ", sqle);
\r
129 } catch (Throwable e) {
\r
130 logger.debug("ReportPostInitHandler: problem checking/adding grant for reader: "+readerRoleName+") SQL: "+sql+" ERROR: "+e);
\r
133 if (conn != null) {
\r
136 if (stmt != null) {
\r
139 } catch (SQLException sqle) {
\r
140 logger.debug("SQL Exception closing statement/connection in executeQuery: " + sqle.getLocalizedMessage());
\r