def validate_email(self, token, id, email, forum_id=None, **kwargs): if forum_id: try: forum_id = int(forum_id) except ValueError: forum_id = None done = request.env['res.users'].sudo().browse( int(id)).process_forum_validation_token(token, email, forum_id=forum_id)[0] if done: request.session['validation_email_done'] = True if forum_id: return request.redirect("/forum/%s" % int(forum_id)) return request.redirect('/forum')
def account(self, redirect=None, **post): values = self._prepare_portal_layout_values() partner = request.env.user.partner_id values.update({ 'error': {}, 'error_message': [], }) if post: error, error_message = self.details_form_validate(post) values.update({'error': error, 'error_message': error_message}) values.update(post) if not error: values = { key: post[key] for key in self.MANDATORY_BILLING_FIELDS } values.update({ key: post[key] for key in self.OPTIONAL_BILLING_FIELDS if key in post }) values.update({'zip': values.pop('zipcode', '')}) partner.sudo().write(values) if redirect: return request.redirect(redirect) return request.redirect('/my/home') countries = request.env['res.country'].sudo().search([]) states = request.env['res.country.state'].sudo().search([]) values.update({ 'partner': partner, 'countries': countries, 'states': states, 'has_check_vat': hasattr(request.env['res.partner'], 'check_vat'), 'redirect': redirect, 'page_name': 'my_details', }) response = request.render("portal.portal_my_details", values) response.headers['X-Frame-Options'] = 'DENY' return response
def product_compare(self, **post): values = {} product_ids = [ int(i) for i in post.get('products', '').split(',') if i.isdigit() ] if not product_ids: return request.redirect("/shop") # use search to check read access on each record/ids products = request.env['product.product'].search([('id', 'in', product_ids)]) values['products'] = products.with_context(display_default_code=False) res = {} for num, product in enumerate(products): for var in product.attribute_line_ids: cat_name = var.attribute_id.category_id.name or _( 'Uncategorized') att_name = var.attribute_id.name if not product.attribute_value_ids: # create_variant = False continue res.setdefault(cat_name, {}).setdefault(att_name, [' - '] * len(products)) val = product.attribute_value_ids.filtered( lambda x: x.attribute_id == var.attribute_id) res[cat_name][att_name][num] = val[0].name values['specs'] = res values['compute_currency'] = self._get_compute_currency_and_context( )[0] return request.render("website_sale_comparison.product_compare", values)
def jobs_add(self, **kwargs): # avoid branding of website_description by setting rendering_bundle in context job = request.env['hr.job'].with_context(rendering_bundle=True).create( { 'name': _('Job Title'), }) return request.redirect("/jobs/detail/%s?enable_editor=1" % slug(job))
def registration_confirm(self, event, **post): order = request.website.sale_get_order(force_create=1) attendee_ids = set() registrations = self._process_registration_details(post) for registration in registrations: ticket = request.env['event.event.ticket'].sudo().browse( int(registration['ticket_id'])) cart_values = order.with_context( event_ticket_id=ticket.id, fixed_price=True)._cart_update( product_id=ticket.product_id.id, add_qty=1, registration_data=[registration]) attendee_ids |= set(cart_values.get('attendee_ids', [])) # free tickets -> order with amount = 0: auto-confirm, no checkout if not order.amount_total: order.action_confirm() # tde notsure: email sending ? attendees = request.env['event.registration'].browse( list(attendee_ids)).sudo() # clean context and session, then redirect to the confirmation page request.website.sale_reset() return request.render("website_event.registration_complete", { 'attendees': attendees, 'event': event, }) return request.redirect("/shop/checkout")
def actions_server(self, path_or_xml_id_or_id, **post): ServerActions = request.env['ir.actions.server'] action = action_id = None # find the action_id: either an xml_id, the path, or an ID if isinstance(path_or_xml_id_or_id, pycompat.string_types) and '.' in path_or_xml_id_or_id: action = request.env.ref(path_or_xml_id_or_id, raise_if_not_found=False) if not action: action = ServerActions.search( [('website_path', '=', path_or_xml_id_or_id), ('website_published', '=', True)], limit=1) if not action: try: action_id = int(path_or_xml_id_or_id) except ValueError: pass # check it effectively exists if action_id: action = ServerActions.browse(action_id).exists() # run it, return only if we got a Response object if action: if action.state == 'code' and action.website_published: action_res = action.run() if isinstance(action_res, werkzeug.wrappers.Response): return action_res return request.redirect('/')
def invoice_pay_token(self, invoice_id, pm_id=None, **kwargs): """ Use a token to perform a s2s transaction """ error_url = kwargs.get('error_url', '/my') success_url = kwargs.get('success_url', '/my') access_token = kwargs.get('access_token') params = {} if access_token: params['access_token'] = access_token invoice_sudo = request.env['account.invoice'].sudo().browse( invoice_id).exists() if not invoice_sudo: params['error'] = 'pay_invoice_invalid_doc' return request.redirect(_build_url_w_params(error_url, params)) try: token = request.env['payment.token'].sudo().browse(int(pm_id)) except (ValueError, TypeError): token = False token_owner = invoice_sudo.partner_id if request.env.user == request.env.ref( 'base.public_user') else request.env.user.partner_id if not token or token.partner_id != token_owner: params['error'] = 'pay_invoice_invalid_token' return request.redirect(_build_url_w_params(error_url, params)) # find an existing tx or create a new one tx = request.env['payment.transaction'].sudo( )._check_or_create_invoice_tx( invoice_sudo, token.acquirer_id, payment_token=token, tx_type='server2server', ) # set the transaction id into the session request.session['portal_invoice_%s_transaction_id' % invoice_sudo.id] = tx.id # proceed to the payment res = tx.confirm_invoice_token() if tx.state != 'authorized' or not tx.acquirer_id.capture_manually: if res is not True: params['error'] = res return request.redirect(_build_url_w_params(error_url, params)) params['success'] = 'pay_invoice' return request.redirect(_build_url_w_params(success_url, params))
def event(self, event, **post): if event.menu_id and event.menu_id.child_id: target_url = event.menu_id.child_id[0].url else: target_url = '/event/%s/register' % str(event.id) if post.get('enable_editor') == '1': target_url += '?enable_editor=1' return request.redirect(target_url)
def post_toc_ok(self, forum, post_id, toc_id, **kwargs): assert request.env.user.karma >= 200, 'Not enough karma, you need 200 to promote a documentation.' stage = request.env['forum.documentation.toc'].search([], limit=1) request.env['forum.post'].browse(int(post_id)).write({ 'documentation_toc_id': toc_id and int(toc_id) or False, 'documentation_stage_id': stage and stage.id }) return request.redirect('/forum/' + str(forum.id) + '/question/' + str(post_id))
def portal_chatter_post(self, res_model, res_id, message, **kw): url = request.httprequest.referrer if message: # message is received in plaintext and saved in html message = plaintext2html(message) _message_post_helper(res_model, int(res_id), message, **kw) url = url + "#discussion" return request.redirect(url)
def portal_my_invoice_detail(self, invoice_id, access_token=None, **kw): try: invoice_sudo = self._invoice_check_access(invoice_id, access_token) except AccessError: return request.redirect('/my') values = self._invoice_get_page_view_values(invoice_sudo, access_token, **kw) return request.render("account.portal_invoice_page", values)
def post_toggle_correct(self, forum, post, **kwargs): if post.parent_id is False: return request.redirect('/') if not request.session.uid: return {'error': 'anonymous_user'} # set all answers to False, only one can be accepted (post.parent_id.child_ids - post).write(dict(is_correct=False)) post.is_correct = not post.is_correct return post.is_correct
def portal_order_page(self, order=None, access_token=None, **kw): try: order_sudo = self._order_check_access(order, access_token=access_token) except AccessError: return request.redirect('/my') values = self._order_get_page_view_values(order_sudo, access_token, **kw) return request.render("sale.portal_order_page", values)
def payment(self, **post): order = request.website.sale_get_order() carrier_id = post.get('carrier_id') if carrier_id: carrier_id = int(carrier_id) if order: order._check_carrier_quotation(force_carrier_id=carrier_id) if carrier_id: return request.redirect("/shop/payment") return super(WebsiteSaleDelivery, self).payment(**post)
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 portal_my_purchase_order(self, order_id=None, **kw): order = request.env['purchase.order'].browse(order_id) try: order.check_access_rights('read') order.check_access_rule('read') except AccessError: return request.redirect('/my') history = request.session.get('my_purchases_history', []) values = { 'order': order.sudo(), } values.update(get_records_pager(history, order)) return request.render("purchase.portal_my_purchase_order", values)
def slide_download(self, slide, **kw): slide = slide.sudo() 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 request.redirect('/web/login?redirect=/slides/slide/%s' % (slide.id)) return request.render("website.403")
def slides_index(self, *args, **post): """ Returns a list of available channels: if only one is available, redirects directly to its slides """ channels = request.env['slide.channel'].search([], order='sequence, id') if not channels: return request.render("website_slides.channel_not_found") elif len(channels) == 1: return request.redirect("/slides/%s" % channels.id) return request.render('website_slides.channels', { 'channels': channels, 'user': request.env.user, 'is_public_user': request.env.user == request.website.user_id })
def _serve_fallback(cls, exception): # serve attachment before parent = super(Http, cls)._serve_fallback(exception) if parent: # attachment return parent website_page = cls._serve_page() if website_page: return website_page redirect = cls._serve_redirect() if redirect: return request.redirect(_build_url_w_params(redirect.url_to, request.params), code=redirect.type) return False
def portal_order_report(self, order_id, access_token=None, **kw): try: order_sudo = self._order_check_access(order_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( 'sale.action_report_saleorder').sudo().render_qweb_pdf( [order_sudo.id])[0] pdfhttpheaders = [ ('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ] return request.make_response(pdf, headers=pdfhttpheaders)
def reset_template(self, templates, redirect='/'): templates = request.httprequest.form.getlist('templates') modules_to_update = [] for temp_id in templates: view = request.env['ir.ui.view'].browse(int(temp_id)) if view.page: continue view.model_data_id.write({'noupdate': False}) if view.model_data_id.module not in modules_to_update: modules_to_update.append(view.model_data_id.module) if modules_to_update: modules = request.env['ir.module.module'].sudo().search([ ('name', 'in', modules_to_update) ]) if modules: modules.button_immediate_upgrade() return request.redirect(redirect)
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 index(self, **kw): homepage = request.website.homepage_id if homepage and (homepage.sudo().is_visible or request.env.user.has_group('base.group_user') ) and homepage.url != '/': return request.env['ir.http'].reroute(homepage.url) website_page = request.env['ir.http']._serve_page() if website_page: return website_page else: top_menu = request.website.menu_id first_menu = top_menu and top_menu.child_id and top_menu.child_id.filtered( lambda menu: menu.is_visible) if first_menu and first_menu[0].url not in ('/', '') and ( not (first_menu[0].url.startswith(('/?', '/#', ' ')))): return request.redirect(first_menu[0].url) raise request.not_found()
def start_survey(self, survey, token=None, **post): UserInput = request.env['survey.user_input'] # Test mode if token and token == "phantom": _logger.info("[survey] Phantom mode") user_input = UserInput.create({ 'survey_id': survey.id, 'test_entry': True }) data = {'survey': survey, 'page': None, 'token': user_input.token} return request.render('survey.survey_init', data) # END Test mode # Controls if the survey can be displayed errpage = self._check_bad_cases(survey, token=token) if errpage: return errpage # Manual surveying if not token: vals = {'survey_id': survey.id} if request.website.user_id != request.env.user: vals['partner_id'] = request.env.user.partner_id.id user_input = UserInput.create(vals) else: user_input = UserInput.sudo().search([('token', '=', token)], limit=1) if not user_input: return request.render("website.403") # Do not open expired survey errpage = self._check_deadline(user_input) if errpage: return errpage # Select the right page if user_input.state == 'new': # Intro page data = {'survey': survey, 'page': None, 'token': user_input.token} return request.render('survey.survey_init', data) else: return request.redirect('/survey/fill/%s/%s' % (survey.id, user_input.token))
def slide_set_promoted(self, slide): slide.channel_id.promoted_slide_id = slide.id return request.redirect("/slides/%s" % slide.channel_id.id)
def theme_customize_reload(self, href, enable, disable): self.theme_customize(enable and enable.split(",") or [], disable and disable.split(",") or []) return request.redirect( href + ("&theme=true" if "#" in href else "#theme=true"))
def blog_post(self, blog, blog_post, tag_id=None, page=1, enable_editor=None, **post): """ Prepare all values to display the blog. :return dict values: values for the templates, containing - 'blog_post': browse of the current post - 'blog': browse of the current blog - 'blogs': list of browse records of blogs - 'tag': current tag, if tag_id in parameters - 'tags': all tags, for tag-based navigation - 'pager': a pager on the comments - 'nav_list': a dict [year][month] for archives navigation - 'next_post': next blog post, to direct the user towards the next interesting post """ BlogPost = request.env['blog.post'] date_begin, date_end = post.get('date_begin'), post.get('date_end') pager_url = "/blogpost/%s" % blog_post.id pager = request.website.pager(url=pager_url, total=len(blog_post.website_message_ids), page=page, step=self._post_comment_per_page, scope=7) pager_begin = (page - 1) * self._post_comment_per_page pager_end = page * self._post_comment_per_page comments = blog_post.website_message_ids[pager_begin:pager_end] tag = None if tag_id: tag = request.env['blog.tag'].browse(int(tag_id)) blog_url = QueryURL('', ['blog', 'tag'], blog=blog_post.blog_id, tag=tag, date_begin=date_begin, date_end=date_end) if not blog_post.blog_id.id == blog.id: return request.redirect("/blog/%s/post/%s" % (slug(blog_post.blog_id), slug(blog_post))) tags = request.env['blog.tag'].search([]) # Find next Post all_post = BlogPost.search([('blog_id', '=', blog.id)]) if not request.env.user.has_group('website.group_website_designer'): all_post = all_post.filtered( lambda r: r.post_date <= fields.Datetime.now()) if blog_post not in all_post: return request.redirect("/blog/%s" % (slug(blog_post.blog_id))) # should always return at least the current post all_post_ids = all_post.ids current_blog_post_index = all_post_ids.index(blog_post.id) nb_posts = len(all_post_ids) next_post_id = all_post_ids[(current_blog_post_index + 1) % nb_posts] if nb_posts > 1 else None next_post = next_post_id and BlogPost.browse(next_post_id) or False values = { 'tags': tags, 'tag': tag, 'blog': blog, 'blog_post': blog_post, 'blog_post_cover_properties': json.loads(blog_post.cover_properties), 'main_object': blog_post, 'nav_list': self.nav_list(blog), 'enable_editor': enable_editor, 'next_post': next_post, 'next_post_cover_properties': json.loads(next_post.cover_properties) if next_post else {}, 'date': date_begin, 'blog_url': blog_url, 'pager': pager, 'comments': comments, } response = request.render("website_blog.blog_post_complete", values) request.session[request.session.sid] = request.session.get( request.session.sid, []) if not (blog_post.id in request.session[request.session.sid]): request.session[request.session.sid].append(blog_post.id) # Increase counter blog_post.sudo().write({ 'visits': blog_post.visits + 1, }) return response
def _dispatch(cls): """ Before executing the endpoint method, add website params on request, such as - current website (record) - multilang support (set on cookies) - geoip dict data are added in the session Then follow the parent dispatching. Reminder : Do not use `request.env` before authentication phase, otherwise the env set on request will be created with uid=None (and it is a lazy property) """ request.routing_iteration = getattr(request, 'routing_iteration', 0) + 1 func = None routing_error = None # locate the controller method try: if request.httprequest.method == 'GET' and '//' in request.httprequest.path: new_url = request.httprequest.path.replace( '//', '/') + '?' + request.httprequest.query_string.decode( 'utf-8') return werkzeug.utils.redirect(new_url, 301) rule, arguments = cls._find_handler(return_rule=True) func = rule.endpoint request.is_frontend = func.routing.get('website', False) except werkzeug.exceptions.NotFound as e: # either we have a language prefixed route, either a real 404 # in all cases, website processes them request.is_frontend = True routing_error = e request.is_frontend_multilang = ( request.is_frontend and (not func or (func and func.routing.get( 'multilang', func.routing['type'] == 'http')))) cls._geoip_setup_resolver() cls._geoip_resolve() # check authentication level try: if func: cls._authenticate(func.routing['auth']) elif request.uid is None and request.is_frontend: cls._auth_method_public() except Exception as e: return cls._handle_exception(e) # For website routes (only), add website params on `request` cook_lang = request.httprequest.cookies.get('frontend_lang') if request.is_frontend: request.redirect = lambda url, code=302: werkzeug.utils.redirect( url_for(url), code) cls._add_dispatch_parameters(func) path = request.httprequest.path.split('/') if request.routing_iteration == 1: is_a_bot = cls.is_a_bot() nearest_lang = not func and cls.get_nearest_lang(path[1]) url_lang = nearest_lang and path[1] # if lang in url but not the displayed or default language --> change or remove # or no lang in url, and lang to dispay not the default language --> add lang # and not a POST request # and not a bot or bot but default lang in url if ((url_lang and (url_lang != request.lang or url_lang == cls._get_default_lang().code)) or (not url_lang and request.is_frontend_multilang and request.lang != cls._get_default_lang().code) and request.httprequest.method != 'POST') \ and (not is_a_bot or (url_lang and url_lang == cls._get_default_lang().code)): if url_lang: path.pop(1) if request.lang != cls._get_default_lang().code: path.insert(1, request.lang) path = '/'.join(path) or '/' routing_error = None redirect = request.redirect( path + '?' + request.httprequest.query_string.decode('utf-8')) redirect.set_cookie('frontend_lang', request.lang) return redirect elif url_lang: request.uid = None path.pop(1) routing_error = None return cls.reroute('/'.join(path) or '/') if request.lang == cls._get_default_lang().code: context = dict(request.context) context['edit_translations'] = False request.context = context if routing_error: return cls._handle_exception(routing_error) # removed cache for auth public result = super(IrHttp, cls)._dispatch() if request.is_frontend and cook_lang != request.lang and hasattr( result, 'set_cookie'): result.set_cookie('frontend_lang', request.lang) return result