Commit 6c6b77a0 authored by Julien Muchembled's avatar Julien Muchembled

Prevent ERP5 site creation if SQL databases aren't empty, add an option to force

/reviewed-on !314
parent 31d74297
......@@ -73,6 +73,7 @@ def manage_addERP5Site(self,
cmf_activity_sql_connection_string='test test',
light_install=0,
reindex=1,
sql_reset=0,
RESPONSE=None):
'''
Adds a portal instance.
......@@ -87,7 +88,8 @@ def manage_addERP5Site(self,
cmf_activity_sql_connection_string,
create_activities=create_activities,
light_install=light_install,
reindex=reindex)
reindex=reindex,
sql_reset=sql_reset)
gen.setupDefaultProperties(p,
title,
description,
......@@ -1967,43 +1969,37 @@ class ERP5Generator(PortalGenerator):
if not p.hasObject('portal_catalog'):
addTool('ERP5 Catalog', None)
if 1:
# Add Default SQL connection
if not p.hasObject('erp5_sql_connection'):
addSQLConnection = p.manage_addProduct['ZMySQLDA'].\
manage_addZMySQLConnection
addSQLConnection('erp5_sql_connection',
'ERP5 SQL Server Connection',
p.erp5_sql_connection_string)
# Add Deferred SQL Connections
if not p.hasObject('erp5_sql_deferred_connection'):
addSQLConnection = p.manage_addProduct['ZMySQLDA'].\
manage_addZMySQLConnection
addSQLConnection('erp5_sql_deferred_connection',
'ERP5 SQL Server Deferred Connection',
p.erp5_sql_deferred_connection_string,
deferred=True)
# Add Activity SQL Connections
if not p.hasObject('cmf_activity_sql_connection'):
addSQLConnection = p.manage_addProduct['CMFActivity'].\
manage_addActivityConnection
addSQLConnection('cmf_activity_sql_connection',
'CMF Activity SQL Server Connection',
p.cmf_activity_sql_connection_string)
# Warning : This transactionless connection is created with
sql_reset = kw.get('sql_reset', 0)
def addSQLConnection(id, title, **kw):
if p.hasObject(id):
return
# Warning : The transactionless connection is created with
# the activity connection string and not the catalog's because
# it's not compatible with the hot reindexing feature.
# Though, it has nothing to do with activities.
# The only difference compared to activity connection is the
# minus prepended to the connection string.
if not p.hasObject('erp5_sql_transactionless_connection'):
addSQLConnection = p.manage_addProduct['ZMySQLDA'].\
manage_addZMySQLConnection
addSQLConnection('erp5_sql_transactionless_connection',
'ERP5 Transactionless SQL Server Connection',
'-%s' % p.cmf_activity_sql_connection_string)
if id == 'erp5_sql_transactionless_connection':
connection_string = '-' + p.cmf_activity_sql_connection_string
else:
connection_string = getattr(p, id + '_string')
manage_add(id, title, connection_string, **kw)
if not sql_reset and p[id]().tables():
raise Exception("Database %r is not empty." % connection_string)
# Add Z MySQL Connections
manage_add = p.manage_addProduct['ZMySQLDA'].manage_addZMySQLConnection
addSQLConnection('erp5_sql_connection',
'ERP5 SQL Server Connection')
addSQLConnection('erp5_sql_deferred_connection',
'ERP5 SQL Server Deferred Connection',
deferred=True)
addSQLConnection('erp5_sql_transactionless_connection',
'ERP5 Transactionless SQL Server Connection')
# Add Activity SQL Connections
manage_add = p.manage_addProduct['CMFActivity'].manage_addActivityConnection
addSQLConnection('cmf_activity_sql_connection',
'CMF Activity SQL Server Connection')
# Add ERP5Form Tools
addERP5Tool(p, 'portal_selections', 'Selection Tool')
......
......@@ -97,6 +97,10 @@ label {
<label class="form-label" for="cmf_activity_sql_connection_string">CMF Activity Database</label>
<input class="form-element" name="cmf_activity_sql_connection_string" id="cmf_activity_sql_connection_string" type="text" size="40" value="test test"/>
</div>
<div>
<label class="form-label" for="sql_reset">Drop any existing table</label>
<input type="checkbox" name="sql_reset:int" value="1" id="sql_reset"/>
</div>
<div>
<p>The connection strings used for Z MySQL Database Connections are of the form:</p>
<blockquote><code>database[@host[:port]] [user [password [unix_socket]]]</code></blockquote>
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2014 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
import unittest
from Products.ERP5Type.tests.ERP5TypeTestCase import (
ERP5TypeTestCase, failed_portal_installation)
class TestERP5Site(ERP5TypeTestCase):
def getPortalName(self):
return self._testMethodName
def setUp(self):
pass
def test_00_fillSQL(self):
"""
A empty test that is run first, only to make sure that the other test
tries to create an ERP5 Site with a non-empty SQL database.
"""
super(TestERP5Site, self).setUp()
self.portal
self.assertNotIn(self.getPortalName(), failed_portal_installation)
def test_01_do_not_wipe_SQL_data_by_default(self):
"""
Unless wanted explicitely by the user, creating an ERP5 Site must fail
if the given SQL parameters give access to a database that already contains
data. This prevents existing SQL databases from being wiped mistakenly.
"""
kw = self._getSiteCreationParameterDict()
del kw['sql_reset']
self._getSiteCreationParameterDict = lambda: kw
self.assertRaisesRegexp(Exception, "not empty",
super(TestERP5Site, self).setUp)
self.assertFalse(hasattr(self, 'portal'))
self.assertIn(self.getPortalName(), failed_portal_installation)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestERP5Site))
return suite
......@@ -211,7 +211,6 @@ DateTime._parse_args = _parse_args
class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase):
"""Mixin class for ERP5 based tests.
"""
def dummy_test(self):
ZopeTestCase._print('All tests are skipped when --save option is passed '
'with --update_business_templates or without --load')
......@@ -1041,6 +1040,18 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin):
if not quiet:
ZopeTestCase._print('done (%.3fs)\n' % (time.time() - start))
def _getSiteCreationParameterDict(self):
kw = _getConnectionStringDict()
# manage_addERP5Site does not accept the following 2 arguments
for k in ('erp5_sql_deferred_connection_string',
'erp5_sql_transactionless_connection_string'):
kw.pop(k, None)
email_from_address = os.environ.get('email_from_address')
if email_from_address is not None:
kw['email_from_address'] = email_from_address
kw['sql_reset'] = 1
return kw
def setUpERP5Site(self,
business_template_list=(),
quiet=0,
......@@ -1092,23 +1103,15 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin):
if not quiet:
ZopeTestCase._print('Adding %s ERP5 Site ... ' % portal_name)
extra_constructor_kw = _getConnectionStringDict()
# manage_addERP5Site does not accept the following 2 arguments
for k in ('erp5_sql_deferred_connection_string',
'erp5_sql_transactionless_connection_string'):
extra_constructor_kw.pop(k, None)
email_from_address = os.environ.get('email_from_address')
if email_from_address is not None:
extra_constructor_kw['email_from_address'] = email_from_address
kw = self._getSiteCreationParameterDict()
factory = app.manage_addProduct['ERP5']
factory.manage_addERP5Site(portal_name,
erp5_catalog_storage=erp5_catalog_storage,
light_install=light_install,
reindex=reindex,
create_activities=create_activities,
**extra_constructor_kw )
sql = extra_constructor_kw.get('erp5_sql_connection_string')
**kw)
sql = kw.get('erp5_sql_connection_string')
if sql:
app[portal_name]._setProperty('erp5_site_global_id',
base64.standard_b64encode(sql))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment