Ejemplo n.º 1
0
 def connect_box(self, token):
     """
     This route is called when we want that a IoT Box will be connected to a Flectra DB
     token is a base 64 encoded string and have 2 argument separate by |
     1 - url of flectra DB
     2 - token. This token will be compared to the token of Flectra. He have 1 hour lifetime
     """
     server = helpers.get_flectra_server_url()
     image = get_resource_path('hw_drivers', 'static/img', 'False.jpg')
     if not server:
         credential = b64decode(token).decode('utf-8').split('|')
         url = credential[0]
         token = credential[1]
         if len(credential) > 2:
             # IoT Box send token with db_uuid and enterprise_code only since V13
             db_uuid = credential[2]
             enterprise_code = credential[3]
             helpers.add_credential(db_uuid, enterprise_code)
         try:
             subprocess.check_call([
                 get_resource_path(
                     'point_of_sale',
                     'tools/posbox/configuration/connect_to_server.sh'),
                 url, '', token, 'noreboot'
             ])
             manager.send_alldevices()
             image = get_resource_path('hw_drivers', 'static/img',
                                       'True.jpg')
             helpers.flectra_restart(3)
         except subprocess.CalledProcessError as e:
             _logger.error('A error encountered : %s ' % e.output)
     if os.path.isfile(image):
         with open(image, 'rb') as f:
             return f.read()
Ejemplo n.º 2
0
    def _get_files(self):
        def _get_upgrade_path(pkg):
            for path in flectra.upgrade.__path__:
                upgrade_path = opj(path, pkg)
                if os.path.exists(upgrade_path):
                    return upgrade_path
            return None

        def get_scripts(path):
            if not path:
                return {}
            return {
                version: glob.glob1(opj(path, version), '*.py')
                for version in os.listdir(path)
                if os.path.isdir(opj(path, version))
            }

        for pkg in self.graph:
            if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade'
                    or getattr(pkg, 'load_state', None) == 'to upgrade'):
                continue

            self.migrations[pkg.name] = {
                'module':
                get_scripts(get_resource_path(pkg.name, 'migrations')),
                'module_upgrades':
                get_scripts(get_resource_path(pkg.name, 'upgrades')),
                'upgrade':
                get_scripts(_get_upgrade_path(pkg.name)),
            }
Ejemplo n.º 3
0
def load_script(path, module_name):
    full_path = get_resource_path(
        *path.split(os.path.sep)) if not os.path.isabs(path) else path
    spec = importlib.util.spec_from_file_location(module_name, full_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module
Ejemplo n.º 4
0
 def list_handlers(self):
     drivers_list = []
     for driver in os.listdir(get_resource_path('hw_drivers', 'iot_handlers/drivers')):
         if driver != '__pycache__':
             drivers_list.append(driver)
     interfaces_list = []
     for interface in os.listdir(get_resource_path('hw_drivers', 'iot_handlers/interfaces')):
         if interface != '__pycache__':
             interfaces_list.append(interface)
     return handler_list_template.render({
         'title': "Flectra's IoT Box - Handlers list",
         'breadcrumb': 'Handlers list',
         'drivers_list': drivers_list,
         'interfaces_list': interfaces_list,
         'server': helpers.get_flectra_server_url()
     })
Ejemplo n.º 5
0
 def _get_default_favicon(self, original=False):
     img_path = get_resource_path('web', 'static/src/img/favicon.ico')
     with tools.file_open(img_path, 'rb') as f:
         if original:
             return base64.b64encode(f.read())
         # Modify the source image to add a colored bar on the bottom
         # This could seem overkill to modify the pixels 1 by 1, but
         # Pillow doesn't provide an easy way to do it, and this
         # is acceptable for a 16x16 image.
         color = (randrange(32, 224,
                            24), randrange(32, 224,
                                           24), randrange(32, 224, 24))
         original = Image.open(f)
         new_image = Image.new('RGBA', original.size)
         height = original.size[1]
         width = original.size[0]
         bar_size = 1
         for y in range(height):
             for x in range(width):
                 pixel = original.getpixel((x, y))
                 if height - bar_size <= y + 1 <= height:
                     new_image.putpixel((x, y),
                                        (color[0], color[1], color[2], 255))
                 else:
                     new_image.putpixel(
                         (x, y), (pixel[0], pixel[1], pixel[2], pixel[3]))
         stream = io.BytesIO()
         new_image.save(stream, format="ICO")
         return base64.b64encode(stream.getvalue())
Ejemplo n.º 6
0
    def test_01_debug_mode_assets(self):
        """ Checks that the ir.attachments records created for compiled less assets in debug mode
        are correctly invalidated.
        """
        # Compile for the first time
        self._bundle(self._get_asset(), True, False)

        # Compile a second time, without changes
        self._bundle(self._get_asset(), False, False)

        # Touch the file and compile a third time
        path = get_resource_path('test_assetsbundle', 'static', 'src', 'less',
                                 'test_lessfile1.less')
        t = time.time() + 5
        asset = self._get_asset()
        _touch(path, asset, t=t)
        self._bundle(asset, True, True)

        # Because we are in the same transaction since the beginning of the test, the first asset
        # created and the second one have the same write_date, but the file's last modified date
        # has really been modified. If we do not update the write_date to a posterior date, we are
        # not able to reproduce the case where we compile this bundle again without changing
        # anything.
        self.cr.execute(
            "update ir_attachment set write_date=clock_timestamp() + interval '10 seconds' where id = (select max(id) from ir_attachment)"
        )

        # Compile a fourth time, without changes
        self._bundle(self._get_asset(), False, False)
Ejemplo n.º 7
0
 def _compute_rating_image(self):
     for rating in self:
         try:
             image_path = get_resource_path('rating', 'static/src/img', 'rating_%s.png' % (int(rating.rating),))
             rating.rating_image = base64.b64encode(open(image_path, 'rb').read())
         except (IOError, OSError):
             rating.rating_image = False
Ejemplo n.º 8
0
 def _compute_website_image_url(self):
     for sponsor in self:
         if sponsor.image_256:
             sponsor.website_image_url = self.env['website'].image_url(sponsor, 'image_256', size=256)
         elif sponsor.partner_id.image_256:
             sponsor.website_image_url = self.env['website'].image_url(sponsor.partner_id, 'image_256', size=256)
         else:
             sponsor.website_image_url = get_resource_path('website_event_track', 'static/src/img', 'event_sponsor_default_%d.png' % (sponsor.id % 1))
Ejemplo n.º 9
0
 def step_by_step_configure(self, token, iotname, essid, password, persistent=False):
     if token:
         url = token.split('|')[0]
         token = token.split('|')[1]
     else:
         url = ''
     subprocess.check_call([get_resource_path('point_of_sale', 'tools/posbox/configuration/connect_to_server_wifi.sh'), url, iotname, token, essid, password, persistent])
     return url
Ejemplo n.º 10
0
 def get_command(self):
     try:
         if os.name == 'nt':
             lessc = misc.find_in_path('lessc.cmd')
         else:
             lessc = misc.find_in_path('lessc')
     except IOError:
         lessc = 'lessc'
     lesspath = get_resource_path('web', 'static', 'lib', 'bootstrap', 'less')
     return [lessc, '-', '--no-js', '--no-color', '--include-path=%s' % lesspath]
Ejemplo n.º 11
0
 def _compute_rating_image(self):
     for rating in self:
         try:
             image_path = get_resource_path(
                 'rating', 'static/src/img',
                 rating._get_rating_image_filename())
             rating.rating_image = base64.b64encode(
                 open(image_path, 'rb').read()) if image_path else False
         except (IOError, OSError):
             rating.rating_image = False
Ejemplo n.º 12
0
 def _compute_sample_bill_image(self):
     """ Retrieve sample bill with facturx to speed up onboarding """
     try:
         path = get_resource_path('account_edi_facturx', 'data/files',
                                  'Invoice.pdf')
         self.sample_bill_preview = base64.b64encode(
             open(path, 'rb').read()) if path else False
     except (IOError, OSError):
         self.sample_bill_preview = False
     return
Ejemplo n.º 13
0
 def stat(self):
     if not (self.inline or self._filename or self._ir_attach):
         path = (segment for segment in self.url.split('/') if segment)
         self._filename = get_resource_path(*path)
         if self._filename:
             return
         try:
             # Test url against ir.attachments
             attach = self.bundle.env['ir.attachment'].sudo().get_serve_attachment(self.url)
             self._ir_attach = attach[0]
         except Exception:
             raise AssetNotFound("Could not find %s" % self.name)
Ejemplo n.º 14
0
 def get_content(self, url, xmlid):
     custom_url = self._get_custom_url(url, xmlid)
     custom_attachment = self._get_custom_attachment(custom_url)
     if custom_attachment.exists():
         return base64.b64decode(custom_attachment.datas).decode('utf-8')
     else:
         match = re.compile("^/(\w+)/(.+?)(\.custom\.(.+))?\.(\w+)$").match(
             url)
         module_path = module.get_module_path(match.group(1))
         resource_path = "%s.%s" % (match.group(2), match.group(5))
         module_resource_path = module.get_resource_path(
             module_path, resource_path)
         with open(module_resource_path, "rb") as file:
             return file.read().decode('utf-8')
Ejemplo n.º 15
0
    def get_asset_content(self, url, url_info=None, custom_attachments=None):
        """
        Fetch the content of an asset (scss / js) file. That content is either
        the one of the related file on the disk or the one of the corresponding
        custom ir.attachment record.

        Params:
            url (str): the URL of the asset (scss / js) file/ir.attachment

            url_info (dict, optional):
                the related url info (see get_asset_info) (allows to optimize
                some code which already have the info and do not want this
                function to re-get it)

            custom_attachments (ir.attachment(), optional):
                the related custom ir.attachment records the function might need
                to search into (allows to optimize some code which already have
                that info and do not want this function to re-get it)

        Returns:
            utf-8 encoded content of the asset (scss / js)
        """
        if url_info is None:
            url_info = self.get_asset_info(url)

        if url_info["customized"]:
            # If the file is already customized, the content is found in the
            # corresponding attachment
            attachment = None
            if custom_attachments is None:
                attachment = self._get_custom_attachment(url)
            else:
                attachment = custom_attachments.filtered(
                    lambda r: r.url == url)
            return attachment and base64.b64decode(attachment.datas) or False

        # If the file is not yet customized, the content is found by reading
        # the local scss file
        module = url_info["module"]
        module_path = get_module_path(module)
        module_resource_path = get_resource_path(module,
                                                 url_info["resource_path"])
        if module_path and module_resource_path:
            module_path = os.path.join(
                os.path.normpath(module_path),
                '')  # join ensures the path ends with '/'
            module_resource_path = os.path.normpath(module_resource_path)
            if module_resource_path.startswith(module_path):
                with open(module_resource_path, "rb") as f:
                    return f.read()
Ejemplo n.º 16
0
    def _get_files(self):
        def get_scripts(path):
            if not path:
                return {}
            return {
                version: glob.glob1(opj(path, version), '*.py')
                for version in os.listdir(path)
                if os.path.isdir(opj(path, version))
            }

        for pkg in self.graph:
            if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade'
                    or getattr(pkg, 'load_state', None) == 'to upgrade'):
                continue

            self.migrations[pkg.name] = {
                'module':
                get_scripts(get_resource_path(pkg.name, 'migrations')),
                'maintenance':
                get_scripts(
                    get_resource_path('base', 'maintenance', 'migrations',
                                      pkg.name)),
            }
