def question(self, forum, question, **post): if not forum.active: return request.render("website_forum.header", {'forum': forum}) # 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() - question.write_date).days > 9), 'header': {'question_data': True}, 'filters': filters, 'reversed': reversed, }) return request.render("website_forum.post_description_full", values)
def sitemap_partners(env, rule, qs): if not qs or qs.lower() in '/partners': yield {'loc': '/partners'} Grade = env['res.partner.grade'] dom = [('website_published', '=', True)] dom += sitemap_qs2dom(qs=qs, route='/partners/grade/', field=Grade._rec_name) for grade in env['res.partner.grade'].search(dom): loc = '/partners/grade/%s' % slug(grade) if not qs or qs.lower() in loc: yield {'loc': loc} partners_dom = [('is_company', '=', True), ('grade_id', '!=', False), ('website_published', '=', True), ('grade_id.website_published', '=', True), ('country_id', '!=', False)] dom += sitemap_qs2dom(qs=qs, route='/partners/country/') countries = env['res.partner'].sudo().read_group( partners_dom, fields=['id', 'country_id'], groupby='country_id') for country in countries: loc = '/partners/country/%s' % slug(country['country_id']) if not qs or qs.lower() in loc: yield {'loc': loc}
def post_mark_as_offensive(self, forum, post, **kwargs): post.mark_as_offensive(reason_id=int(kwargs.get('reason_id', False))) url = '' if post.parent_id: url = "/forum/%s/question/%s/#answer-%s" % (slug(forum), post.parent_id.id, post.id) else: url = "/forum/%s/question/%s" % (slug(forum), slug(post)) return werkzeug.utils.redirect(url)
def post_accept(self, forum, post, **kwargs): url = "/forum/%s/validation_queue" % (slug(forum)) if post.state == 'flagged': url = "/forum/%s/flagged_queue" % (slug(forum)) elif post.state == 'offensive': url = "/forum/%s/offensive_posts" % (slug(forum)) post.validate() return werkzeug.utils.redirect(url)
def post_comment(self, forum, post, **kwargs): question = post.parent_id if post.parent_id else post if kwargs.get('comment') and post.forum_id.id == forum.id: # TDE FIXME: check that post_id is the question or one of its answers body = tools.mail.plaintext2html(kwargs['comment']) post.with_context(mail_create_nosubscribe=True).message_post( body=body, message_type='comment', subtype='mt_comment') return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
def blog_post_copy(self, blog_post_id, **post): """ Duplicate a blog. :param blog_post_id: id of the blog post currently browsed. :return redirect to the new blog created """ new_blog_post = request.env['blog.post'].with_context( mail_create_nosubscribe=True).browse(int(blog_post_id)).copy() return werkzeug.utils.redirect( "/blog/%s/post/%s?enable_editor=1" % (slug(new_blog_post.blog_id), slug(new_blog_post)))
def forum_create(self, forum_name="New Forum", add_menu=False): forum_id = request.env['forum.forum'].create({ 'name': forum_name, 'website_id': request.website.id, }) if add_menu: request.env['website.menu'].create({ 'name': forum_name, 'url': "/forum/%s" % slug(forum_id), 'parent_id': request.website.menu_id.id, 'website_id': request.website.id, }) return "/forum/%s" % slug(forum_id)
def post_save(self, forum, post, **kwargs): if 'post_name' in kwargs and not kwargs.get('post_name').strip(): return request.render('website.http_error', {'status_code': _('Bad Request'), 'status_message': _('Title should not be empty.')}) post_tags = forum._tag_to_write_vals(kwargs.get('post_tags', '')) vals = { 'tag_ids': post_tags, 'name': kwargs.get('post_name'), 'content': kwargs.get('content'), 'content_link': kwargs.get('content_link'), } post.write(vals) question = post.parent_id if post.parent_id else post return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), slug(question)))
def __call__(self, path=None, path_args=None, **kw): path = path or self.path for key, value in self.args.items(): kw.setdefault(key, value) path_args = OrderedSet(path_args or []) | self.path_args paths, fragments = {}, [] for key, value in kw.items(): if value and key in path_args: if isinstance(value, models.BaseModel): paths[key] = slug(value) else: paths[key] = u"%s" % value elif value: if isinstance(value, list) or isinstance(value, set): fragments.append( werkzeug.url_encode([(key, item) for item in value])) else: fragments.append(werkzeug.url_encode([(key, value)])) for key in path_args: value = paths.get(key) if value is not None: path += '/' + key + '/' + value if fragments: path += '?' + '&'.join(fragments) return path
def test_08_survey_urls(self): def validate_url(url): """ Reference: https://github.com/django/django/blob/master/django/core/validators.py """ url_regex = re.compile( r'^https?://' # http:// or https:// r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain... r'localhost|' # localhost... r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|' # ...or ipv4 r'\[?[A-F0-9]*:[A-F0-9:]+\]?)' # ...or ipv6 r'(?::\d+)?' # optional port r'(?:/?|[/?]\S+)$', re.IGNORECASE) return True if url_regex.match(url) else False base_url = self.env['ir.config_parameter'].get_param('web.base.url') urltypes = {'public': 'start', 'print': 'print', 'result': 'results'} for urltype, urltxt in urltypes.items(): survey_url = getattr(self.survey1, urltype + '_url') survey_url_relative = getattr(self.survey1.with_context({'relative_url': True}), urltype + '_url') self.assertTrue(validate_url(survey_url)) url = "survey/%s/%s" % (urltxt, slug(self.survey1)) full_url = urls.url_join(base_url, url) self.assertEqual(full_url, survey_url) self.assertEqual('/' + url, survey_url_relative) if urltype == 'public': url_html = '<a href="%s">Click here to start survey</a>' self.assertEqual(url_html % full_url, getattr(self.survey1, urltype + '_url_html'), msg="Public URL is incorrect") self.assertEqual(url_html % ('/' + url), getattr(self.survey1.with_context({'relative_url': True}), urltype + '_url_html'), msg="Public URL is incorrect.")
def _compute_website_url(self): super(Slide, self)._compute_website_url() for slide in self: if slide.id: # avoid to perform a slug on a not yet saved record in case of an onchange. base_url = slide.channel_id.get_base_url() # link_tracker is not in dependencies, so use it to shorten url only if installed. if self.env.registry.get('link.tracker'): url = self.env['link.tracker'].sudo().create({ 'url': '%s/slides/slide/%s' % (base_url, slug(slide)), 'title': slide.name, }).short_url else: url = '%s/slides/slide/%s' % (base_url, slug(slide)) slide.website_url = url
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 _compute_website_url(self): super(Channel, self)._compute_website_url() for channel in self: if channel.id: # avoid to perform a slug on a not yet saved record in case of an onchange. base_url = channel.get_base_url() channel.website_url = '%s/slides/%s' % (base_url, slug(channel))
def blogs(self, page=1, **post): domain = request.website.website_domain() Blog = request.env['blog.blog'] blogs = Blog.search(domain, limit=2) if len(blogs) == 1: return werkzeug.utils.redirect('/blog/%s' % slug(blogs[0]), code=302) BlogPost = request.env['blog.post'] total = BlogPost.search_count(domain) pager = request.website.pager( url='/blog', total=total, page=page, step=self._blog_post_per_page, ) posts = BlogPost.search(domain, offset=(page - 1) * self._blog_post_per_page, limit=self._blog_post_per_page) blog_url = QueryURL('', ['blog', 'tag']) return request.render("website_blog.latest_blogs", { 'posts': posts, 'pager': pager, 'blog_url': blog_url, })
def _send_prepare_body(self): """ Short-circuit parent method for mail groups, replace the default footer with one appropriate for mailing-lists.""" if self.model == 'mail.channel' and self.res_id: # no super() call on purpose, no private links that could be quoted! channel = self.env['mail.channel'].browse(self.res_id) base_url = self.env['ir.config_parameter'].sudo().get_param( 'web.base.url') vals = { 'maillist': _('Mailing-List'), 'post_to': _('Post to'), 'unsub': _('Unsubscribe'), 'mailto': 'mailto:%s@%s' % (channel.alias_name, channel.alias_domain), 'group_url': '%s/groups/%s' % (base_url, slug(channel)), 'unsub_url': '%s/groups?unsubscribe' % (base_url, ), } footer = """_______________________________________________ %(maillist)s: %(group_url)s %(post_to)s: %(mailto)s %(unsub)s: %(unsub_url)s """ % vals body = tools.append_content_to_html(self.body, footer, container_tag='div') return body else: return super(MailMail, self)._send_prepare_body()
def thread_headers(self, group, page=1, mode='thread', date_begin=None, date_end=None, **post): if group.channel_type != 'channel': raise werkzeug.exceptions.NotFound() Message = request.env['mail.message'] domain = [('model', '=', 'mail.channel'), ('res_id', '=', group.id), ('message_type', '!=', 'notification')] if mode == 'thread': domain += [('parent_id', '=', False)] if date_begin and date_end: domain += [('date', '>=', date_begin), ('date', '<=', date_end)] pager = request.website.pager( url='/groups/%s' % slug(group), total=Message.search_count(domain), page=page, step=self._thread_per_page, url_args={'mode': mode, 'date_begin': date_begin or '', 'date_end': date_end or ''}, ) messages = Message.search(domain, limit=self._thread_per_page, offset=pager['offset']) values = { 'messages': messages, 'group': group, 'pager': pager, 'mode': mode, 'archives': self._get_archives(group.id), 'date_begin': date_begin, 'date_end': date_end, 'replies_per_page': self._replies_per_page, } return request.render('website_mail_channel.group_messages', 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 tags_list(tag_ids, current_tag): tag_ids = list(tag_ids) # required to avoid using the same list if current_tag in tag_ids: tag_ids.remove(current_tag) else: tag_ids.append(current_tag) tag_ids = request.env['blog.tag'].browse(tag_ids).exists() return ','.join(slug(tag) for tag in tag_ids)
def blog_post_create(self, blog_id, **post): # Use sudo so this line prevents both editor and admin to access blog from another website # as browse() will return the record even if forbidden by security rules but editor won't # be able to access it if not request.env['blog.blog'].browse( blog_id).sudo().can_access_from_current_website(): raise werkzeug.exceptions.NotFound() new_blog_post = request.env['blog.post'].create({ 'blog_id': blog_id, 'website_published': False, }) return werkzeug.utils.redirect( "/blog/%s/post/%s?enable_editor=1" % (slug(new_blog_post.blog_id), slug(new_blog_post)))
def sitemap_forum(env, rule, qs): Forum = env['forum.forum'] dom = sitemap_qs2dom(qs, '/forum', Forum._rec_name) dom += env['website'].get_current_website().website_domain() for f in Forum.search(dom): loc = '/forum/%s' % slug(f) if not qs or qs.lower() in loc: yield {'loc': loc}
def _get_menu_entries(self): """ Method returning menu entries to display on the website view of the event, possibly depending on some options in inheriting modules. """ self.ensure_one() return [ (_('Introduction'), False, 'website_event.template_intro'), (_('Location'), False, 'website_event.template_location'), (_('Register'), '/event/%s/register' % slug(self), False), ]
def sitemap_industry(env, rule, qs): if not qs or qs.lower() in '/customers': yield {'loc': '/customers'} Industry = env['res.partner.industry'] dom = sitemap_qs2dom(qs, '/customers/industry', Industry._rec_name) for industry in Industry.search(dom): loc = '/customers/industry/%s' % slug(industry) if not qs or qs.lower() in loc: yield {'loc': loc} dom = [('website_published', '=', True), ('assigned_partner_id', '!=', False), ('country_id', '!=', False)] dom += sitemap_qs2dom(qs, '/customers/country') countries = env['res.partner'].sudo().read_group(dom, ['id', 'country_id'], groupby='country_id') for country in countries: loc = '/customers/country/%s' % slug(country['country_id']) if not qs or qs.lower() in loc: yield {'loc': loc}
def _notify_specific_email_values(self, message): res = super(MailGroup, self)._notify_specific_email_values(message) try: headers = safe_eval(res.get('headers', dict())) except Exception: headers = {} base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') headers['List-Archive'] = '<%s/groups/%s>' % (base_url, slug(self)) headers['List-Subscribe'] = '<%s/groups>' % (base_url) headers['List-Unsubscribe'] = '<%s/groups?unsubscribe>' % (base_url,) res['headers'] = repr(headers) return res
def post_create(self, forum, post_parent=None, post_type=None, **post): if post_type == 'question' and not post.get('post_name', ''): return request.render('website.http_error', {'status_code': _('Bad Request'), 'status_message': _('Title should not be empty.')}) if post.get('content', '') == '<p><br></p>': return request.render('website.http_error', {'status_code': _('Bad Request'), 'status_message': _('Question should not be empty.')}) post_tag_ids = forum._tag_to_write_vals(post.get('post_tags', '')) if request.env.user.forum_waiting_posts_count: return werkzeug.utils.redirect("/forum/%s/ask" % slug(forum)) new_question = request.env['forum.post'].create({ 'forum_id': forum.id, 'name': post.get('post_name') or (post_parent and 'Re: %s' % (post_parent.name or '')) or '', 'content': post.get('content', False), 'content_link': post.get('content_link', False), 'parent_id': post_parent and post_parent.id or False, 'tag_ids': post_tag_ids, 'post_type': post_parent and post_parent.post_type or post_type, # tde check in selection field }) return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), post_parent and slug(post_parent) or new_question.id))
def _get_event_resource_urls(self, attendees): url_date_start = self.date_begin.strftime('%Y%m%dT%H%M%SZ') url_date_stop = self.date_end.strftime('%Y%m%dT%H%M%SZ') params = { 'action': 'TEMPLATE', 'text': self.name, 'dates': url_date_start + '/' + url_date_stop, 'details': self.name, } if self.address_id: params.update( location=self.sudo().address_id.contact_address.replace( '\n', ' ')) encoded_params = werkzeug.url_encode(params) google_url = GOOGLE_CALENDAR_URL + encoded_params iCal_url = '/event/%s/ics?%s' % (slug(self), encoded_params) return {'google_url': google_url, 'iCal_url': iCal_url}
def _create_menu(self, sequence, name, url, xml_id): if not url: newpath = self.env['website'].new_page(name + ' ' + self.name, template=xml_id, ispage=False)['url'] url = "/event/" + slug(self) + "/page/" + newpath[1:] menu = self.env['website.menu'].create({ 'name': name, 'url': url, 'parent_id': self.menu_id.id, 'sequence': sequence, 'website_id': self.website_id.id, }) return menu
def save_edited_profile(self, forum, user, **kwargs): values = { 'name': kwargs.get('name'), 'website': kwargs.get('website'), 'email': kwargs.get('email'), 'city': kwargs.get('city'), 'country_id': int(kwargs.get('country')) if kwargs.get('country') else False, 'website_description': kwargs.get('description'), } if 'clear_image' in kwargs: values['image'] = False elif kwargs.get('ufile'): image = kwargs.get('ufile').read() values['image'] = base64.b64encode(image) if request.uid == user.id: # the controller allows to edit only its own privacy settings; use partner management for other cases values['website_published'] = kwargs.get('website_published') == 'True' user.write(values) return werkzeug.utils.redirect("/forum/%s/user/%d" % (slug(forum), user.id))
def users(self, forum, page=1, **searches): User = request.env['res.users'] step = 30 tag_count = User.sudo().search_count([('karma', '>', 1), ('website_published', '=', True)]) pager = request.website.pager(url="/forum/%s/users" % slug(forum), total=tag_count, page=page, step=step, scope=30) user_obj = User.sudo().search([('karma', '>', 1), ('website_published', '=', True)], limit=step, offset=pager['offset'], order='karma DESC') # put the users in block of 3 to display them as a table users = [[] for i in range(len(user_obj) // 3 + 1)] for index, user in enumerate(user_obj): users[index // 3].append(user) searches['users'] = 'True' values = self._prepare_forum_values(forum=forum, searches=searches) values .update({ 'users': users, 'main_object': forum, 'notifications': self._get_notifications(), 'pager': pager, }) return request.render("website_forum.users", values)
def partners(self, country=None, grade=None, page=0, **post): country_all = post.pop('country_all', False) partner_obj = request.env['res.partner'] country_obj = request.env['res.country'] search = post.get('search', '') base_partner_domain = [('is_company', '=', True), ('grade_id', '!=', False), ('website_published', '=', True)] if not request.env['res.users'].has_group( 'website.group_website_publisher'): base_partner_domain += [('grade_id.website_published', '=', True)] if search: base_partner_domain += [ '|', ('name', 'ilike', search), ('website_description', 'ilike', search) ] # group by grade grade_domain = list(base_partner_domain) if not country and not country_all: country_code = request.session['geoip'].get('country_code') if country_code: country = country_obj.search([('code', '=', country_code)], limit=1) if country: grade_domain += [('country_id', '=', country.id)] grades = partner_obj.sudo().read_group(grade_domain, ["id", "grade_id"], groupby="grade_id") grades_partners = partner_obj.sudo().search_count(grade_domain) # flag active grade for grade_dict in grades: grade_dict[ 'active'] = grade and grade_dict['grade_id'][0] == grade.id grades.insert( 0, { 'grade_id_count': grades_partners, 'grade_id': (0, _("All Categories")), 'active': bool(grade is None), }) # group by country country_domain = list(base_partner_domain) if grade: country_domain += [('grade_id', '=', grade.id)] countries = partner_obj.sudo().read_group(country_domain, ["id", "country_id"], groupby="country_id", orderby="country_id") countries_partners = partner_obj.sudo().search_count(country_domain) # flag active country for country_dict in countries: country_dict['active'] = country and country_dict[ 'country_id'] and country_dict['country_id'][0] == country.id countries.insert( 0, { 'country_id_count': countries_partners, 'country_id': (0, _("All Countries")), 'active': bool(country is None), }) # current search if grade: base_partner_domain += [('grade_id', '=', grade.id)] if country: base_partner_domain += [('country_id', '=', country.id)] # format pager if grade and not country: url = '/partners/grade/' + slug(grade) elif country and not grade: url = '/partners/country/' + slug(country) elif country and grade: url = '/partners/grade/' + slug(grade) + '/country/' + slug( country) else: url = '/partners' url_args = {} if search: url_args['search'] = search if country_all: url_args['country_all'] = True partner_count = partner_obj.sudo().search_count(base_partner_domain) pager = request.website.pager(url=url, total=partner_count, page=page, step=self._references_per_page, scope=7, url_args=url_args) # search partners matching current search parameters partner_ids = partner_obj.sudo().search( base_partner_domain, order= "grade_sequence DESC, implemented_count DESC, display_name ASC, id ASC", offset=pager['offset'], limit=self._references_per_page) partners = partner_ids.sudo() google_map_partner_ids = ','.join(str(p.id) for p in partners) google_maps_api_key = request.website.google_maps_api_key values = { 'countries': countries, 'current_country': country, 'grades': grades, 'current_grade': grade, 'partners': partners, 'google_map_partner_ids': google_map_partner_ids, 'pager': pager, 'searches': post, 'search_path': "%s" % werkzeug.url_encode(post), 'google_maps_api_key': google_maps_api_key, } return request.render("website_crm_partner_assign.index", values, status=partners and 200 or 404)
def _compute_website_url(self): super(BlogPost, self)._compute_website_url() for blog_post in self: blog_post.website_url = "/blog/%s/post/%s" % (slug( blog_post.blog_id), slug(blog_post))