summaryrefslogtreecommitdiff
path: root/addons/website_profile
diff options
context:
space:
mode:
authorDavid Beguin <dbe@odoo.com>2019-02-20 16:54:36 +0000
committerDavid Beguin <dbe@odoo.com>2019-03-15 14:58:28 +0000
commitfb40c6bf6018f7f208201e1d4a4d413fd2ce3080 (patch)
treed6df1ec5f2e7aca08311a51fad7f2ab3162a6806 /addons/website_profile
parentbbedcdb19054527940fb040a0d4f22115d5be265 (diff)
[IMP] website(_profile,_forum,_slides): move validation email to profile and use in forum and elearning
Email validation was necessary on the forum to be able to begin to use the forum (ask or answer questions, vote, etc..) As the new elearning also uses karma since 705376a982d64fb41800f148a167ef0fc28ce4c6, the email validation is now also necessary in the eLearning platform. This is why this commit is moving the email validation process to website_profile and extend website_slides (eLearning) and website_forum to use this feature. In function of where the user asked to send him the validation email, the user is redirected on the forum or on the elearning when he clicks on 'Validate my account' in the received 'email validation' email. Task ID : 1943788 PR #31321
Diffstat (limited to 'addons/website_profile')
-rw-r--r--addons/website_profile/__manifest__.py1
-rw-r--r--addons/website_profile/controllers/main.py28
-rw-r--r--addons/website_profile/data/profile_data.xml106
-rw-r--r--addons/website_profile/models/__init__.py1
-rw-r--r--addons/website_profile/models/res_users.py58
-rw-r--r--addons/website_profile/static/src/js/website_profile.js47
-rw-r--r--addons/website_profile/views/website_profile.xml39
7 files changed, 276 insertions, 4 deletions
diff --git a/addons/website_profile/__manifest__.py b/addons/website_profile/__manifest__.py
index 1214d3f03e8..fbb57d126fd 100644
--- a/addons/website_profile/__manifest__.py
+++ b/addons/website_profile/__manifest__.py
@@ -12,6 +12,7 @@
'gamification'
],
'data': [
+ 'data/profile_data.xml',
'views/gamification_badge_views.xml',
'views/website_profile.xml',
'security/ir.model.access.csv',
diff --git a/addons/website_profile/controllers/main.py b/addons/website_profile/controllers/main.py
index 4d0e58efbe8..b29ba2077fb 100644
--- a/addons/website_profile/controllers/main.py
+++ b/addons/website_profile/controllers/main.py
@@ -57,6 +57,8 @@ class WebsiteProfile(http.Controller):
values = {
'user': request.env.user,
'is_public_user': request.website.is_public_user(),
+ 'validation_email_sent': request.session.get('validation_email_sent', False),
+ 'validation_email_done': request.session.get('validation_email_done', False),
}
values.update(kwargs)
return values
@@ -111,8 +113,9 @@ class WebsiteProfile(http.Controller):
user = self._check_user_profile_access(user_id)
if not user:
return request.render("website_profile.private_profile")
+ values = self._prepare_user_values(**post)
params = self._prepare_user_profile_parameters(**post)
- values = self._prepare_user_profile_values(user, **params)
+ values.update(self._prepare_user_profile_values(user, **params))
return request.render("website_profile.user_profile_main", values)
# Edit Profile
@@ -234,3 +237,26 @@ class WebsiteProfile(http.Controller):
'pager': pager
}
return request.render("website_profile.users_page_main", values)
+
+ # User and validation
+ # --------------------------------------------------
+
+ @http.route('/profile/send_validation_email', type='json', auth='user', website=True)
+ def send_validation_email(self, **kwargs):
+ if request.env.uid != request.website.user_id.id:
+ request.env.user._send_profile_validation_email(**kwargs)
+ request.session['validation_email_sent'] = True
+ return True
+
+ @http.route('/profile/validate_email', type='http', auth='public', website=True, sitemap=False)
+ def validate_email(self, token, user_id, email, **kwargs):
+ done = request.env['res.users'].sudo().browse(int(user_id))._process_profile_validation_token(token, email)
+ if done:
+ request.session['validation_email_done'] = True
+ url = kwargs.get('redirect_url', '/')
+ return request.redirect(url)
+
+ @http.route('/profile/validate_email/close', type='json', auth='public', website=True)
+ def validate_email_done(self, **kwargs):
+ request.session['validation_email_done'] = False
+ return True
diff --git a/addons/website_profile/data/profile_data.xml b/addons/website_profile/data/profile_data.xml
new file mode 100644
index 00000000000..5331fa23e8e
--- /dev/null
+++ b/addons/website_profile/data/profile_data.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <data noupdate="1">
+
+ <!-- Email template for email validation (for karma purpose) -->
+ <record id="validation_email" model="mail.template">
+ <field name="name">Profile: Email Verification</field>
+ <field name="model_id" ref="base.model_res_users"/>
+ <field name="subject">${object.company_id.name} Profile validation</field>
+ <field name="email_from">${('&lt;%s&gt;' % (object.env.user.company_id.email or user.email)) | safe}</field>
+ <field name="email_to">${object.email|safe}</field>
+ <field name="body_html" type="html">
+<table border="0" cellpadding="0" cellspacing="0" style="padding-top: 16px; background-color: #F1F1F1; color: #454748; width: 100%; border-collapse:separate;"><tr><td align="center">
+<table border="0" cellpadding="0" cellspacing="0" width="590" style="padding: 16px; background-color: white; color: #454748; border-collapse:separate;">
+<tbody>
+ <!-- HEADER -->
+ <tr>
+ <td align="center" style="min-width: 590px;">
+ <table border="0" cellpadding="0" cellspacing="0" width="590" style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;">
+ <tr>
+ <td valign="middle">
+ <span style="font-size: 20px; font-weight: bold;">
+ ${object.company_id.name} Profile validation
+ </span>
+ </td>
+ <td valign="middle" align="right">
+ <img src="/logo.png?company=${user.company_id.id}" style="padding: 0px; margin: 0px; height: auto; width: 80px;" alt="${user.company_id.name}"/>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" style="text-align:center;">
+ <hr width="100%" style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin:16px 0px 16px 0px;"/>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <!-- CONTENT -->
+ <tr>
+ <td align="center" style="min-width: 590px;">
+ <table border="0" cellpadding="0" cellspacing="0" width="590" style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;">
+ <tr>
+ <td valign="top" style="font-size: 13px;">
+ <p style="margin: 0px; padding: 0px; font-size: 13px;">
+ Hello ${object.name},<br /><br />
+ You have been invited to validate your email in order to get access to "${object.company_id.name}" website.
+ To validate your email, please click on the following link:
+ <div style="margin: 16px 0px 16px 0px;">
+ <a href="${ctx.get('token_url')}"
+ style="background-color: #875A7B; padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;">
+ Validate my account
+ </a>
+ </div>
+ Thanks for your participation!
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td style="text-align:center;">
+ <hr width="100%" style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;"/>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <!-- FOOTER -->
+ <tr>
+ <td align="center" style="min-width: 590px;">
+ <table border="0" cellpadding="0" cellspacing="0" width="590" style=" font-family: 'Verdana Regular'; color: #454748; min-width: 590px; background-color: white; font-size: 11px; padding: 0px 8px 0px 8px; border-collapse:separate;">
+ <tr>
+ <td valign="middle" align="left">
+ ${user.company_id.name}
+ </td>
+ <td valign="middle" align="right" style="opacity: 0.7;">
+ ${user.company_id.phone}
+ % if user.company_id.email:
+ | <a href="'mailto:%s' % ${user.company_id.email}" style="text-decoration:none; color: #454748;">
+ ${user.company_id.email}
+ </a>
+ % endif
+ % if user.company_id.website:
+ | <a href="${user.company_id.website}" style="text-decoration:none; color: #454748;">
+ ${user.company_id.website}
+ </a>
+ % endif
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</tbody>
+</table>
+</td></tr>
+<!-- POWERED BY -->
+<tr><td align="center" style="min-width: 590px;">
+ <table border="0" cellpadding="0" cellspacing="0" width="590" style="min-width: 590px; background-color: #F1F1F1; color: #454748; padding: 8px; border-collapse:separate;">
+ <tr><td style="text-align: center; font-size: 13px;">
+ Powered by <a target="_blank" href="https://www.odoo.com?utm_source=db&amp;utm_medium=forum" style="color: #875A7B;">Odoo</a>
+ </td></tr>
+ </table>
+</td></tr>
+</table>
+ </field>
+ </record>
+ </data>
+</odoo>
diff --git a/addons/website_profile/models/__init__.py b/addons/website_profile/models/__init__.py
index c26e78d1255..e5d082ad113 100644
--- a/addons/website_profile/models/__init__.py
+++ b/addons/website_profile/models/__init__.py
@@ -3,3 +3,4 @@
from . import gamification_badge
from . import website
+from . import res_users
diff --git a/addons/website_profile/models/res_users.py b/addons/website_profile/models/res_users.py
new file mode 100644
index 00000000000..5bf49be0a78
--- /dev/null
+++ b/addons/website_profile/models/res_users.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import hashlib
+import uuid
+
+from datetime import datetime
+from werkzeug import urls
+from odoo import api, models
+
+VALIDATION_KARMA_GAIN = 3
+
+
+class Users(models.Model):
+ _inherit = 'res.users'
+
+ @api.model
+ def _generate_profile_token(self, user_id, email):
+ """Return a token for email validation. This token is valid for the day
+ and is a hash based on a (secret) uuid generated by the forum module,
+ the user_id, the email and currently the day (to be updated if necessary). """
+ profile_uuid = self.env['ir.config_parameter'].sudo().get_param('website_profile.uuid')
+ if not profile_uuid:
+ profile_uuid = str(uuid.uuid4())
+ self.env['ir.config_parameter'].sudo().set_param('website_profile.uuid', profile_uuid)
+ return hashlib.sha256((u'%s-%s-%s-%s' % (
+ datetime.now().replace(hour=0, minute=0, second=0, microsecond=0),
+ profile_uuid,
+ user_id,
+ email
+ )).encode('utf-8')).hexdigest()
+
+ def _send_profile_validation_email(self, **kwargs):
+ if not self.email:
+ return False
+ token = self._generate_profile_token(self.id, self.email)
+ activation_template = self.env.ref('website_profile.validation_email')
+ if activation_template:
+ params = {
+ 'token': token,
+ 'user_id': self.id,
+ 'email': self.email
+ }
+ params.update(kwargs)
+ base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
+ token_url = base_url + '/profile/validate_email?%s' % urls.url_encode(params)
+ with self._cr.savepoint():
+ activation_template.sudo().with_context(token_url=token_url).send_mail(
+ self.id, force_send=True, raise_exception=True)
+ return True
+
+ @api.multi
+ def _process_profile_validation_token(self, token, email):
+ self.ensure_one()
+ validation_token = self._generate_profile_token(self.id, email)
+ if token == validation_token and self.karma == 0:
+ return self.write({'karma': VALIDATION_KARMA_GAIN})
+ return False
diff --git a/addons/website_profile/static/src/js/website_profile.js b/addons/website_profile/static/src/js/website_profile.js
new file mode 100644
index 00000000000..a3cc18f53f5
--- /dev/null
+++ b/addons/website_profile/static/src/js/website_profile.js
@@ -0,0 +1,47 @@
+odoo.define('website_profile.website_profile', function (require) {
+'use strict';
+
+var sAnimations = require('website.content.snippets.animation');
+
+//TODO DBE : to change into publicWidget = require('web.public.widget'); after forward port in master
+sAnimations.registry.websiteProfile = sAnimations.Class.extend({
+ selector: '.o_wprofile_email_validation_container',
+ read_events: {
+ 'click .send_validation_email': '_onSendValidationEmailClick',
+ 'click .validated_email_close': '_onCloseValidatedEmailClick',
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+ /**
+ * @private
+ * @param {Event} ev
+ */
+ _onSendValidationEmailClick: function (ev) {
+ ev.preventDefault();
+ var self = this;
+ var $element = $(ev.currentTarget);
+ this._rpc({
+ route: '/profile/send_validation_email',
+ params: {'redirect_url': $element.data('redirect_url')},
+ }).then(function (data) {
+ if (data) {
+ self.$('button.validation_email_close').click();
+ }
+ });
+ },
+
+ /**
+ * @private
+ */
+ _onCloseValidatedEmailClick: function () {
+ this._rpc({
+ route: '/profile/validate_email/close',
+ });
+ },
+});
+
+return sAnimations.registry.websiteProfile;
+
+});
diff --git a/addons/website_profile/views/website_profile.xml b/addons/website_profile/views/website_profile.xml
index 2a108ef8906..fc9e6aae113 100644
--- a/addons/website_profile/views/website_profile.xml
+++ b/addons/website_profile/views/website_profile.xml
@@ -4,6 +4,9 @@
<xpath expr="link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href="/website_profile/static/src/scss/website_profile.scss"/>
</xpath>
+ <xpath expr="script[last()]" position="after">
+ <script type="text/javascript" src="/website_profile/static/src/js/website_profile.js"/>
+ </xpath>
</template>
@@ -130,7 +133,7 @@
<div class="col-12 col-md-4 col-lg-3">
<div t-attf-class="d-flex align-items-start #{'justify-content-between' if (request.env.user == user) else 'justify-content-around' }">
<div class="o_wprofile_pict d-inline-block mb-3 mb-md-0" t-attf-style="background-image:url(/web/image/res.users/#{user.id}/image)"/>
- <a class="btn btn-primary d-inline-block d-md-none" t-if="request.env.user == user" t-attf-href="/profile/edit?url_param=#{edit_button_url_param}">
+ <a class="btn btn-primary d-inline-block d-md-none" t-if="request.env.user == user and validation_email_done" t-attf-href="/profile/edit?url_param=#{edit_button_url_param}">
<i class="fa fa-pencil mr-1"/>EDIT
</a>
</div>
@@ -139,8 +142,10 @@
<!-- ==== Header Right ==== -->
<div class="col-12 col-md-8 col-lg-9 d-flex flex-column">
<div class="d-flex justify-content-between align-items-start">
- <h1 class="o_card_people_name" t-field="user.name"/>
- <a class="btn btn-primary d-none d-md-inline-block" t-if="request.env.user == user" t-attf-href="/profile/edit?url_param=#{edit_button_url_param}">
+ <h1 class="o_card_people_name">
+ <span t-field="user.name"/><small t-if="not validation_email_done"> (not verified)</small>
+ </h1>
+ <a class="btn btn-primary d-none d-md-inline-block" t-if="request.env.user == user and validation_email_done" t-attf-href="/profile/edit?url_param=#{edit_button_url_param}">
<i class="fa fa-pencil mr-2"/>EDIT PROFILE
</a>
</div>
@@ -212,6 +217,12 @@
</ul>
<div class="tab-content py-4 o_wprofile_tabs_content mb-4" id="profile_extra_info_tabcontent">
<div role="tabpanel" class="tab-pane active" id="profile_tab_content_about">
+ <div class="o_wprofile_email_validation_container mb16 mt16">
+ <t t-call="website_profile.email_validation_banner">
+ <t t-set="redirect_url" t-value="'/profile/user/%s' % user.id"/>
+ <t t-set="send_validation_email_message" t-value="'Click here to send a verification email.'"/>
+ </t>
+ </div>
<div id="profile_about_badge" class="mb32">
<h5 class="border-bottom pb-1">Badges</h5>
<t t-call="website_profile.user_badges"></t>
@@ -463,4 +474,26 @@
</ul>
</template>
+ <template id="email_validation_banner">
+ <div t-if="not validation_email_sent and not is_public_user and user.karma == 0" class="alert alert-danger alert-dismissable" role="alert">
+ <button type="button" class="close validation_email_close" data-dismiss="alert" aria-label="Close">&amp;times;</button>
+ <div>
+ <p>
+ It appears your email has not been verified.
+ <a class="send_validation_email" href="#" t-att-data-redirect_url="redirect_url">
+ <span t-esc="send_validation_email_message"/></a>
+ </p>
+ </div>
+ </div>
+ <div t-if="validation_email_done" class="alert alert-success alert-dismissable" role="status">
+ <button type="button" class="close validated_email_close" data-dismiss="alert" aria-label="Close">&amp;times;</button>
+ <div>
+ <p>
+ <span id="email_validated_message">Congratulations! Your email has just been validated.</span>
+ <span t-esc="additional_validated_email_message"/>
+ </p>
+ </div>
+ </div>
+ </template>
+
</data></odoo>