def slides_embed(self, slide_id, page="1", **kw): # Note : don't use the 'model' in the route (use 'slide_id'), otherwise if public cannot access the embedded # slide, the error will be the website.403 page instead of the one of the website_slides.embed_slide. # Do not forget the rendering here will be displayed in the embedded iframe # determine if it is embedded from external web page referrer_url = request.httprequest.headers.get('Referer', '') base_url = request.env['ir.config_parameter'].sudo().get_param( 'web.base.url') is_embedded = referrer_url and not bool( base_url in referrer_url) or False # try accessing slide, and display to corresponding template try: slide = request.env['slide.slide'].browse(slide_id) if is_embedded: request.env['slide.embed'].sudo().add_embed_url( slide.id, referrer_url) values = self._get_slide_detail(slide) values['page'] = page values['is_embedded'] = is_embedded if not values.get('private'): self._set_viewed_slide(slide, 'embed') return request.render('website_slides.embed_slide', values) except AccessError: # TODO : please, make it clean one day, or find another secure way to detect # if the slide can be embedded, and properly display the error message. slide = request.env['slide.slide'].sudo().browse(slide_id) return request.render('website_slides.embed_slide_forbidden', {'slide': slide})
def add(self, option_id, order_id, token, **post): Order = request.env['sale.order'].sudo().browse(order_id) if token != Order.access_token: return request.render('website.404') if Order.state not in ['draft', 'sent']: return request.render( 'website.http_error', { 'status_code': 'Forbidden', 'status_message': _('You cannot add options to a confirmed order.') }) Option = request.env['sale.order.option'].sudo().browse(option_id) vals = { 'price_unit': Option.price_unit, 'website_description': Option.website_description, 'name': Option.name, 'order_id': Order.id, 'product_id': Option.product_id.id, 'layout_category_id': Option.layout_category_id.id, 'product_uom_qty': Option.quantity, 'product_uom': Option.uom_id.id, 'discount': Option.discount, } OrderLine = request.env['sale.order.line'].sudo().create(vals) OrderLine._compute_tax_id() Option.write({'line_id': OrderLine.id}) return werkzeug.utils.redirect("/quote/%s/%s#pricing" % (Order.id, token))
def confirm_unsubscribe(self, channel, partner_id, token, **kw): subscriber = request.env['mail.channel.partner'].search([ ('channel_id', '=', channel.id), ('partner_id', '=', partner_id) ]) if not subscriber: partner = request.env['res.partner'].browse( partner_id).sudo().exists() # FIXME: remove try/except in master try: response = request.render( 'website_mail_channel.not_subscribed', {'partner_id': partner}) # make sure the rendering (and thus error if template is # missing) happens inside the try block response.flatten() return response except ValueError: return _( "The address %s is already unsubscribed or was never subscribed to any mailing list" ) % (partner.email) subscriber_token = channel._generate_action_token(partner_id, action='unsubscribe') if token != subscriber_token: return request.render( 'website_mail_channel.invalid_token_subscription') # remove partner channel.sudo().write({'channel_partner_ids': [(3, partner_id)]}) return request.render("website_mail_channel.confirmation_subscription", {'subscribing': False})
def question(self, forum, question, **post): # Hide posts from abusers (negative karma), except for moderators if not question.can_view: raise werkzeug.exceptions.NotFound() # Hide pending posts from non-moderators and non-creator user = request.env.user if question.state == 'pending' and user.karma < forum.karma_post and question.create_uid != user: raise werkzeug.exceptions.NotFound() # increment view counter question.sudo().set_viewed() if question.parent_id: redirect_url = "/forum/%s/question/%s" % (slug(forum), slug(question.parent_id)) return werkzeug.utils.redirect(redirect_url, 301) filters = 'question' values = self._prepare_forum_values(forum=forum, searches=post) values.update({ 'main_object': question, 'question': question, 'can_bump': (question.forum_id.allow_bump and not question.child_ids and (datetime.today() - datetime.strptime(question.write_date, tools.DEFAULT_SERVER_DATETIME_FORMAT)).days > 9), 'header': {'question_data': True}, 'filters': filters, 'reversed': reversed, }) return request.render("website_forum.post_description_full", values)
def tags(self, forum, tag_char=None, **post): # build the list of tag first char, with their value as tag_char param Ex : [('All', 'all'), ('C', 'c'), ('G', 'g'), ('Z', z)] first_char_tag = forum.get_tags_first_char() first_char_list = [(t, t.lower()) for t in first_char_tag if t.isalnum()] first_char_list.insert(0, (_('All'), 'all')) # get active first char tag active_char_tag = first_char_list[1][1] if len(first_char_list) > 1 else 'all' if tag_char: active_char_tag = tag_char.lower() # generate domain for searched tags domain = [('forum_id', '=', forum.id), ('posts_count', '>', 0)] order_by = 'name' if active_char_tag and active_char_tag != 'all': domain.append(('name', '=ilike', tools.escape_psql(active_char_tag)+'%')) order_by = 'posts_count DESC' tags = request.env['forum.tag'].search(domain, limit=None, order=order_by) # prepare values and render template values = self._prepare_forum_values(forum=forum, searches={'tags': True}, **post) values.update({ 'tags': tags, 'pager_tag_chars': first_char_list, 'active_char_tag': active_char_tag, }) return request.render("website_forum.tag", values)
def FieldTextHtml(self, model=None, res_id=None, field=None, callback=None, **kwargs): kwargs.update(model=model, res_id=res_id, field=field, datarecord=json.loads(kwargs['datarecord']), debug=request.debug) for k in kwargs: if isinstance(kwargs[k], pycompat.string_types) and kwargs[k].isdigit(): kwargs[k] = int(kwargs[k]) trans = dict(lang=kwargs.get('lang', request.env.context.get('lang')), translatable=kwargs.get('translatable'), edit_translations=kwargs.get('edit_translations'), editable=kwargs.get('enable_editor')) kwargs.update(trans) record = None if model and kwargs.get('res_id'): record = request.env[model].with_context(trans).browse( kwargs.get('res_id')) kwargs.update(content=record and getattr(record, field) or "") return request.render(kwargs.get("template") or "web_editor.FieldTextHtml", kwargs, uid=request.uid)
def statistics_shorten_url(self, code, **post): code = request.env['link.tracker.code'].search([('code', '=', code)], limit=1) if code: return request.render("website_links.graphs", code.link_id.read()[0]) else: return werkzeug.utils.redirect('', 301)
def event_agenda(self, event, tag=None, **post): event = event.with_context(tz=event.date_tz or 'UTC') local_tz = pytz.timezone(event.date_tz or 'UTC') days_tracks = collections.defaultdict(lambda: []) for track in event.track_ids.sorted( lambda track: (track.date or '', bool(track.location_id))): if not track.date: continue date = fields.Datetime.from_string( track.date).replace(tzinfo=pytz.utc).astimezone(local_tz) days_tracks[str(date)[:10]].append(track) days = {} tracks_by_days = {} for day, tracks in days_tracks.items(): tracks_by_days[day] = tracks days[day] = self._prepare_calendar(event, tracks) return request.render( "website_event_track.agenda", { 'event': event, 'days': days, 'tracks_by_days': tracks_by_days, 'tag': tag })
def web_auth_reset_password(self, *args, **kw): qcontext = self.get_auth_signup_qcontext() if not qcontext.get('token') and not qcontext.get( 'reset_password_enabled'): raise werkzeug.exceptions.NotFound() if 'error' not in qcontext and request.httprequest.method == 'POST': try: if qcontext.get('token'): self.do_signup(qcontext) return super(AuthSignupHome, self).web_login(*args, **kw) else: login = qcontext.get('login') assert login, _("No login provided.") _logger.info( "Password reset attempt for <%s> by user <%s> from %s", login, request.env.user.login, request.httprequest.remote_addr) request.env['res.users'].sudo().reset_password(login) qcontext['message'] = _( "An email has been sent with credentials to reset your password" ) except SignupError: qcontext['error'] = _("Could not reset your password") _logger.exception('error when resetting password') except Exception as e: qcontext['error'] = str(e) response = request.render('auth_signup.reset_password', qcontext) response.headers['X-Frame-Options'] = 'DENY' return response
def channel_list(self, **kw): # display the list of the channel channels = request.env['im_livechat.channel'].search([ ('website_published', '=', True) ]) values = {'channels': channels} return request.render('website_livechat.channel_list_page', values)
def survey_reporting(self, survey, token=None, **post): '''Display survey Results & Statistics for given survey.''' result_template = 'survey.result' current_filters = [] filter_display_data = [] filter_finish = False if not survey.user_input_ids or not [ input_id.id for input_id in survey.user_input_ids if input_id.state != 'new' ]: result_template = 'survey.no_result' if 'finished' in post: post.pop('finished') filter_finish = True if post or filter_finish: filter_data = self.get_filter_data(post) current_filters = survey.filter_input_ids(filter_data, filter_finish) filter_display_data = survey.get_filter_display_data(filter_data) return request.render( result_template, { 'survey': survey, 'survey_dict': self.prepare_result_dict( survey, current_filters), 'page_range': self.page_range, 'current_filters': current_filters, 'filter_display_data': filter_display_data, 'filter_finish': filter_finish })
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 questions(self, forum, tag=None, page=1, filters='all', sorting=None, search='', post_type=None, **post): Post = request.env['forum.post'] domain = [('forum_id', '=', forum.id), ('parent_id', '=', False), ('state', '=', 'active')] if search: domain += ['|', ('name', 'ilike', search), ('content', 'ilike', search)] if tag: domain += [('tag_ids', 'in', tag.id)] if filters == 'unanswered': domain += [('child_ids', '=', False)] elif filters == 'followed': domain += [('message_partner_ids', '=', request.env.user.partner_id.id)] if post_type: domain += [('post_type', '=', post_type)] if sorting: # check that sorting is valid # retro-compatibily for V8 and google links try: Post._generate_order_by(sorting, None) except ValueError: sorting = False if not sorting: sorting = forum.default_order question_count = Post.search_count(domain) if tag: url = "/forum/%s/tag/%s/questions" % (slug(forum), slug(tag)) else: url = "/forum/%s" % slug(forum) url_args = { 'sorting': sorting } if search: url_args['search'] = search if filters: url_args['filters'] = filters pager = request.website.pager(url=url, total=question_count, page=page, step=self._post_per_page, scope=self._post_per_page, url_args=url_args) question_ids = Post.search(domain, limit=self._post_per_page, offset=pager['offset'], order=sorting) values = self._prepare_forum_values(forum=forum, searches=post, header={'ask_hide': not forum.active}) values.update({ 'main_object': tag or forum, 'question_ids': question_ids, 'question_count': question_count, 'pager': pager, 'tag': tag, 'filters': filters, 'sorting': sorting, 'search': search, 'post_type': post_type, }) return request.render("website_forum.forum_index", values)
def event_register(self, event, **post): values = { 'event': event, 'main_object': event, 'range': range, 'registrable': event._is_event_registrable() } return request.render("website_event.event_description_full", values)
def forum_post(self, forum, post_type=None, **post): user = request.env.user if post_type not in ['question', 'link', 'discussion']: # fixme: make dynamic return werkzeug.utils.redirect('/forum/%s' % slug(forum)) if not user.email or not tools.single_email_re.match(user.email): return werkzeug.utils.redirect("/forum/%s/user/%s/edit?email_required=1" % (slug(forum), request.session.uid)) values = self._prepare_forum_values(forum=forum, searches={}, header={'ask_hide': True}) return request.render("website_forum.new_%s" % post_type, values)
def event_track_view(self, event, track, **post): track = track.sudo().with_context(tz=event.date_tz or 'UTC') values = { 'track': track, 'event': track.event_id, 'main_object': track } return request.render("website_event_track.track_view", values)
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 badges(self, forum, **searches): Badge = request.env['gamification.badge'] badges = Badge.sudo().search([('challenge_ids.category', '=', 'forum')]) badges = sorted(badges, key=lambda b: b.stat_count_distinct, reverse=True) values = self._prepare_forum_values(forum=forum, searches={'badges': True}) values.update({ 'badges': badges, }) return request.render("website_forum.badge", values)
def mailing(self, mailing_id, email=None, res_id=None, **post): mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id) if mailing.exists(): if mailing.mailing_model_name == 'mail.mass_mailing.contact': contacts = request.env['mail.mass_mailing.contact'].sudo( ).search([('email', '=', email)]) return request.render('website_mass_mailing.page_unsubscribe', { 'contacts': contacts, 'email': email, 'mailing_id': mailing_id }) else: super(MassMailController, self).mailing(mailing_id, email=email, res_id=res_id, **post) return request.render('website_mass_mailing.page_unsubscribed')
def portal_my_task(self, task_id=None, **kw): task = request.env['project.task'].browse(task_id) vals = { 'task': task, 'user': request.env.user } history = request.session.get('my_tasks_history', []) vals.update(get_records_pager(history, task)) return request.render("project.portal_my_task", vals)
def partners_detail(self, partner_id, **post): _, partner_id = unslug(partner_id) if partner_id: partner = request.env['res.partner'].sudo().browse(partner_id) if partner.exists() and partner.website_published: # TODO should be done with access rules values = {} values['main_object'] = values['partner'] = partner return request.render("website_membership.partner", values) return self.members(**post)
def edit_profile(self, forum, user, **kwargs): countries = request.env['res.country'].search([]) values = self._prepare_forum_values(forum=forum, searches=kwargs) values.update({ 'email_required': kwargs.get('email_required'), 'countries': countries, 'notifications': self._get_notifications(), }) return request.render("website_forum.edit_profile", values)
def partners_detail(self, partner_id, **post): _, partner_id = unslug(partner_id) if partner_id: partner = request.env['res.partner'].sudo().browse(partner_id) if partner.exists() and partner.website_published: values = {} values['main_object'] = values['partner'] = partner return request.render("website_customer.details", values) return self.customers(**post)
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 post(self, toc, post, **kwargs): # TODO: implement a redirect instead of crash assert post.documentation_toc_id == toc, "Wrong post!" value = { 'toc': toc, 'post': post, 'main_object': post, 'forum': post.forum_id } return request.render("website_forum_doc.documentation_post", value)
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 question_ask_for_close(self, forum, question, **post): reasons = request.env['forum.post.reason'].search([('reason_type', '=', 'basic')]) values = self._prepare_forum_values(**post) values.update({ 'question': question, 'forum': forum, 'reasons': reasons, }) return request.render("website_forum.close_post", values)
def _check_deadline(self, user_input): '''Prevent opening of the survey if the deadline has turned out ! This will NOT disallow access to users who have already partially filled the survey !''' deadline = user_input.deadline if deadline: dt_deadline = fields.Datetime.from_string(deadline) dt_now = datetime.now() if dt_now > dt_deadline: # survey is not open anymore return request.render("survey.notopen") return None
def print_survey(self, survey, token=None, **post): '''Display an survey in printable view; if <token> is set, it will grab the answers of the user_input_id that has <token>.''' return request.render( 'survey.survey_print', { 'survey': survey, 'token': token, 'page_nr': 0, 'quizz_correction': True if survey.quizz_mode and token else False })
def jobs_apply(self, job, **kwargs): error = {} default = {} if 'website_hr_recruitment_error' in request.session: error = request.session.pop('website_hr_recruitment_error') default = request.session.pop('website_hr_recruitment_default') return request.render("website_hr_recruitment.apply", { 'job': job, 'error': error, 'default': default, })