Ejemplo n.º 17
0
 def stat(self):
     if not (self.inline or self._filename or self._ir_attach):
         path = (segment for segment in self.url.split('/') if segment)
         self._filename = get_resource_path(*path)
         if self._filename:
             return
         try:
             # Test url against ir.attachments
             fields = ['__last_update', 'datas', 'mimetype']
             domain = [('type', '=', 'binary'), ('url', '=', self.url)]
             attach = self.bundle.env['ir.attachment'].sudo().search_read(domain, fields)
             self._ir_attach = attach[0]
         except Exception:
             raise AssetNotFound("Could not find %s" % self.name)
Ejemplo n.º 18
0
    def _connect_to_server(self, url, token, db_uuid, enterprise_code):
        if db_uuid and enterprise_code:
            helpers.add_credential(db_uuid, enterprise_code)

        # Save DB URL and token
        subprocess.check_call([
            get_resource_path(
                'point_of_sale',
                'tools/posbox/configuration/connect_to_server.sh'), url, '',
            token, 'noreboot'
        ])
        # Notify the DB, so that the kanban view already shows the IoT Box
        manager.send_alldevices()
        # Restart to checkout the git branch, get a certificate, load the IoT handlers...
        subprocess.check_call(["sudo", "service", "flectra", "restart"])
