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 nexedi/erp5!314
parent 31d74297
...@@ -73,6 +73,7 @@ def manage_addERP5Site(self, ...@@ -73,6 +73,7 @@ def manage_addERP5Site(self,
cmf_activity_sql_connection_string='test test', cmf_activity_sql_connection_string='test test',
light_install=0, light_install=0,
reindex=1, reindex=1,
sql_reset=0,
RESPONSE=None): RESPONSE=None):
''' '''
Adds a portal instance. Adds a portal instance.
...@@ -87,7 +88,8 @@ def manage_addERP5Site(self, ...@@ -87,7 +88,8 @@ def manage_addERP5Site(self,
cmf_activity_sql_connection_string, cmf_activity_sql_connection_string,
create_activities=create_activities, create_activities=create_activities,
light_install=light_install, light_install=light_install,
reindex=reindex) reindex=reindex,
sql_reset=sql_reset)
gen.setupDefaultProperties(p, gen.setupDefaultProperties(p,
title, title,
description, description,
...@@ -1967,43 +1969,37 @@ class ERP5Generator(PortalGenerator): ...@@ -1967,43 +1969,37 @@ class ERP5Generator(PortalGenerator):
if not p.hasObject('portal_catalog'): if not p.hasObject('portal_catalog'):
addTool('ERP5 Catalog', None) addTool('ERP5 Catalog', None)
if 1: sql_reset = kw.get('sql_reset', 0)
# Add Default SQL connection def addSQLConnection(id, title, **kw):
if not p.hasObject('erp5_sql_connection'): if p.hasObject(id):
addSQLConnection = p.manage_addProduct['ZMySQLDA'].\ return
manage_addZMySQLConnection # Warning : The transactionless connection is created with
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
# the activity connection string and not the catalog's because # the activity connection string and not the catalog's because
# it's not compatible with the hot reindexing feature. # it's not compatible with the hot reindexing feature.
# Though, it has nothing to do with activities. # Though, it has nothing to do with activities.
# The only difference compared to activity connection is the # The only difference compared to activity connection is the
# minus prepended to the connection string. # minus prepended to the connection string.
if not p.hasObject('erp5_sql_transactionless_connection'): if id == 'erp5_sql_transactionless_connection':
addSQLConnection = p.manage_addProduct['ZMySQLDA'].\ connection_string = '-' + p.cmf_activity_sql_connection_string
manage_addZMySQLConnection else:
addSQLConnection('erp5_sql_transactionless_connection', connection_string = getattr(p, id + '_string')
'ERP5 Transactionless SQL Server Connection', manage_add(id, title, connection_string, **kw)
'-%s' % p.cmf_activity_sql_connection_string) 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 # Add ERP5Form Tools
addERP5Tool(p, 'portal_selections', 'Selection Tool') addERP5Tool(p, 'portal_selections', 'Selection Tool')
......
...@@ -97,6 +97,10 @@ label { ...@@ -97,6 +97,10 @@ label {
<label class="form-label" for="cmf_activity_sql_connection_string">CMF Activity Database</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"/> <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>
<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> <div>
<p>The connection strings used for Z MySQL Database Connections are of the form:</p> <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> <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 ...@@ -211,7 +211,6 @@ DateTime._parse_args = _parse_args
class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase): class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase):
"""Mixin class for ERP5 based tests. """Mixin class for ERP5 based tests.
""" """
def dummy_test(self): def dummy_test(self):
ZopeTestCase._print('All tests are skipped when --save option is passed ' ZopeTestCase._print('All tests are skipped when --save option is passed '
'with --update_business_templates or without --load') 'with --update_business_templates or without --load')
...@@ -1041,6 +1040,18 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin): ...@@ -1041,6 +1040,18 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin):
if not quiet: if not quiet:
ZopeTestCase._print('done (%.3fs)\n' % (time.time() - start)) 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, def setUpERP5Site(self,
business_template_list=(), business_template_list=(),
quiet=0, quiet=0,
...@@ -1092,23 +1103,15 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin): ...@@ -1092,23 +1103,15 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin):
if not quiet: if not quiet:
ZopeTestCase._print('Adding %s ERP5 Site ... ' % portal_name) ZopeTestCase._print('Adding %s ERP5 Site ... ' % portal_name)
extra_constructor_kw = _getConnectionStringDict() kw = self._getSiteCreationParameterDict()
# 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
factory = app.manage_addProduct['ERP5'] factory = app.manage_addProduct['ERP5']
factory.manage_addERP5Site(portal_name, factory.manage_addERP5Site(portal_name,
erp5_catalog_storage=erp5_catalog_storage, erp5_catalog_storage=erp5_catalog_storage,
light_install=light_install, light_install=light_install,
reindex=reindex, reindex=reindex,
create_activities=create_activities, create_activities=create_activities,
**extra_constructor_kw ) **kw)
sql = extra_constructor_kw.get('erp5_sql_connection_string') sql = kw.get('erp5_sql_connection_string')
if sql: if sql:
app[portal_name]._setProperty('erp5_site_global_id', app[portal_name]._setProperty('erp5_site_global_id',
base64.standard_b64encode(sql)) 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