def view(self, db, token, action, id, view='calendar'): registry = registry_get(db) with registry.cursor() as cr: # Since we are in auth=none, create an env with SUPERUSER_ID env = Environment(cr, SUPERUSER_ID, {}) attendee = env['calendar.attendee'].search([('access_token', '=', token), ('event_id', '=', int(id))]) if not attendee: return request.not_found() timezone = attendee.partner_id.tz lang = attendee.partner_id.lang or 'en_US' event = env['calendar.event'].with_context(tz=timezone, lang=lang).browse(int(id)) # If user is internal and logged, redirect to form view of event # otherwise, display the simplifyed web page with event informations if request.session.uid and request.env['res.users'].browse(request.session.uid).user_has_groups('base.group_user'): return werkzeug.utils.redirect('/web?db=%s#id=%s&view_type=form&model=calendar.event' % (db, id)) # NOTE : we don't use request.render() since: # - we need a template rendering which is not lazy, to render before cursor closing # - we need to display the template in the language of the user (not possible with # request.render()) response_content = env['ir.ui.view'].with_context(lang=lang).render_template( 'calendar.invitation_page_anonymous', { 'event': event, 'attendee': attendee, }) return request.make_response(response_content, headers=[('Content-Type', 'text/html')])
def download_document(self, file, filename): if not file: return request.not_found() else: return request.make_response( file, [('Content-Type', 'application/octet-stream'), ('Content-Disposition', content_disposition(filename))])
def view_meeting(self, token, id, **kwargs): attendee = request.env['calendar.attendee'].sudo().search([ ('access_token', '=', token), ('event_id', '=', int(id)) ]) if not attendee: return request.not_found() timezone = attendee.partner_id.tz lang = attendee.partner_id.lang or get_lang(request.env).code event = request.env['calendar.event'].with_context( tz=timezone, lang=lang).sudo().browse(int(id)) company = event.user_id and event.user_id.company_id or event.create_uid.company_id # If user is internal and logged, redirect to form view of event # otherwise, display the simplifyed web page with event informations if request.session.uid and request.env['res.users'].browse( request.session.uid).user_has_groups('base.group_user'): return werkzeug.utils.redirect( '/web?db=%s#id=%s&view_type=form&model=calendar.event' % (request.env.cr.dbname, id)) # NOTE : we don't use request.render() since: # - we need a template rendering which is not lazy, to render before cursor closing # - we need to display the template in the language of the user (not possible with # request.render()) response_content = request.env['ir.ui.view'].with_context( lang=lang)._render_template('calendar.invitation_page_anonymous', { 'company': company, 'event': event, 'attendee': attendee, }) return request.make_response(response_content, headers=[('Content-Type', 'text/html')])
def _show_report(self, model, report_type, report_ref, download=False): if report_type not in ('html', 'pdf', 'text'): raise UserError(_("Invalid report type: %s", report_type)) report_sudo = request.env.ref(report_ref).with_user(SUPERUSER_ID) if not isinstance(report_sudo, type(request.env['ir.actions.report'])): raise UserError( _("%s is not the reference of a report", report_ref)) method_name = '_render_qweb_%s' % (report_type) report = getattr(report_sudo, method_name)([model.id], data={ 'report_type': report_type })[0] reporthttpheaders = [ ('Content-Type', 'application/pdf' if report_type == 'pdf' else 'text/html'), ('Content-Length', len(report)), ] if report_type == 'pdf' and download: filename = "%s.pdf" % (re.sub('\W+', '-', model._get_report_base_filename())) reporthttpheaders.append( ('Content-Disposition', content_disposition(filename))) return request.make_response(report, headers=reporthttpheaders)
def avatar(self, res_model, res_id, partner_id): headers = [('Content-Type', 'image/png')] status = 200 content = 'R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' # default image is one white pixel if res_model in request.env: try: # if the current user has access to the document, get the partner avatar as sudo() request.env[res_model].browse(res_id).check_access_rule('read') if partner_id in request.env[res_model].browse(res_id).sudo( ).exists().message_ids.mapped('author_id').ids: status, headers, _content = binary_content( model='res.partner', id=partner_id, field='image_medium', default_mimetype='image/png', env=request.env(user=SUPERUSER_ID)) # binary content return an empty string and not a placeholder if obj[field] is False if _content != '': content = _content if status == 304: return werkzeug.wrappers.Response(status=304) except AccessError: pass image_base64 = base64.b64decode(content) headers.append(('Content-Length', len(image_base64))) response = request.make_response(image_base64, headers) response.status = str(status) return response
def webmanifest(self): """ Returns a WebManifest describing the metadata associated with a web application. Using this metadata, user agents can provide developers with means to create user experiences that are more comparable to that of a native application. """ website = request.website manifest = { 'name': website.events_app_name, 'short_name': website.events_app_name, 'description': _('%s Online Events Application') % website.company_id.name, 'scope': url_for('/event'), 'start_url': url_for('/event'), 'display': 'standalone', 'background_color': '#ffffff', 'theme_color': '#009EFB', } icon_sizes = ['192x192', '512x512'] manifest['icons'] = [{ 'src': website.image_url(website, 'app_icon', size=size), 'sizes': size, 'type': 'image/png', } for size in icon_sizes] body = json.dumps(manifest, default=ustr) response = request.make_response(body, [ ('Content-Type', 'application/manifest+json'), ]) return response
def print_sale_details(self, date_start=False, date_stop=False, **kw): r = request.env['report.point_of_sale.report_saledetails'] pdf, _ = request.env.ref( 'point_of_sale.sale_details_report').with_context( date_start=date_start, date_stop=date_stop).render_qweb_pdf(r) pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf))] return request.make_response(pdf, headers=pdfhttpheaders)
def portal_sale_order_report(self, order_id, access_token=None, **kw): pdf = request.env.ref('sale.action_report_saleorder' ).sudo().render_qweb_pdf([order_id])[0] pdfhttpheaders = [ ('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ] return request.make_response(pdf, headers=pdfhttpheaders)
def dashboard(self, **post): image = None user = request.env.user company = user.company_id if company.dashboard_background: image = base64.b64decode(company.dashboard_background) return request.make_response( image, [('Content-Type', 'image')])
def attachment_add(self, name, file, res_model, res_id, access_token=None, **kwargs): """Process a file uploaded from the portal chatter and create the corresponding `ir.attachment`. The attachment will be created "pending" until the associated message is actually created, and it will be garbage collected otherwise. :param name: name of the file to save. :type name: string :param file: the file to save :type file: werkzeug.FileStorage :param res_model: name of the model of the original document. To check access rights only, it will not be saved here. :type res_model: string :param res_id: id of the original document. To check access rights only, it will not be saved here. :type res_id: int :param access_token: access_token of the original document. To check access rights only, it will not be saved here. :type access_token: string :return: attachment data {id, name, mimetype, file_size, access_token} :rtype: dict """ try: self._document_check_access(res_model, int(res_id), access_token=access_token) except (AccessError, MissingError) as e: raise UserError(_("The document does not exist or you do not have the rights to access it.")) IrAttachment = request.env['ir.attachment'] access_token = False # Avoid using sudo or creating access_token when not necessary: internal # users can create attachments, as opposed to public and portal users. if not request.env.user.has_group('base.group_user'): IrAttachment = IrAttachment.sudo().with_context(binary_field_real_user=IrAttachment.env.user) access_token = IrAttachment._generate_access_token() # At this point the related message does not exist yet, so we assign # those specific res_model and res_is. They will be correctly set # when the message is created: see `portal_chatter_post`, # or garbage collected otherwise: see `_garbage_collect_attachments`. attachment = IrAttachment.create({ 'name': name, 'datas': base64.b64encode(file.read()), 'res_model': 'mail.compose.message', 'res_id': 0, 'access_token': access_token, }) return request.make_response( data=json.dumps(attachment.read(['id', 'name', 'mimetype', 'file_size', 'access_token'])[0]), headers=[('Content-Type', 'application/json')] )
def dashboard(self, **post): user = request.env.user company = user.company_id if company.dashboard_background: image = base64.b64decode(company.dashboard_background) else: return redirect(DEFAULT_IMAGE) return request.make_response(image, [('Content-Type', 'image')])
def _make_attachment_response(self, file, filename): headers = [ ('Content-Type', mimetypes.guess_type(urllib.request.pathname2url(filename))[0]), ('Content-Disposition', 'attachment; filename="{}";'.format(filename)), ('Content-Length', len(file)) ] return request.make_response(file, headers)
def get_wishlist(self, count=False, **kw): values = request.env['product.wishlist'].with_context(display_default_code=False).current() if count: return request.make_response(json.dumps(values.mapped('product_id').ids)) if not len(values): return request.redirect("/shop") return request.render("website_sale_wishlist.product_wishlist", dict(wishes=values))
def event_ics_file(self, event, **kwargs): files = event._get_ics_file() if not event.id in files: return NotFound() content = files[event.id] return request.make_response(content, [ ('Content-Type', 'application/octet-stream'), ('Content-Length', len(content)), ('Content-Disposition', content_disposition('%s.ics' % event.name)) ])
def print_saleorder(self): sale_order_id = request.session.get('sale_last_order_id') if sale_order_id: pdf, _ = request.env.ref( 'sale.action_report_saleorder').sudo().render_qweb_pdf( [sale_order_id]) pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', u'%s' % len(pdf))] return request.make_response(pdf, headers=pdfhttpheaders) else: return request.redirect('/shop')
def slide_download(self, slide, sitemap=False): if slide.download_security == 'public' or (slide.download_security == 'user' and request.session.uid): filecontent = base64.b64decode(slide.datas) disposition = 'attachment; filename=%s.pdf' % werkzeug.urls.url_quote(slide.name) return request.make_response( filecontent, [('Content-Type', 'application/pdf'), ('Content-Length', len(filecontent)), ('Content-Disposition', disposition)]) elif not request.session.uid and slide.download_security == 'user': return werkzeug.utils.redirect('/web?redirect=/slides/slide/%s' % (slide.id)) return request.render("website.403")
def portal_my_invoice_report(self, invoice_id, access_token=None, **kw): try: invoice_sudo = self._invoice_check_access(invoice_id, access_token) except AccessError: return request.redirect('/my') # print report as sudo, since it require access to taxes, payment term, ... and portal # does not have those access rights. pdf = request.env.ref('account.account_invoices').sudo().render_qweb_pdf([invoice_sudo.id])[0] pdfhttpheaders = [ ('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ] return request.make_response(pdf, headers=pdfhttpheaders)
def livechat_lib(self, ext, **kwargs): # _get_asset return the bundle html code (script and link list) but we want to use the attachment content xmlid = 'im_livechat.external_lib' files, remains = request.env["ir.qweb"]._get_asset_content(xmlid, options=request.context) asset = AssetsBundle(xmlid, files, remains) mock_attachment = getattr(asset, ext)() if isinstance(mock_attachment, list): # suppose that CSS asset will not required to be split in pages mock_attachment = mock_attachment[0] # can't use /web/content directly because we don't have attachment ids (attachments must be created) status, headers, content = binary_content(id=mock_attachment.id, unique=asset.checksum) content_base64 = base64.b64decode(content) if content else '' headers.append(('Content-Length', len(content_base64))) return request.make_response(content_base64, headers)
def _get_icon(self, icon_size, company_id): config = self._get_pwa_config(company_id) if config: if icon_size == 128: icon = config.pwa_icon_128 elif icon_size == 192: icon = config.pwa_icon_192 elif icon_size == 512: icon = config.pwa_icon_512 if icon: icon = BytesIO(base64.b64decode(icon)) return request.make_response(icon.read(), [('Content-Type', 'image/png')]) return False
def user_avatar(self, user_id=0, **post): status, headers, content = binary_content(model='res.users', id=user_id, field='image_medium', default_mimetype='image/png', env=request.env(user=SUPERUSER_ID)) if not content: img_path = modules.get_module_resource('web', 'static/src/img', 'placeholder.png') with open(img_path, 'rb') as f: image = f.read() content = base64.b64encode(image) if status == 304: return werkzeug.wrappers.Response(status=304) image_base64 = base64.b64decode(content) headers.append(('Content-Length', len(image_base64))) response = request.make_response(image_base64, headers) response.status = str(status) return response
def report(self, output_format, report_name, token, report_id=False, **kw): uid = request.session.uid domain = [('create_uid', '=', uid)] stock_traceability = request.env[ 'stock.traceability.report'].with_user(uid).search(domain, limit=1) line_data = json.loads(kw['data']) try: if output_format == 'pdf': response = request.make_response( stock_traceability.with_context( active_id=report_id).get_pdf(line_data), headers=[('Content-Type', 'application/pdf'), ('Content-Disposition', 'attachment; filename=' + 'stock_traceability' + '.pdf;')]) response.set_cookie('fileToken', token) return response except Exception as e: se = _serialize_exception(e) error = { 'code': 200, 'message': 'Flectra Server Error', 'data': se } return request.make_response(html_escape(json.dumps(error)))
def portal_my_picking_report(self, picking_id, access_token=None, **kw): """ Print delivery slip for customer, using either access rights or access token to be sure customer has access """ try: picking_sudo = self._stock_picking_check_access(picking_id, access_token=access_token) except exceptions.AccessError: return request.redirect('/my') # print report as sudo, since it require access to product, taxes, payment term etc.. and portal does not have those access rights. pdf = request.env.ref('stock.action_report_delivery').sudo().render_qweb_pdf([picking_sudo.id])[0] pdfhttpheaders = [ ('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ] return request.make_response(pdf, headers=pdfhttpheaders)
def download(self, generator, modules, **kwargs): generator = request.env[generator] modules = request.env['module.builder.main'].search([ ('id', 'in', modules.split(',')) ]) filename = "{name}.{ext}".format( name=modules[0].name if len( modules) == 1 else 'modules', ext="zip") zip_io = generator.get_zipped(modules) content = zip_io.getvalue() return request.make_response( content, headers=[ ('Content-Type', 'plain/text' or 'application/octet-stream'), ('Content-Disposition', content_disposition(filename)) ] )
def google_console_search(self, key, **kwargs): if not request.website.google_search_console: logger.warning('Google Search Console not enable') raise werkzeug.exceptions.NotFound() trusted = request.website.google_search_console.lstrip( 'google').rstrip('.html') if key != trusted: if key.startswith(trusted): request.website.sudo( ).google_search_console = "google%s.html" % key else: logger.warning('Google Search Console %s not recognize' % key) raise werkzeug.exceptions.NotFound() return request.make_response("google-site-verification: %s" % request.website.google_search_console)
def _generate_report(self, user_input, download=True): report = request.env.ref('survey.certification_report').with_user( SUPERUSER_ID)._render_qweb_pdf([user_input.id], data={'report_type': 'pdf'})[0] report_content_disposition = content_disposition('Certification.pdf') if not download: content_split = report_content_disposition.split(';') content_split[0] = 'inline' report_content_disposition = ';'.join(content_split) return request.make_response(report, headers=[ ('Content-Type', 'application/pdf'), ('Content-Length', len(report)), ('Content-Disposition', report_content_disposition), ])
def web_check_session(self, *args, **kwargs): json_result = [] # Double check session ir_session_obj = request.env['ir.session'].sudo() session_history = ir_session_obj.search([ ('session_id', '=', request.session.sid), ('user_id', '=', request.session.uid), ]) if session_history and not session_history.is_logged_in: request.session.logout() # Check current user's session if request.session.uid is None: json_result.append({'result': 'true'}) else: json_result.append({'result': 'false'}) content = simplejson.dumps(json_result) return request.make_response( content, [('Content-Type', 'application/json;charset=utf-8')])
def service_worker(self): """ Returns a ServiceWorker javascript file scoped for website_event """ sw_file = get_module_resource('website_event_track', 'static/src/js/service_worker.js') with open(sw_file, 'r') as fp: body = fp.read() js_cdn_url = 'undefined' if request.website.cdn_activated: cdn_url = request.website.cdn_url.replace('"', '%22').replace( '\x5c', '%5C') js_cdn_url = '"%s"' % cdn_url body = body.replace('__FLECTRA_CDN_URL__', js_cdn_url) response = request.make_response(body, [ ('Content-Type', 'text/javascript'), ('Service-Worker-Allowed', url_for('/event')), ]) return response
def get_user_profile_avatar(self, user_id, field='image_256', width=0, height=0, crop=False, **post): if field not in ('image_128', 'image_256'): return werkzeug.exceptions.Forbidden() can_sudo = self._check_avatar_access(user_id, **post) if can_sudo: status, headers, image_base64 = request.env['ir.http'].sudo( ).binary_content(model='res.users', id=user_id, field=field, default_mimetype='image/png') else: status, headers, image_base64 = request.env[ 'ir.http'].binary_content(model='res.users', id=user_id, field=field, default_mimetype='image/png') if status == 301: return request.env['ir.http']._response_by_status( status, headers, image_base64) if status == 304: return werkzeug.wrappers.Response(status=304) if not image_base64: image_base64 = self._get_default_avatar() if not (width or height): width, height = tools.image_guess_size_from_field_name(field) image_base64 = tools.image_process(image_base64, size=(int(width), int(height)), crop=crop) content = base64.b64decode(image_base64) headers = http.set_safe_image_headers(headers, content) response = request.make_response(content, headers) response.status_code = status return response
def download_document(self,model,field,id,filename=None, **kw): """ Download link for files stored as binary fields. :param str model: name of the model to fetch the binary from :param str field: binary field :param str id: id of the record from which to fetch the binary :param str filename: field holding the file's name, if any :returns: :class:`werkzeug.wrappers.Response` """ Model = request.registry[model] cr, uid, context = request.cr, request.uid, request.context fields = [field] res = Model.read(cr, uid, [int(id)], fields, context)[0] filecontent = base64.b64decode(res.get(field) or '') if not filecontent: return request.not_found() else: if not filename: filename = '%s_%s' % (model.replace('.', '_'), id) return request.make_response(filecontent, [('Content-Type', 'application/pdf'), ('Content-Disposition', content_disposition(filename))])
def get_report(self, **kwargs): uid = request.session.uid gst_report_obj = request.env['gst.report'].sudo(uid) data = { 'from_date': kwargs['from_date'], 'to_date': kwargs['to_date'], 'company_id': int(kwargs['company_id']), 'year': kwargs['year'], 'month': kwargs['month'], 'summary_type': kwargs['summary_type'], } utc_tz = pytz.timezone('UTC') tz = pytz.timezone( request.env.user.tz) if request.env.user.tz else pytz.utc def utc_to_local_zone(naive_datetime): utc_dt = utc_tz.localize(naive_datetime, is_dst=False) return utc_dt.astimezone(tz) create_date = datetime.strptime( datetime.today().strftime(DEFAULT_SERVER_DATETIME_FORMAT), DEFAULT_SERVER_DATETIME_FORMAT) company_id = request.env['res.company'].browse(int(data['company_id'])) gst_file_name = '' if data['summary_type'] == 'gstr1': gst_file_name = _('GSTR-1') elif data['summary_type'] == 'gstr2': gst_file_name = _('GSTR-2') filename = gst_file_name + _('_%s_%s-%s_%s.xlsx') % ( company_id.vat, datetime.today().strftime("%B"), data['year'], utc_to_local_zone(create_date).strftime("%d/%m/%Y %H:%M:%S")) response = request.make_response( None, headers=[('Content-Type', 'application/vnd.ms-excel'), ('Content-Disposition', 'attachment; filename=' + filename + ';')]) gst_report_obj.print_report(data, 1, response) return response