Ejemplo n.º 19
0
 def connect_to_server(self, token, iotname):
     if token:
         credential = token.split('|')
         url = credential[0]
         token = credential[1]
         if len(credential) > 2:
             # IoT Box send token with db_uuid and enterprise_code only since V13
             db_uuid = credential[2]
             enterprise_code = credential[3]
             helpers.add_credential(db_uuid, enterprise_code)
     else:
         url = helpers.get_flectra_server_url()
         token = helpers.get_token()
     reboot = 'reboot'
     subprocess.check_call([get_resource_path('point_of_sale', 'tools/posbox/configuration/connect_to_server.sh'), url, iotname, token, reboot])
     return 'http://' + helpers.get_ip() + ':7073'
Ejemplo n.º 20
0
def load_iot_handlers():
    """
    This method loads local files: 'flectra/addons/hw_drivers/iot_handlers/drivers' and
    'flectra/addons/hw_drivers/iot_handlers/interfaces'
    And execute these python drivers and interfaces
    """
    for directory in ['interfaces', 'drivers']:
        path = get_resource_path('hw_drivers', 'iot_handlers', directory)
        filesList = os.listdir(path)
        for file in filesList:
            path_file = os.path.join(path, file)
            spec = util.spec_from_file_location(file, path_file)
            if spec:
                module = util.module_from_spec(spec)
                spec.loader.exec_module(module)
    http.addons_manifest = {}
    http.root = http.Root()
Ejemplo n.º 21
0
    def test_17_css_bundle_date_invalidation(self):
        """ Checks that both css bundles are invalidated when one of its assets' modification date is changed
        """
        # Assets access for en_US language
        ltr_bundle0 = self._get_asset(self.cssbundle_xmlid)
        ltr_bundle0.css()
        ltr_last_modified0 = ltr_bundle0.last_modified
        ltr_version0 = ltr_bundle0.version

        # Assets access for ar_SY language
        rtl_bundle0 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'lang': 'ar_SY'}))
        rtl_bundle0.css()
        rtl_last_modified0 = rtl_bundle0.last_modified
        rtl_version0 = rtl_bundle0.version

        # Touch test_cssfile1.css
        # Note: No lang specific context given while calling _get_asset so it will load assets for en_US
        path = get_resource_path('test_assetsbundle', 'static', 'src', 'css', 'test_cssfile1.css')
        ltr_bundle1 = self._get_asset(self.cssbundle_xmlid)

        with self._touch(path):
            ltr_bundle1.css()
            ltr_last_modified1 = ltr_bundle1.last_modified
            ltr_version1 = ltr_bundle1.version
            ltr_ira1 = self._any_ira_for_bundle('css')
            self.assertNotEqual(ltr_last_modified0, ltr_last_modified1)
            self.assertNotEqual(ltr_version0, ltr_version1)

            rtl_bundle1 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'lang': 'ar_SY'}))

            rtl_bundle1.css()
            rtl_last_modified1 = rtl_bundle1.last_modified
            rtl_version1 = rtl_bundle1.version
            rtl_ira1 = self._any_ira_for_bundle('css', lang='ar_SY')
            self.assertNotEqual(rtl_last_modified0, rtl_last_modified1)
            self.assertNotEqual(rtl_version0, rtl_version1)

            # Checks rtl and ltr bundles are different
            self.assertNotEqual(ltr_ira1.id, rtl_ira1.id)

            # check if the previous attachment is correctly cleaned
            css_bundles = self.env['ir.attachment'].search([
                ('url', '=like', '/web/content/%-%/{0}%.{1}'.format(self.cssbundle_xmlid, 'css'))
            ])
            self.assertEqual(len(css_bundles), 2)
