You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

272 lines
9.5 KiB

8 years ago
10 years ago
10 years ago
  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Adapted by Nicolas Bessi. Copyright Camptocamp SA
  5. # Based on Florent Xicluna original code. Copyright Wingo SA
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. #
  20. ##############################################################################
  21. import logging
  22. import os
  23. import ConfigParser
  24. from lxml import etree
  25. from itertools import chain
  26. from openerp import api, models, fields
  27. from openerp.tools.config import config as system_base_config
  28. from .system_info import get_server_environment
  29. _logger = logging.getLogger(__name__)
  30. # Same dict as RawConfigParser._boolean_states
  31. _boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
  32. '0': False, 'no': False, 'false': False, 'off': False}
  33. try:
  34. from openerp.addons import server_environment_files
  35. _dir = os.path.dirname(server_environment_files.__file__)
  36. if not system_base_config.get('running_env', False):
  37. raise Exception(
  38. "The parameter 'running_env' has not be set neither in base "
  39. "config file option -c or in openerprc.\n"
  40. "We strongly recommend against using the rc file but instead use "
  41. "an explicit config file with this content:\n"
  42. "[options]\nrunning_env = dev"
  43. )
  44. ck_path = os.path.join(_dir, system_base_config['running_env'])
  45. if not os.path.exists(ck_path):
  46. raise Exception(
  47. "Provided server environment does not exist, "
  48. "please add a folder %s" % ck_path
  49. )
  50. except ImportError:
  51. _logger.info("ImportError raised while loading module.")
  52. _logger.debug("ImportError details:", exc_info=True)
  53. server_environment_files = False
  54. def setboolean(obj, attr, _bool=None):
  55. """Replace the attribute with a boolean."""
  56. if _bool is None:
  57. _bool = dict(_boolean_states)
  58. res = _bool[getattr(obj, attr).lower()]
  59. setattr(obj, attr, res)
  60. return res
  61. # Borrowed from MarkupSafe
  62. def _escape(s):
  63. """Convert the characters &<>'" in string s to HTML-safe sequences."""
  64. return (str(s).replace('&', '&amp;')
  65. .replace('>', '&gt;')
  66. .replace('<', '&lt;')
  67. .replace("'", '&#39;')
  68. .replace('"', '&#34;'))
  69. def _listconf(env_path):
  70. """List configuration files in a folder."""
  71. files = [os.path.join(env_path, name)
  72. for name in sorted(os.listdir(env_path))
  73. if name.endswith('.conf')]
  74. return files
  75. def _load_config():
  76. """Load the configuration and return a ConfigParser instance."""
  77. default = os.path.join(_dir, 'default')
  78. running_env = os.path.join(_dir,
  79. system_base_config['running_env'])
  80. if os.path.isdir(default):
  81. conf_files = _listconf(default) + _listconf(running_env)
  82. else:
  83. conf_files = _listconf(running_env)
  84. config_p = ConfigParser.SafeConfigParser()
  85. # options are case-sensitive
  86. config_p.optionxform = str
  87. try:
  88. config_p.read(conf_files)
  89. except Exception as e:
  90. raise Exception('Cannot read config files "%s": %s' % (conf_files, e))
  91. config_p.read(system_base_config.rcfile)
  92. config_p.remove_section('options')
  93. return config_p
  94. if server_environment_files:
  95. serv_config = _load_config()
  96. class _Defaults(dict):
  97. __slots__ = ()
  98. def __setitem__(self, key, value):
  99. def func(*a):
  100. return str(value)
  101. return dict.__setitem__(self, key, func)
  102. class ServerConfiguration(models.TransientModel):
  103. """Display server configuration."""
  104. _name = 'server.config'
  105. _conf_defaults = _Defaults()
  106. def __init__(self, pool, cr):
  107. """Add columns to model dynamically
  108. and init some properties
  109. """
  110. self._add_columns()
  111. super(ServerConfiguration, self).__init__(pool, cr)
  112. self.running_env = system_base_config['running_env']
  113. # Only show passwords in development
  114. self.show_passwords = self.running_env in ('dev',)
  115. self._arch = None
  116. self._build_osv()
  117. def _format_key(self, section, key):
  118. return '%s | %s' % (section, key)
  119. def _add_columns(self):
  120. """Add columns to model dynamically"""
  121. cols = chain(
  122. self._get_base_cols().items(),
  123. self._get_env_cols().items(),
  124. self._get_system_cols().items()
  125. )
  126. for col, value in cols:
  127. col_name = col.replace('.', '_')
  128. setattr(ServerConfiguration,
  129. col_name,
  130. fields.Char(string=col, readonly=True))
  131. self._conf_defaults[col_name] = value
  132. def _get_base_cols(self):
  133. """ Compute base fields"""
  134. res = {}
  135. for col, item in system_base_config.options.items():
  136. key = self._format_key('openerp', col)
  137. res[key] = item
  138. return res
  139. def _get_env_cols(self, sections=None):
  140. """ Compute base fields"""
  141. res = {}
  142. sections = sections if sections else serv_config.sections()
  143. for section in sections:
  144. for col, item in serv_config.items(section):
  145. key = self._format_key(section, col)
  146. res[key] = item
  147. return res
  148. def _get_system_cols(self):
  149. """ Compute system fields"""
  150. res = {}
  151. for col, item in get_server_environment():
  152. key = self._format_key('system', col)
  153. res[key] = item
  154. return res
  155. def _group(self, items):
  156. """Return an XML chunk which represents a group of fields."""
  157. names = []
  158. for key in sorted(items):
  159. names.append(key.replace('.', '_'))
  160. return ('<group col="2" colspan="4">' +
  161. ''.join(['<field name="%s" readonly="1"/>' %
  162. _escape(name) for name in names]) +
  163. '</group>')
  164. def _build_osv(self):
  165. """Build the view for the current configuration."""
  166. arch = ('<?xml version="1.0" encoding="utf-8"?>'
  167. '<form string="Configuration Form">'
  168. '<notebook colspan="4">')
  169. # OpenERP server configuration
  170. rcfile = system_base_config.rcfile
  171. items = self._get_base_cols()
  172. arch += '<page string="OpenERP">'
  173. arch += '<separator string="%s" colspan="4"/>' % _escape(rcfile)
  174. arch += self._group(items)
  175. arch += '<separator colspan="4"/></page>'
  176. arch += '<page string="Environment based configurations">'
  177. for section in sorted(serv_config.sections()):
  178. items = self._get_env_cols(sections=[section])
  179. arch += '<separator string="[%s]" colspan="4"/>' % _escape(section)
  180. arch += self._group(items)
  181. arch += '<separator colspan="4"/></page>'
  182. # System information
  183. arch += '<page string="System">'
  184. arch += '<separator string="Server Environment" colspan="4"/>'
  185. arch += self._group(self._get_system_cols())
  186. arch += '<separator colspan="4"/></page>'
  187. arch += '</notebook></form>'
  188. self._arch = etree.fromstring(arch)
  189. def fields_view_get(self, cr, uid, view_id=None, view_type='form',
  190. context=None, toolbar=False, submenu=False):
  191. """Overwrite the default method to render the custom view."""
  192. res = super(ServerConfiguration, self).fields_view_get(cr, uid,
  193. view_id,
  194. view_type,
  195. context,
  196. toolbar)
  197. if view_type == 'form':
  198. arch_node = self._arch
  199. xarch, xfields = self._view_look_dom_arch(cr, uid,
  200. arch_node,
  201. view_id,
  202. context=context)
  203. res['arch'] = xarch
  204. res['fields'] = xfields
  205. return res
  206. @api.model
  207. def _is_secret(self, key):
  208. """
  209. This method is intended to be inherited to defined which keywords
  210. should be secret.
  211. :return: list of secret keywords
  212. """
  213. secret_keys = ['passw', 'key', 'secret', 'token']
  214. return any(secret_key in key for secret_key in secret_keys)
  215. def default_get(self, cr, uid, fields_list, context=None):
  216. res = {}
  217. current_user = self.pool['res.users'].browse(
  218. cr, uid, uid, context=context)
  219. if not current_user.has_group(
  220. 'server_environment.has_server_configuration_access'):
  221. return res
  222. for key in self._conf_defaults:
  223. if not self.show_passwords and self._is_secret(
  224. cr, uid, context=context, key=key):
  225. res[key] = '**********'
  226. else:
  227. res[key] = self._conf_defaults[key]()
  228. return res