From 40fdb08a7db13c52c49026f8425bc40dac5a7696 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 19 Mar 2014 09:53:43 +0100 Subject: [PATCH 01/13] [WIP] base_import_module bzr revid: fme@openerp.com-20140319085343-zkee3rmqc9dzpa7h --- addons/base_import_module/__init__.py | 2 + addons/base_import_module/__openerp__.py | 21 ++++++++ .../controllers/__init__.py | 1 + addons/base_import_module/controllers/main.py | 38 ++++++++++++++ addons/base_import_module/models/__init__.py | 2 + addons/base_import_module/models/ir_module.py | 49 +++++++++++++++++++ 6 files changed, 113 insertions(+) create mode 100644 addons/base_import_module/__init__.py create mode 100644 addons/base_import_module/__openerp__.py create mode 100644 addons/base_import_module/controllers/__init__.py create mode 100644 addons/base_import_module/controllers/main.py create mode 100644 addons/base_import_module/models/__init__.py create mode 100644 addons/base_import_module/models/ir_module.py diff --git a/addons/base_import_module/__init__.py b/addons/base_import_module/__init__.py new file mode 100644 index 00000000000..9f86759e32b --- /dev/null +++ b/addons/base_import_module/__init__.py @@ -0,0 +1,2 @@ +import controllers +import models diff --git a/addons/base_import_module/__openerp__.py b/addons/base_import_module/__openerp__.py new file mode 100644 index 00000000000..ba37462642c --- /dev/null +++ b/addons/base_import_module/__openerp__.py @@ -0,0 +1,21 @@ +{ + 'name': 'Base import module', + 'description': """ +Import a custom data module +=========================== + +This module allows authorized users to import a custom data module (.xml files and static assests) +for customization purpose. +""", + 'category': 'Uncategorized', + 'website': 'http://www.openerp.com', + 'author': 'OpenERP SA', + 'depends': ['web'], + 'installable': True, + 'auto_install': False, + 'data': [], + 'css': [], + 'js': [], + 'qweb': [], + 'test': [], +} diff --git a/addons/base_import_module/controllers/__init__.py b/addons/base_import_module/controllers/__init__.py new file mode 100644 index 00000000000..8ee9bae18d9 --- /dev/null +++ b/addons/base_import_module/controllers/__init__.py @@ -0,0 +1 @@ +import main diff --git a/addons/base_import_module/controllers/main.py b/addons/base_import_module/controllers/main.py new file mode 100644 index 00000000000..6ddd0158b4d --- /dev/null +++ b/addons/base_import_module/controllers/main.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +import os +import zipfile +from os.path import join as opj + +import openerp +from openerp.http import Controller, route, request + +MAX_FILE_SIZE = 100 * 1024 * 1024 # in megabytes + +class ImportModule(Controller): + + @route('/base_import_module/upload', type='http', auth='none') + def upload(self, mod_file=None, **kw): + assert request.db # TODO: custom ensure_db? + request.uid = openerp.SUPERUSER_ID # TODO: proper security + + imm = request.registry['ir.module.module'] + + if not mod_file: + raise Exception("No file sent.") + if not zipfile.is_zipfile(mod_file): + raise Exception("Not a zipfile.") + + with zipfile.ZipFile(mod_file, "r") as z: + for zf in z.filelist: + if zf.file_size > MAX_FILE_SIZE: + raise Exception("File %r exceed maximum allowed file size" % zf.filename) + + with openerp.tools.osutil.tempdir() as module_dir: + z.extractall(module_dir) + dirs = [d for d in os.listdir(module_dir) if os.path.isdir(opj(module_dir, d))] + for mod_name in dirs: + # assert mod_name.startswith('theme_') + path = opj(module_dir, mod_name) + imm.import_module(request.cr, request.uid, mod_name, path, context=request.context) + return 'ok' + diff --git a/addons/base_import_module/models/__init__.py b/addons/base_import_module/models/__init__.py new file mode 100644 index 00000000000..a28c82fe5ba --- /dev/null +++ b/addons/base_import_module/models/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +import ir_module diff --git a/addons/base_import_module/models/ir_module.py b/addons/base_import_module/models/ir_module.py new file mode 100644 index 00000000000..be03067972b --- /dev/null +++ b/addons/base_import_module/models/ir_module.py @@ -0,0 +1,49 @@ +import logging +from os.path import join as opj + +import openerp +from openerp.osv import osv, fields +from openerp.tools import convert_file + +_logger = logging.getLogger(__name__) + +class view(osv.osv): + _inherit = "ir.module.module" + _columns = { + 'is_theme': fields.boolean('Theme'), + } + _defaults = { + 'is_theme': False, + } + + def import_module(self, cr, uid, module, path, context=None): + known_mods = self.browse(cr, uid, self.search(cr, uid, [])) + known_mods_names = dict([(m.name, m) for m in known_mods]) + + mod = known_mods_names.get(module) + terp = openerp.modules.load_information_from_description_file(module, mod_path=path) + values = self.get_values_from_terp(terp) + + unmet_dependencies = set(terp['depends']).difference(known_mods_names.keys()) + if unmet_dependencies: + raise Exception("Unmet module dependencies: %s" % ', '.join(unmet_dependencies)) + + if mod: + self.write(cr, uid, mod.id, values) + mode = 'update' + else: + assert terp.get('installable', True), "Module not installable" + self.create(cr, uid, dict(name=module, state='uninstalled', **values)) + mode = 'init' + + for kind in ['data', 'init_xml', 'update_xml']: + for filename in terp[kind]: + _logger.info("module %s: loading %s", module, filename) + noupdate = False + if filename.endswith('.csv') and kind in ('init', 'init_xml'): + noupdate = True + pathname = opj(path, filename) + idref = {} + convert_file(cr, module, filename, idref, mode=mode, noupdate=noupdate, kind=kind, pathname=pathname) + + return True From 5d107cfaa0946f81a7e584681467ac0d0f363272 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 20 Mar 2014 15:33:46 +0100 Subject: [PATCH 02/13] [IMP] static file injected in ir.attachment bzr revid: fme@openerp.com-20140320143346-nimxg7c61lm1253x --- addons/base_import_module/models/ir_module.py | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/addons/base_import_module/models/ir_module.py b/addons/base_import_module/models/ir_module.py index be03067972b..318af923032 100644 --- a/addons/base_import_module/models/ir_module.py +++ b/addons/base_import_module/models/ir_module.py @@ -1,20 +1,16 @@ import logging +import os +import sys from os.path import join as opj import openerp -from openerp.osv import osv, fields +from openerp.osv import osv from openerp.tools import convert_file _logger = logging.getLogger(__name__) class view(osv.osv): _inherit = "ir.module.module" - _columns = { - 'is_theme': fields.boolean('Theme'), - } - _defaults = { - 'is_theme': False, - } def import_module(self, cr, uid, module, path, context=None): known_mods = self.browse(cr, uid, self.search(cr, uid, [])) @@ -46,4 +42,25 @@ class view(osv.osv): idref = {} convert_file(cr, module, filename, idref, mode=mode, noupdate=noupdate, kind=kind, pathname=pathname) + path_static = opj(path, 'static') + if os.path.isdir(path_static): + for root, _, files in os.walk(path_static): + for static_file in files: + full_path = opj(root, static_file) + with open(full_path, 'r') as fp: + data = fp.read().encode('base64') + url_path = full_path.split(path)[1].replace(os.path.sep, '/') + url_path = url_path.decode(sys.getfilesystemencoding()) + filename = os.path.split(url_path)[1] + values = dict( + name=filename, + datas_fname=filename, + url=url_path, + res_model='ir.ui.view', + type='binary', + datas=data, + ) + self.pool['ir.attachment'].create(cr, uid, values, context=context) + return True + From 9285813da9ea83853d6524395677ad4f40b76e10 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Mon, 24 Mar 2014 16:14:47 +0100 Subject: [PATCH 03/13] [IMP] website images: only checksum ir.attachment for empty urls bzr revid: fme@openerp.com-20140324151447-a3mkncjh0b7k16hg --- addons/website/models/website.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/website/models/website.py b/addons/website/models/website.py index 1a541865987..ca39c9249eb 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -574,7 +574,7 @@ class ir_attachment(osv.osv): def _compute_checksum(self, attachment_dict): if attachment_dict.get('res_model') == 'ir.ui.view'\ - and not attachment_dict.get('res_id')\ + and not attachment_dict.get('res_id') and not attachment_dict.get('url')\ and attachment_dict.get('type', 'binary') == 'binary'\ and attachment_dict.get('datas'): return hashlib.new('sha1', attachment_dict['datas']).hexdigest() From 5e484ae892efc9a45ae66a01ac32d4fce193b4d7 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Mon, 24 Mar 2014 16:17:11 +0100 Subject: [PATCH 04/13] [IMP] Properly import files bzr revid: fme@openerp.com-20140324151711-89mfg14573dpnh0p --- addons/base_import_module/models/ir_module.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/addons/base_import_module/models/ir_module.py b/addons/base_import_module/models/ir_module.py index 318af923032..18e60f858da 100644 --- a/addons/base_import_module/models/ir_module.py +++ b/addons/base_import_module/models/ir_module.py @@ -43,13 +43,14 @@ class view(osv.osv): convert_file(cr, module, filename, idref, mode=mode, noupdate=noupdate, kind=kind, pathname=pathname) path_static = opj(path, 'static') + ir_attach = self.pool['ir.attachment'] if os.path.isdir(path_static): for root, _, files in os.walk(path_static): for static_file in files: full_path = opj(root, static_file) with open(full_path, 'r') as fp: data = fp.read().encode('base64') - url_path = full_path.split(path)[1].replace(os.path.sep, '/') + url_path = '/%s%s' % (module, full_path.split(path)[1].replace(os.path.sep, '/')) url_path = url_path.decode(sys.getfilesystemencoding()) filename = os.path.split(url_path)[1] values = dict( @@ -60,7 +61,11 @@ class view(osv.osv): type='binary', datas=data, ) - self.pool['ir.attachment'].create(cr, uid, values, context=context) + att_id = ir_attach.search(cr, uid, [('url', '=', url_path), ('type', '=', 'binary'), ('res_model', '=', 'ir.ui.view')], context=context) + if att_id: + ir_attach.write(cr, uid, att_id, values, context=context) + else: + ir_attach.create(cr, uid, values, context=context) return True From bb8b7ea2d97bec32a1b78d1361ad51160f326344 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Mon, 24 Mar 2014 16:17:28 +0100 Subject: [PATCH 05/13] [ADD] website ir_http: serve binary ir.attchments with urls bzr revid: fme@openerp.com-20140324151728-hpegewvf3b38ndyi --- addons/website/models/ir_http.py | 35 +++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 47c0853d6be..a7c066145c1 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- +import datetime +import hashlib import logging +import mimetypes import re import traceback - import werkzeug import werkzeug.routing @@ -94,9 +96,40 @@ class ir_http(orm.AbstractModel): if path != request.httprequest.path: return werkzeug.utils.redirect(path) + def _serve_attachment(self): + domain = [('type', '=', 'binary'), ('url', '=', request.httprequest.path)] + attach = self.pool['ir.attachment'].search_read(request.cr, request.uid, domain, ['__last_update', 'datas', 'datas_fname'], context=request.context) + if attach: + wdate = attach[0]['__last_update'] + datas = attach[0]['datas'] + fname = attach[0]['datas_fname'] + response = werkzeug.wrappers.Response() + server_format = openerp.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT + try: + response.last_modified = datetime.datetime.strptime(wdate, server_format + '.%f') + except ValueError: + # just in case we have a timestamp without microseconds + response.last_modified = datetime.datetime.strptime(wdate, server_format) + + response.set_etag(hashlib.sha1(datas).hexdigest()) + response.make_conditional(request.httprequest) + + if response.status_code == 304: + return response + + guessed_mimetype = mimetypes.guess_type(fname) + response.mimetype = guessed_mimetype[0] or 'application/octet-stream' + response.set_data(datas.decode('base64')) + return response + def _handle_exception(self, exception=None, code=500): if isinstance(exception, werkzeug.exceptions.HTTPException) and hasattr(exception, 'response') and exception.response: return exception.response + + attach = self._serve_attachment() + if attach: + return attach + if getattr(request, 'website_enabled', False) and request.website: values = dict( exception=exception, From 0fe55dddc1e051bedbe1a72482862622e49b4c9f Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Tue, 25 Mar 2014 17:04:13 +0100 Subject: [PATCH 06/13] [IMP] Added a mimetype field in ir.attachment bzr revid: fme@openerp.com-20140325160413-jvxjii6rbqcrjxor --- addons/website/models/ir_http.py | 7 ++----- addons/website/models/website.py | 13 ++++++++++++- addons/website/static/src/js/website.editor.js | 3 ++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index a7c066145c1..f173b3bee38 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -2,7 +2,6 @@ import datetime import hashlib import logging -import mimetypes import re import traceback import werkzeug @@ -98,11 +97,10 @@ class ir_http(orm.AbstractModel): def _serve_attachment(self): domain = [('type', '=', 'binary'), ('url', '=', request.httprequest.path)] - attach = self.pool['ir.attachment'].search_read(request.cr, request.uid, domain, ['__last_update', 'datas', 'datas_fname'], context=request.context) + attach = self.pool['ir.attachment'].search_read(request.cr, request.uid, domain, ['__last_update', 'datas', 'mimetype'], context=request.context) if attach: wdate = attach[0]['__last_update'] datas = attach[0]['datas'] - fname = attach[0]['datas_fname'] response = werkzeug.wrappers.Response() server_format = openerp.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT try: @@ -117,8 +115,7 @@ class ir_http(orm.AbstractModel): if response.status_code == 304: return response - guessed_mimetype = mimetypes.guess_type(fname) - response.mimetype = guessed_mimetype[0] or 'application/octet-stream' + response.mimetype = attach[0]['mimetype'] response.set_data(datas.decode('base64')) return response diff --git a/addons/website/models/website.py b/addons/website/models/website.py index ca39c9249eb..64a2d7b255c 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -4,6 +4,7 @@ import inspect import itertools import logging import math +import mimetypes import re import urlparse @@ -553,7 +554,7 @@ class ir_attachment(osv.osv): def _website_url_get(self, cr, uid, ids, name, arg, context=None): result = {} for attach in self.browse(cr, uid, ids, context=context): - if attach.type == 'url': + if attach.url: result[attach.id] = attach.url else: result[attach.id] = urlplus('/website/image', { @@ -600,17 +601,27 @@ class ir_attachment(osv.osv): 'website_url': fields.function(_website_url_get, string="Attachment URL", type='char'), 'datas_big': fields.function (_datas_big, type='binary', store=True, string="Resized file content"), + 'mimetype': fields.char('Mime Type', readonly=True), } + def _add_mimetype_if_needed(self, values): + if values.get('datas_fname'): + values['mimetype'] = mimetypes.guess_type(values.get('datas_fname'))[0] or 'application/octet-stream' + def create(self, cr, uid, values, context=None): chk = self._compute_checksum(values) if chk: match = self.search(cr, uid, [('datas_checksum', '=', chk)], context=context) if match: return match[0] + self._add_mimetype_if_needed(values) return super(ir_attachment, self).create( cr, uid, values, context=context) + def write(self, cr, uid, ids, values, context=None): + self._add_mimetype_if_needed(values) + return super(ir_attachment, self).write(cr, uid, ids, values, context=context) + def try_remove(self, cr, uid, ids, context=None): """ Removes a web-based image attachment if it is used by no view (template) diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c89bf9ec2fb..24c97bce311 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -1500,7 +1500,8 @@ args: [], kwargs: { fields: ['name', 'website_url'], - domain: [['res_model', '=', 'ir.ui.view']], + domain: [['res_model', '=', 'ir.ui.view'], '|', + ['mimetype', '=', false], ['mimetype', '=like', 'image/%']], order: 'id desc', context: website.get_context(), } From 0dd65c6af887c737fd87d0255a19d97e75361b40 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 26 Mar 2014 14:33:19 +0100 Subject: [PATCH 07/13] [ADD] deploy script bzr revid: fme@openerp.com-20140326133319-sp8lcvujq7uy55zd --- .../bin/oe_module_deploy.py | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100755 addons/base_import_module/bin/oe_module_deploy.py diff --git a/addons/base_import_module/bin/oe_module_deploy.py b/addons/base_import_module/bin/oe_module_deploy.py new file mode 100755 index 00000000000..d57f589901a --- /dev/null +++ b/addons/base_import_module/bin/oe_module_deploy.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +import argparse +import os +import sys +import tempfile +import urllib +import urllib2 +import zipfile + +def deploy_module(module_path, url, login, password, db=None): + if url.endswith('/'): + url = url[:-1] + module_file = zip_module(module_path) + cookie = authenticate(url, login, password, db) + upload_module(url, module_file, cookie) + +def upload_module(server, module_file, cookie): + pass + +def authenticate(server, login, password, db): + if db: + args = dict(db=db, login=login, key=password) + url = server + '/login?' + urllib.urlencode(args) + req = urllib2.Request(url) + else: + url = server + '/web/login' + args = dict(login=login, password=password) + req = urllib2.Request(url, urllib.urlencode(args)) + response = urllib2.urlopen(req) + if response.code != 200: + raise Exception("Could not authenticate to OpenERP server %r" % server) + cookie = response.headers.get('Set-Cookie') + return cookie + +def zip_module(path): + path = os.path.abspath(path) + if not os.path.isdir(path): + raise Exception("Could not find module directory %r" % path) + container, module_name = os.path.split(path) + temp = tempfile.mktemp(suffix='.zip') + temp = '/tmp/1/test.zip' + with zipfile.ZipFile(temp, 'w') as zfile: + for root, dirs, files in os.walk(path): + for file in files: + file_path = os.path.join(root, file) + zfile.write(file_path, file_path.split(container).pop()) + return temp + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Deploy a module on an OpenERP server.') + parser.add_argument('path', help="Path of the module to deploy") + parser.add_argument('--url', dest='url', help='Url of the server (default=http://localhost:8069)', default="http://localhost:8069") + parser.add_argument('--database', dest='database', help='Database to use if server does not use db-filter.') + parser.add_argument('--login', dest='login', default="admin", help='Login (default=admin)') + parser.add_argument('--password', dest='password', default="admin", help='Password (default=admin)') + if len(sys.argv) == 1: + parser.print_help() + sys.exit(1) + args = parser.parse_args() + deploy_module(args.path, args.url, args.login, args.password, args.database) + # try: + # deploy_module(args.path, args.url, args.login, args.password, args.database) + # except Exception, e: + # print(e) + # sys.exit(1) From 62a5632aec7c14a094164862f8bc2f47060a7943 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 26 Mar 2014 16:08:42 +0100 Subject: [PATCH 08/13] [IMP] Use requests for http requests. python does not provide multipart encoding bzr revid: fme@openerp.com-20140326150842-h33yuiwsnrm8gmbk --- .../bin/oe_module_deploy.py | 82 ++++++++++++------- addons/base_import_module/controllers/main.py | 28 +++++-- 2 files changed, 75 insertions(+), 35 deletions(-) diff --git a/addons/base_import_module/bin/oe_module_deploy.py b/addons/base_import_module/bin/oe_module_deploy.py index d57f589901a..863d7875b40 100755 --- a/addons/base_import_module/bin/oe_module_deploy.py +++ b/addons/base_import_module/bin/oe_module_deploy.py @@ -3,34 +3,58 @@ import argparse import os import sys import tempfile -import urllib -import urllib2 import zipfile + +try: + import requests +except ImportError: + # no multipart encoding in stdlib and this script is temporary + sys.exit("This script requires the 'requests' module. ( pip install requests )") + +session = requests.session() + def deploy_module(module_path, url, login, password, db=None): if url.endswith('/'): url = url[:-1] + authenticate(url, login, password, db) + check_import(url) module_file = zip_module(module_path) - cookie = authenticate(url, login, password, db) - upload_module(url, module_file, cookie) + try: + return upload_module(url, module_file) + finally: + os.remove(module_file) -def upload_module(server, module_file, cookie): - pass +def check_import(server): + url = server +'/base_import_module/check' + res = session.get(url) + if res.status_code == 404: + raise Exception("The server %r does not have the 'base_import_module' installed." % server) + elif res.status_code != 200: + raise Exception("Server %r returned %s http error.", (server, res.status_code)) + +def upload_module(server, module_file): + print("Uploading module file...") + url = server + '/base_import_module/upload' + files = dict(mod_file=open(module_file, 'rb')) + res = session.post(url, files=files) + if res.status_code != 200: + raise Exception("Could not authenticate on server %r" % server) + return res.text def authenticate(server, login, password, db): + print("Connecting to server %r" % server) + print("Waiting for server authentication...") if db: + url = server + '/login' args = dict(db=db, login=login, key=password) - url = server + '/login?' + urllib.urlencode(args) - req = urllib2.Request(url) + res = session.get(url, params=args) else: url = server + '/web/login' args = dict(login=login, password=password) - req = urllib2.Request(url, urllib.urlencode(args)) - response = urllib2.urlopen(req) - if response.code != 200: + res = session.post(url, args) + if res.status_code != 200: raise Exception("Could not authenticate to OpenERP server %r" % server) - cookie = response.headers.get('Set-Cookie') - return cookie def zip_module(path): path = os.path.abspath(path) @@ -38,13 +62,17 @@ def zip_module(path): raise Exception("Could not find module directory %r" % path) container, module_name = os.path.split(path) temp = tempfile.mktemp(suffix='.zip') - temp = '/tmp/1/test.zip' - with zipfile.ZipFile(temp, 'w') as zfile: - for root, dirs, files in os.walk(path): - for file in files: - file_path = os.path.join(root, file) - zfile.write(file_path, file_path.split(container).pop()) - return temp + try: + print("Zipping module directory...") + with zipfile.ZipFile(temp, 'w') as zfile: + for root, dirs, files in os.walk(path): + for file in files: + file_path = os.path.join(root, file) + zfile.write(file_path, file_path.split(container).pop()) + return temp + except Exception: + os.remove(temp) + raise if __name__ == '__main__': parser = argparse.ArgumentParser(description='Deploy a module on an OpenERP server.') @@ -54,12 +82,10 @@ if __name__ == '__main__': parser.add_argument('--login', dest='login', default="admin", help='Login (default=admin)') parser.add_argument('--password', dest='password', default="admin", help='Password (default=admin)') if len(sys.argv) == 1: - parser.print_help() - sys.exit(1) + sys.exit(parser.print_help()) args = parser.parse_args() - deploy_module(args.path, args.url, args.login, args.password, args.database) - # try: - # deploy_module(args.path, args.url, args.login, args.password, args.database) - # except Exception, e: - # print(e) - # sys.exit(1) + try: + result = deploy_module(args.path, args.url, args.login, args.password, args.database) + print(result) + except Exception, e: + sys.exit("ERROR: %s" % e) diff --git a/addons/base_import_module/controllers/main.py b/addons/base_import_module/controllers/main.py index 6ddd0158b4d..45ce1e57480 100644 --- a/addons/base_import_module/controllers/main.py +++ b/addons/base_import_module/controllers/main.py @@ -10,10 +10,16 @@ MAX_FILE_SIZE = 100 * 1024 * 1024 # in megabytes class ImportModule(Controller): - @route('/base_import_module/upload', type='http', auth='none') + @route('/base_import_module/check', type='http', auth='user', methods=['GET']) + def check(self): + assert request.db # TODO: custom ensure_db? + assert request.uid == openerp.SUPERUSER_ID # TODO: check admin group + return 'ok' + + @route('/base_import_module/upload', type='http', auth='user', methods=['POST']) def upload(self, mod_file=None, **kw): assert request.db # TODO: custom ensure_db? - request.uid = openerp.SUPERUSER_ID # TODO: proper security + assert request.uid == openerp.SUPERUSER_ID # TODO: check admin group imm = request.registry['ir.module.module'] @@ -22,6 +28,8 @@ class ImportModule(Controller): if not zipfile.is_zipfile(mod_file): raise Exception("Not a zipfile.") + success = [] + errors = dict() with zipfile.ZipFile(mod_file, "r") as z: for zf in z.filelist: if zf.file_size > MAX_FILE_SIZE: @@ -31,8 +39,14 @@ class ImportModule(Controller): z.extractall(module_dir) dirs = [d for d in os.listdir(module_dir) if os.path.isdir(opj(module_dir, d))] for mod_name in dirs: - # assert mod_name.startswith('theme_') - path = opj(module_dir, mod_name) - imm.import_module(request.cr, request.uid, mod_name, path, context=request.context) - return 'ok' - + try: + # assert mod_name.startswith('theme_') + path = opj(module_dir, mod_name) + imm.import_module(request.cr, request.uid, mod_name, path, context=request.context) + success.append(mod_name) + except Exception, e: + errors[mod_name] = str(e) + r = ["Successfully imported module %r" % mod for mod in success] + for mod, error in errors.items(): + r.append("Error while importing module %r: %r" % (mod, error)) + return '\n'.join(r) From 0195f0d8170e06ab2b83aca2209034bafda4702e Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 26 Mar 2014 16:14:11 +0100 Subject: [PATCH 09/13] [ADD] Test module Test suite is still todo bzr revid: fme@openerp.com-20140326151411-moo1yuozvpgro1mh --- .../tests/test_module/__openerp__.py | 37 ++++++++++++++++++ .../tests/test_module/static/src/img/c64.png | Bin 0 -> 24385 bytes .../tests/test_module/static/src/js/test.js | 1 + .../tests/test_module/test.xml | 33 ++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 addons/base_import_module/tests/test_module/__openerp__.py create mode 100644 addons/base_import_module/tests/test_module/static/src/img/c64.png create mode 100644 addons/base_import_module/tests/test_module/static/src/js/test.js create mode 100644 addons/base_import_module/tests/test_module/test.xml diff --git a/addons/base_import_module/tests/test_module/__openerp__.py b/addons/base_import_module/tests/test_module/__openerp__.py new file mode 100644 index 00000000000..b0ecb362b3f --- /dev/null +++ b/addons/base_import_module/tests/test_module/__openerp__.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2013-Today OpenERP SA (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +{ + 'name': 'Test Module', + 'category': 'Website', + 'summary': 'Custom', + 'version': '1.0', + 'description': """ + Test + """, + 'author': 'OpenERP SA', + 'depends': ['website'], + 'data': [ + 'test.xml', + ], + 'installable': True, + 'application': True, +} diff --git a/addons/base_import_module/tests/test_module/static/src/img/c64.png b/addons/base_import_module/tests/test_module/static/src/img/c64.png new file mode 100644 index 0000000000000000000000000000000000000000..3e8183f934fed7d4fa6548604ece0c8e7f6d3aba GIT binary patch literal 24385 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 + + + + + Module Import Success + + + Hagrid + Your Company Tagline + + + + + + + + + From a0bbbf75c393339290676ede5d15d34c38cc7b29 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 26 Mar 2014 16:34:58 +0100 Subject: [PATCH 10/13] [IMP] Allow to disable ssl check bzr revid: fme@openerp.com-20140326153458-6yzhkipn9njcuxyc --- addons/base_import_module/bin/oe_module_deploy.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/addons/base_import_module/bin/oe_module_deploy.py b/addons/base_import_module/bin/oe_module_deploy.py index 863d7875b40..833d455e360 100755 --- a/addons/base_import_module/bin/oe_module_deploy.py +++ b/addons/base_import_module/bin/oe_module_deploy.py @@ -81,9 +81,15 @@ if __name__ == '__main__': parser.add_argument('--database', dest='database', help='Database to use if server does not use db-filter.') parser.add_argument('--login', dest='login', default="admin", help='Login (default=admin)') parser.add_argument('--password', dest='password', default="admin", help='Password (default=admin)') + parser.add_argument('--no-ssl-check', dest='no_ssl_check', action='store_true', help='Do not check ssl cert') if len(sys.argv) == 1: sys.exit(parser.print_help()) + args = parser.parse_args() + + if args.no_ssl_check: + session.verify = False + try: result = deploy_module(args.path, args.url, args.login, args.password, args.database) print(result) From b7fbef1241ac257a24952b9b8eac725711a398f1 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 26 Mar 2014 19:40:22 +0100 Subject: [PATCH 11/13] [FIX] Serve ir.attachment with SUPERUSER_ID We are not supposed to have a user id here bzr revid: fme@openerp.com-20140326184022-1hulv7t5y6vuvr9y --- addons/website/models/ir_http.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 5459fe2ad8e..272e3480fb5 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -102,7 +102,7 @@ class ir_http(orm.AbstractModel): def _serve_attachment(self): domain = [('type', '=', 'binary'), ('url', '=', request.httprequest.path)] - attach = self.pool['ir.attachment'].search_read(request.cr, request.uid, domain, ['__last_update', 'datas', 'mimetype'], context=request.context) + attach = self.pool['ir.attachment'].search_read(request.cr, openerp.SUPERUSER_ID, domain, ['__last_update', 'datas', 'mimetype'], context=request.context) if attach: wdate = attach[0]['__last_update'] datas = attach[0]['datas'] From e49b8f5ae32b072c7a22763ad9472fcce9265f04 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 26 Mar 2014 22:57:09 +0100 Subject: [PATCH 12/13] [FIX] /login is not webservice friendly, base_import_module uses it's own Exceptions in /base_import_module/* will generate 500 pages with a short message bzr revid: fme@openerp.com-20140326215709-esc4zkpfp8uzuww1 --- .../bin/oe_module_deploy.py | 47 +++++++------------ addons/base_import_module/controllers/main.py | 45 +++++++++++++----- 2 files changed, 51 insertions(+), 41 deletions(-) diff --git a/addons/base_import_module/bin/oe_module_deploy.py b/addons/base_import_module/bin/oe_module_deploy.py index 833d455e360..2412382cba5 100755 --- a/addons/base_import_module/bin/oe_module_deploy.py +++ b/addons/base_import_module/bin/oe_module_deploy.py @@ -14,52 +14,41 @@ except ImportError: session = requests.session() -def deploy_module(module_path, url, login, password, db=None): - if url.endswith('/'): - url = url[:-1] +def deploy_module(module_path, url, login, password, db=''): + url = url.rstrip('/') authenticate(url, login, password, db) - check_import(url) module_file = zip_module(module_path) try: return upload_module(url, module_file) finally: os.remove(module_file) -def check_import(server): - url = server +'/base_import_module/check' - res = session.get(url) - if res.status_code == 404: - raise Exception("The server %r does not have the 'base_import_module' installed." % server) - elif res.status_code != 200: - raise Exception("Server %r returned %s http error.", (server, res.status_code)) - def upload_module(server, module_file): print("Uploading module file...") url = server + '/base_import_module/upload' files = dict(mod_file=open(module_file, 'rb')) res = session.post(url, files=files) if res.status_code != 200: - raise Exception("Could not authenticate on server %r" % server) + raise Exception("Could not authenticate on server '%s'" % server) return res.text -def authenticate(server, login, password, db): - print("Connecting to server %r" % server) - print("Waiting for server authentication...") - if db: - url = server + '/login' - args = dict(db=db, login=login, key=password) - res = session.get(url, params=args) - else: - url = server + '/web/login' - args = dict(login=login, password=password) - res = session.post(url, args) - if res.status_code != 200: - raise Exception("Could not authenticate to OpenERP server %r" % server) +def authenticate(server, login, password, db=''): + print("Authenticating on server '%s' ..." % server) + + # Fixate session with a given db if any + session.get(server + '/web/login', params=dict(db=db)) + + args = dict(login=login, password=password, db=db) + res = session.post(server + '/base_import_module/login', args) + if res.status_code == 404: + raise Exception("The server '%s' does not have the 'base_import_module' installed." % server) + elif res.status_code != 200: + raise Exception(res.text) def zip_module(path): path = os.path.abspath(path) if not os.path.isdir(path): - raise Exception("Could not find module directory %r" % path) + raise Exception("Could not find module directory '%s'" % path) container, module_name = os.path.split(path) temp = tempfile.mktemp(suffix='.zip') try: @@ -78,7 +67,7 @@ if __name__ == '__main__': parser = argparse.ArgumentParser(description='Deploy a module on an OpenERP server.') parser.add_argument('path', help="Path of the module to deploy") parser.add_argument('--url', dest='url', help='Url of the server (default=http://localhost:8069)', default="http://localhost:8069") - parser.add_argument('--database', dest='database', help='Database to use if server does not use db-filter.') + parser.add_argument('--db', dest='db', help='Database to use if server does not use db-filter.') parser.add_argument('--login', dest='login', default="admin", help='Login (default=admin)') parser.add_argument('--password', dest='password', default="admin", help='Password (default=admin)') parser.add_argument('--no-ssl-check', dest='no_ssl_check', action='store_true', help='Do not check ssl cert') @@ -91,7 +80,7 @@ if __name__ == '__main__': session.verify = False try: - result = deploy_module(args.path, args.url, args.login, args.password, args.database) + result = deploy_module(args.path, args.url, args.login, args.password, args.db) print(result) except Exception, e: sys.exit("ERROR: %s" % e) diff --git a/addons/base_import_module/controllers/main.py b/addons/base_import_module/controllers/main.py index 45ce1e57480..cbfbd75894b 100644 --- a/addons/base_import_module/controllers/main.py +++ b/addons/base_import_module/controllers/main.py @@ -1,26 +1,47 @@ # -*- coding: utf-8 -*- +import functools import os import zipfile from os.path import join as opj import openerp -from openerp.http import Controller, route, request +from openerp.http import Controller, route, request, Response MAX_FILE_SIZE = 100 * 1024 * 1024 # in megabytes +def webservice(f): + @functools.wraps(f) + def wrap(*args, **kw): + try: + return f(*args, **kw) + except Exception, e: + return Response(response=str(e), status=500) + return wrap + class ImportModule(Controller): - @route('/base_import_module/check', type='http', auth='user', methods=['GET']) - def check(self): - assert request.db # TODO: custom ensure_db? - assert request.uid == openerp.SUPERUSER_ID # TODO: check admin group - return 'ok' + def check_user(self, uid=None): + if uid is None: + uid = request.uid + is_admin = request.registry['res.users'].has_group(request.cr, uid, 'base.group_erp_manager') + if not is_admin: + raise openerp.exceptions.AccessError("Only administrators can upload a module") + + @route('/base_import_module/login', type='http', auth='none', methods=['POST']) + @webservice + def login(self, login, password, db=None): + if db and db != request.db: + raise Exception("Could not select database '%s'" % db) + uid = request.session.authenticate(request.db, login, password) + if not uid: + return Response(response="Wrong login/password", status=401) + self.check_user(uid) + return "ok" @route('/base_import_module/upload', type='http', auth='user', methods=['POST']) + @webservice def upload(self, mod_file=None, **kw): - assert request.db # TODO: custom ensure_db? - assert request.uid == openerp.SUPERUSER_ID # TODO: check admin group - + self.check_user() imm = request.registry['ir.module.module'] if not mod_file: @@ -33,7 +54,7 @@ class ImportModule(Controller): with zipfile.ZipFile(mod_file, "r") as z: for zf in z.filelist: if zf.file_size > MAX_FILE_SIZE: - raise Exception("File %r exceed maximum allowed file size" % zf.filename) + raise Exception("File '%s' exceed maximum allowed file size" % zf.filename) with openerp.tools.osutil.tempdir() as module_dir: z.extractall(module_dir) @@ -46,7 +67,7 @@ class ImportModule(Controller): success.append(mod_name) except Exception, e: errors[mod_name] = str(e) - r = ["Successfully imported module %r" % mod for mod in success] + r = ["Successfully imported module '%s'" % mod for mod in success] for mod, error in errors.items(): - r.append("Error while importing module %r: %r" % (mod, error)) + r.append("Error while importing module '%s': %r" % (mod, error)) return '\n'.join(r) From 3861a93bd9a25878a1338ccf69c2d8cf2b6ac60b Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 27 Mar 2014 11:50:23 +0100 Subject: [PATCH 13/13] [IMP] Test module bzr revid: fme@openerp.com-20140327105023-x3r7mjmptjxpzkqc --- .../tests/test_module/test.xml | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/addons/base_import_module/tests/test_module/test.xml b/addons/base_import_module/tests/test_module/test.xml index 53c7d680fd0..489b286d975 100644 --- a/addons/base_import_module/tests/test_module/test.xml +++ b/addons/base_import_module/tests/test_module/test.xml @@ -2,16 +2,17 @@ - - Module Import Success + + The base company is noupdate=1 + Hagrid Your Company Tagline -