Ejemplo n.º 22
0
    def test_03_date_invalidation(self):
        """ Checks that a bundle is invalidated when one of its assets' modification date is changed.
        """
        bundle0 = self._get_asset(self.jsbundle_xmlid)
        bundle0.js()
        last_modified0 = bundle0.last_modified
        version0 = bundle0.version

        path = get_resource_path('test_assetsbundle', 'static', 'src', 'js', 'test_jsfile1.js')
        bundle1 = self._get_asset(self.jsbundle_xmlid)
        _touch(path, bundle1)

        bundle1.js()
        last_modified1 = bundle1.last_modified
        version1 = bundle1.version
        self.assertNotEquals(last_modified0, last_modified1)
        self.assertNotEquals(version0, version1)

        # check if the previous attachment is correctly cleaned
        self.assertEquals(len(self._any_ira_for_bundle('js')), 1)
Ejemplo n.º 23
0
    def test_10_paginated_css_date_invalidation(self):
        """ Checks that a bundle is invalidated when one of its assets' modification date is changed.
        """
        bundle0 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'max_css_rules': 1}))
        bundle0.css()
        last_modified0 = bundle0.last_modified
        version0 = bundle0.version

        path = get_resource_path('test_assetsbundle', 'static', 'src', 'css', 'test_cssfile1.css')
        bundle1 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'max_css_rules': 1}))
        _touch(path, bundle1)

        bundle1.css()
        last_modified1 = bundle1.last_modified
        version1 = bundle1.version

        self.assertNotEquals(last_modified0, last_modified1)
        self.assertNotEquals(version0, version1)

        # check if the previous attachment is correctly cleaned
        self.assertEquals(len(self._any_ira_for_bundle('css')), 3)
Ejemplo n.º 24
0
    def connect_to_wifi(self, essid, password, persistent=False):
        if persistent:
                persistent = "1"
        else:
                persistent = ""

        subprocess.check_call([get_resource_path('point_of_sale', 'tools/posbox/configuration/connect_to_wifi.sh'), essid, password, persistent])
        server = helpers.get_flectra_server_url()
        res_payload = {
            'message': 'Connecting to ' + essid,
        }
        if server:
            res_payload['server'] = {
                'url': server,
                'message': 'Redirect to Flectra Server'
            }
        else:
            res_payload['server'] = {
                'url': 'http://' + helpers.get_ip() + ':7073',
                'message': 'Redirect to IoT Box'
            }

        return json.dumps(res_payload)
Ejemplo n.º 25
0
    def setUpClass(cls):
        super(TestAccountInvoiceInterCompany, cls).setUpClass()
        module = "account_invoice_inter_company"
        convert_file(
            cls.cr, module,
            get_resource_path(module, "tests", "inter_company_invoice.xml"),
            None, 'init', False, 'test', cls.registry._assertion_report,
        )
        cls.wizard_obj = cls.env['wizard.multi.charts.accounts']
        cls.account_obj = cls.env['account.account']
        cls.invoice_obj = cls.env['account.invoice']
        cls.invoice_company_a = cls.env.ref(
            'account_invoice_inter_company.customer_invoice_company_a')
        cls.user_company_a = cls.env.ref(
            'account_invoice_inter_company.user_company_a')
        cls.user_company_b = cls.env.ref(
            'account_invoice_inter_company.user_company_b')

        cls.chart = cls.env['account.chart.template'].search([], limit=1)
        if not cls.chart:
            raise ValidationError(
                # translation to avoid pylint warnings
                _("No Chart of Account Template has been defined !"))
Ejemplo n.º 26
0
    def _binary_ir_attachment_redirect_content(
            cls, record, default_mimetype='application/octet-stream'):
        # mainly used for theme images attachemnts
        status = content = filename = filehash = None
        mimetype = getattr(record, 'mimetype', False)
        if record.type == 'url' and record.url:
            # if url in in the form /somehint server locally
            url_match = re.match("^/(\w+)/(.+)$", record.url)
            if url_match:
                module = url_match.group(1)
                module_path = get_module_path(module)
                module_resource_path = get_resource_path(
                    module, url_match.group(2))

                if module_path and module_resource_path:
                    module_path = os.path.join(
                        os.path.normpath(module_path),
                        '')  # join ensures the path ends with '/'
                    module_resource_path = os.path.normpath(
                        module_resource_path)
                    if module_resource_path.startswith(module_path):
                        with open(module_resource_path, 'rb') as f:
                            content = base64.b64encode(f.read())
                        status = 200
                        filename = os.path.basename(module_resource_path)
                        mimetype = guess_mimetype(base64.b64decode(content),
                                                  default=default_mimetype)
                        filehash = '"%s"' % hashlib.md5(
                            pycompat.to_text(content).encode(
                                'utf-8')).hexdigest()

            if not content:
                status = 301
                content = record.url

        return status, content, filename, mimetype, filehash
Ejemplo n.º 27
0
    def _get_asset_content(self, xmlid, options):
        options = dict(options,
                       inherit_branding=False,
                       inherit_branding_auto=False,
                       edit_translations=False,
                       translatable=False,
                       rendering_bundle=True)

        env = self.env(context=options)

        def can_aggregate(url):
            return not urls.url_parse(url).scheme and not urls.url_parse(
                url).netloc and not url.startswith('/web/content')

        # TODO: This helper can be used by any template that wants to embedd the backend.
        #       It is currently necessary because the ir.ui.view bundle inheritance does not
        #       match the module dependency graph.
        def get_modules_order():
            if request:
                from flectra.addons.web.controllers.main import module_boot
                return json.dumps(module_boot())
            return '[]'

        template = env['ir.qweb'].render(
            xmlid, {"get_modules_order": get_modules_order})

        files = []
        remains = []
        for el in html.fragments_fromstring(template):
            if isinstance(el, html.HtmlElement):
                href = el.get('href', '')
                src = el.get('src', '')
                atype = el.get('type')
                media = el.get('media')

                if can_aggregate(href) and (
                        el.tag == 'style' or
                    (el.tag == 'link' and el.get('rel') == 'stylesheet')):
                    if href.endswith('.sass'):
                        atype = 'text/sass'
                    elif href.endswith('.less'):
                        atype = 'text/less'
                    if atype not in ('text/less', 'text/sass'):
                        atype = 'text/css'
                    path = [segment for segment in href.split('/') if segment]
                    filename = get_resource_path(*path) if path else None
                    files.append({
                        'atype': atype,
                        'url': href,
                        'filename': filename,
                        'content': el.text,
                        'media': media
                    })
                elif can_aggregate(src) and el.tag == 'script':
                    atype = 'text/javascript'
                    path = [segment for segment in href.split('/') if segment]
                    filename = get_resource_path(*path) if path else None
                    files.append({
                        'atype': atype,
                        'url': src,
                        'filename': filename,
                        'content': el.text,
                        'media': media
                    })
                else:
                    remains.append((el.tag, OrderedDict(el.attrib), el.text))
            else:
                # the other cases are ignored
                pass

        return (files, remains)
Ejemplo n.º 28
0
    def binary_content(cls,
                       xmlid=None,
                       model='ir.attachment',
                       id=None,
                       field='datas',
                       unique=False,
                       filename=None,
                       filename_field='datas_fname',
                       download=False,
                       mimetype=None,
                       default_mimetype='application/octet-stream',
                       access_token=None,
                       env=None):
        """ Get file, attachment or downloadable content

        If the ``xmlid`` and ``id`` parameter is omitted, fetches the default value for the
        binary field (via ``default_get``), otherwise fetches the field for
        that precise record.

        :param str xmlid: xmlid of the record
        :param str model: name of the model to fetch the binary from
        :param int id: id of the record from which to fetch the binary
        :param str field: binary field
        :param bool unique: add a max-age for the cache control
        :param str filename: choose a filename
        :param str filename_field: if not create an filename with model-id-field
        :param bool download: apply headers to download the file
        :param str mimetype: mintype of the field (for headers)
        :param str default_mimetype: default mintype if no mintype found
        :param str access_token: optional token for unauthenticated access
                                 only available  for ir.attachment
        :param Environment env: by default use request.env
        :returns: (status, headers, content)
        """
        env = env or request.env
        # get object and content
        obj = None
        if xmlid:
            obj = env.ref(xmlid, False)
        elif id and model == 'ir.attachment' and access_token:
            obj = env[model].sudo().browse(int(id))
            if not consteq(obj.access_token, access_token):
                return (403, [], None)
        elif id and model in env.registry:
            obj = env[model].browse(int(id))

        # obj exists
        if not obj or not obj.exists() or field not in obj:
            return (404, [], None)

        # check read access
        try:
            last_update = obj['__last_update']
        except AccessError:
            return (403, [], None)

        status, headers, content = None, [], None

        # attachment by url check
        module_resource_path = None
        if model == 'ir.attachment' and obj.type == 'url' and obj.url:
            url_match = re.match("^/(\w+)/(.+)$", obj.url)
            if url_match:
                module = url_match.group(1)
                module_path = get_module_path(module)
                module_resource_path = get_resource_path(
                    module, url_match.group(2))
                if module_path and module_resource_path:
                    module_path = os.path.join(
                        os.path.normpath(module_path),
                        '')  # join ensures the path ends with '/'
                    module_resource_path = os.path.normpath(
                        module_resource_path)
                    if module_resource_path.startswith(module_path):
                        with open(module_resource_path, 'rb') as f:
                            content = base64.b64encode(f.read())
                        last_update = pycompat.text_type(
                            os.path.getmtime(module_resource_path))

            if not module_resource_path:
                module_resource_path = obj.url

            if not content:
                status = 301
                content = module_resource_path
        else:
            content = obj[field] or ''

        # filename
        if not filename:
            if filename_field in obj:
                filename = obj[filename_field]
            elif module_resource_path:
                filename = os.path.basename(module_resource_path)
            else:
                filename = "%s-%s-%s" % (obj._name, obj.id, field)

        # mimetype
        mimetype = 'mimetype' in obj and obj.mimetype or False
        if not mimetype:
            if filename:
                mimetype = mimetypes.guess_type(filename)[0]
            if not mimetype and getattr(env[model]._fields[field],
                                        'attachment', False):
                # for binary fields, fetch the ir_attachement for mimetype check
                attach_mimetype = env['ir.attachment'].search_read(
                    domain=[('res_model', '=', model), ('res_id', '=', id),
                            ('res_field', '=', field)],
                    fields=['mimetype'],
                    limit=1)
                mimetype = attach_mimetype and attach_mimetype[0]['mimetype']
            if not mimetype:
                mimetype = guess_mimetype(base64.b64decode(content),
                                          default=default_mimetype)

        headers += [('Content-Type', mimetype),
                    ('X-Content-Type-Options', 'nosniff')]

        # cache
        etag = bool(request) and request.httprequest.headers.get(
            'If-None-Match')
        retag = '"%s"' % hashlib.md5(
            pycompat.to_text(content).encode('utf-8')).hexdigest()
        status = status or (304 if etag == retag else 200)
        headers.append(('ETag', retag))
        headers.append(
            ('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0)))

        # content-disposition default name
        if download:
            headers.append(
                ('Content-Disposition', cls.content_disposition(filename)))
        return (status, headers, content)
Ejemplo n.º 29
0
 def _get_thumbnail_path(self, size, name):
     folders = ["static", "lib", "img", "thumbnails"]
     path = get_resource_path("dms", *folders, name)
     if not os.path.isfile(path):
         path = get_resource_path("dms", *folders, "file_unkown.svg")
     return path
Ejemplo n.º 30
0
    def get_assets_editor_resources(self, key, get_views=True, get_less=True, bundles=False, bundles_restriction=[]):
        # Related views must be fetched if the user wants the views and/or the style
        views = request.env["ir.ui.view"].get_related_views(key, bundles=bundles)
        views = views.read(['name', 'id', 'key', 'xml_id', 'arch', 'active', 'inherit_id'])

        less_files_data_by_bundle = []

        # Load less only if asked by the user
        if get_less:
            # Compile regex outside of the loop
            # This will used to exclude library less files from the result
            excluded_url_matcher = re.compile("^(.+/lib/.+)|(.+import_bootstrap.less)$")

            # Load already customized less files attachments
            custom_attachments = request.env["ir.attachment"].search([("url", "=like", self._make_custom_less_file_url("%%.%%", "%%"))])

            # First check the t-call-assets used in the related views
            url_infos = dict()
            for v in views:
                for asset_call_node in etree.fromstring(v["arch"]).xpath("//t[@t-call-assets]"):
                    if asset_call_node.get("t-css") == "false":
                        continue
                    asset_name = asset_call_node.get("t-call-assets")

                    # Loop through bundle files to search for LESS file info
                    less_files_data = []
                    for file_info in request.env["ir.qweb"]._get_asset_content(asset_name, {})[0]:
                        if file_info["atype"] != "text/less":
                            continue
                        url = file_info["url"]

                        # Exclude library files (see regex above)
                        if excluded_url_matcher.match(url):
                            continue

                        # Check if the file is customized and get bundle/path info
                        less_file_data = self._match_less_file_url(url)
                        if not less_file_data:
                            continue

                        # Save info (arch will be fetched later)
                        url_infos[url] = less_file_data
                        less_files_data.append(url)

                    # Less data is returned sorted by bundle, with the bundles names and xmlids
                    if len(less_files_data):
                        less_files_data_by_bundle.append([dict(xmlid=asset_name, name=request.env.ref(asset_name).name), less_files_data])

            # Filter bundles/files:
            # - A file which appears in multiple bundles only appears in the first one (the first in the DOM)
            # - Only keep bundles with files which appears in the asked bundles and only keep those files
            for i in range(0, len(less_files_data_by_bundle)):
                bundle_1 = less_files_data_by_bundle[i]
                for j in range(0, len(less_files_data_by_bundle)):
                    bundle_2 = less_files_data_by_bundle[j]
                    # In unwanted bundles, keep only the files which are in wanted bundles too (less_helpers)
                    if bundle_1[0]["xmlid"] not in bundles_restriction and bundle_2[0]["xmlid"] in bundles_restriction:
                        bundle_1[1] = [item_1 for item_1 in bundle_1[1] if item_1 in bundle_2[1]]
            for i in range(0, len(less_files_data_by_bundle)):
                bundle_1 = less_files_data_by_bundle[i]
                for j in range(i+1, len(less_files_data_by_bundle)):
                    bundle_2 = less_files_data_by_bundle[j]
                    # In every bundle, keep only the files which were not found in previous bundles
                    bundle_2[1] = [item_2 for item_2 in bundle_2[1] if item_2 not in bundle_1[1]]

            # Only keep bundles which still have files and that were requested
            less_files_data_by_bundle = [
                data for data in less_files_data_by_bundle
                if (len(data[1]) > 0 and (not bundles_restriction or data[0]["xmlid"] in bundles_restriction))
            ]

            # Fetch the arch of each kept file, in each bundle
            for bundle_data in less_files_data_by_bundle:
                for i in range(0, len(bundle_data[1])):
                    url = bundle_data[1][i]
                    url_info = url_infos[url]

                    content = None
                    if url_info["customized"]:
                        # If the file is already customized, the content is found in the corresponding attachment
                        content = base64.b64decode(custom_attachments.filtered(lambda a: a.url == url).datas)
                    else:
                        # If the file is not yet customized, the content is found by reading the local less file
                        module = url_info["module"]
                        module_path = get_module_path(module)
                        module_resource_path = get_resource_path(module, url_info["resource_path"])
                        if module_path and module_resource_path:
                            module_path = os.path.join(os.path.normpath(module_path), '') # join ensures the path ends with '/'
                            module_resource_path = os.path.normpath(module_resource_path)
                            if module_resource_path.startswith(module_path):
                                with open(module_resource_path, "rb") as f:
                                    content = f.read()

                    bundle_data[1][i] = dict(
                        url = "/%s/%s" % (url_info["module"], url_info["resource_path"]),
                        arch = content,
                        customized = url_info["customized"],
                    )

        return dict(
            views = get_views and views or [],
            less = get_less and less_files_data_by_bundle or [],
        )