[IMP] auth_signup converted to server side module

bzr revid: fme@openerp.com-20140121152027-7wch4r7dt2ew0did
This commit is contained in:
Fabien Meghazi 2014-01-21 16:20:27 +01:00
parent 1e921cd03d
commit fff55213b5
6 changed files with 102 additions and 298 deletions

View File

@ -43,6 +43,5 @@ Allow users to sign up and reset their password
'views/auth_signup_login.xml',
],
'js': ['static/src/js/auth_signup.js'],
'qweb': ['static/src/xml/auth_signup.xml'],
'bootstrap': True,
}

View File

@ -21,77 +21,71 @@
import logging
import openerp
import openerp.addons.web.controllers.main as webmain
from openerp import http
from openerp.http import request, LazyResponse
from openerp.modules.registry import RegistryManager
from ..res_users import SignupError
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
class Home(openerp.addons.web.controllers.main.Home):
@http.route('/web/login', type='http', auth="none")
@http.route()
def web_login(self, *args, **kw):
response = super(Home, self).web_login(*args, **kw)
if isinstance(response, LazyResponse):
config = self.get_auth_signup_config(request.session.db)
response.params['values'].update(config)
if request.params.get('signup', None) and config['signup']:
response.params['template'] = 'auth_signup.signup'
if request.params.get('reset', None) and config['signup']:
response.params['template'] = 'auth_signup.reset'
# TODO: ensure_db()
request.disable_db = False
mode = request.params.get('mode')
qcontext = request.params.copy()
response = webmain.render_bootstrap_template(request.session.db, 'auth_signup.signup', qcontext, lazy=True)
token = qcontext.get('token', None)
token_infos = None
if token:
try:
# retrieve the user info (name, login or email) corresponding to a signup token
res_partner = request.registry.get('res.partner')
token_infos = res_partner.signup_retrieve_info(request.cr, openerp.SUPERUSER_ID, token)
for k, v in token_infos.items():
qcontext.setdefault(k, v)
except:
qcontext['error'] = _("Invalid signup token")
response.params['template'] = 'web.login'
return response
# retrieve the module config (which features are enabled) for the login page
icp = request.registry.get('ir.config_parameter')
config = {
'signup': icp.get_param(request.cr, openerp.SUPERUSER_ID, 'auth_signup.allow_uninvited') == 'True',
'reset': icp.get_param(request.cr, openerp.SUPERUSER_ID, 'auth_signup.reset_password') == 'True',
}
qcontext.update(config)
if 'error' in qcontext or mode not in ('reset', 'signup') or (not token and not config[mode]):
response = super(Home, self).web_login(*args, **kw)
if isinstance(response, LazyResponse):
response.params['values'].update(config)
return response
if request.httprequest.method == 'GET':
if token_infos:
qcontext.update(token_infos)
else:
res_users = request.registry.get('res.users')
login = request.params.get('login')
if mode == 'reset' and not token:
try:
res_users.reset_password(request.cr, openerp.SUPERUSER_ID, login)
qcontext['message'] = _("An email has been sent with credentials to reset your password")
response.params['template'] = 'web.login'
except:
qcontext['error'] = _("Could not reset your password")
_logger.exception('error when resetting password')
else:
values = {key: qcontext.get(key) for key in ('login', 'name', 'password')}
res_users.signup(request.cr, openerp.SUPERUSER_ID, values, token)
request.cr.commit()
return super(Home, self).web_login(*args, **kw)
return response
def get_auth_signup_config(self, dbname):
""" retrieve the module config (which features are enabled) for the login page """
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
icp = registry.get('ir.config_parameter')
config = {
'signup': icp.get_param(cr, openerp.SUPERUSER_ID, 'auth_signup.allow_uninvited') == 'True',
'reset_password': icp.get_param(cr, openerp.SUPERUSER_ID, 'auth_signup.reset_password') == 'True',
}
return config
class Controller(http.Controller):
@http.route('/auth_signup/retrieve', type='json', auth="none")
def retrieve(self, dbname, token):
""" retrieve the user info (name, login or email) corresponding to a signup token """
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
res_partner = registry.get('res.partner')
user_info = res_partner.signup_retrieve_info(cr, openerp.SUPERUSER_ID, token)
return user_info
@http.route('/auth_signup/signup', type='json', auth="none")
def signup(self, dbname, token, **values):
""" sign up a user (new or existing)"""
try:
self._signup_with_values(dbname, token, values)
except SignupError, e:
return {'error': openerp.tools.exception_to_unicode(e)}
return {}
def _signup_with_values(self, dbname, token, values):
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
res_users = registry.get('res.users')
res_users.signup(cr, openerp.SUPERUSER_ID, values, token)
@http.route('/auth_signup/reset_password', type='json', auth="none")
def reset_password(self, dbname, login):
""" retrieve user, and perform reset password """
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
try:
res_users = registry.get('res.users')
res_users.reset_password(cr, openerp.SUPERUSER_ID, login)
cr.commit()
except Exception as e:
# signup error
_logger.exception('error when resetting password')
raise(e)
return True
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -69,7 +69,8 @@ class res_partner(osv.Model):
# the parameters to encode for the query
query = dict(db=cr.dbname)
signup_type = context.get('signup_force_type_in_url', partner.signup_type or '')
query[signup_type] = 1
if signup_type:
query['mode'] = signup_type
if partner.signup_token and signup_type:
query['token'] = partner.signup_token

View File

@ -1,188 +1,19 @@
openerp.auth_signup = function(instance) {
instance.auth_signup = instance.auth_signup || {};
var _t = instance.web._t;
return;
instance.web.Login.include({
start: function() {
openerp.web.LoginForm.include({
start: function () {
var self = this;
this.signup_enabled = false;
this.reset_password_enabled = false;
return this._super().always(function() {
// Switches the login box to the select mode whith mode == [default|signup|reset]
self.on('change:login_mode', self, function() {
var mode = self.get('login_mode') || 'default';
self.$('*[data-modes]').each(function() {
var modes = $(this).data('modes').split(/\s+/);
$(this).toggle(modes.indexOf(mode) > -1);
});
self.$('a.oe_signup_signup:visible').toggle(self.signup_enabled);
self.$('a.oe_signup_reset_password:visible').toggle(self.reset_password_enabled);
});
// to switch between the signup and regular login form
self.$('a.oe_signup_signup').click(function(ev) {
self.set('login_mode', 'signup');
this.$el.on('submit', function () {
var password = self.get_password_field('password');
var confirm_password = self.get_password_field('confirm_password');
if (password && confirm_password && (password.value != confirm_password.value)) {
alert("Passwords do not match; please retype them.");
return false;
});
self.$('a.oe_signup_back').click(function(ev) {
self.set('login_mode', 'default');
delete self.params.token;
return false;
});
var dbname = self.selected_db;
// if there is an error message in params, show it then forget it
if (self.params.error_message) {
self.show_error(self.params.error_message);
delete self.params.error_message;
}
if (dbname && self.params.login) {
self.$("form input[name=login]").val(self.params.login);
}
// bind reset password link
self.$('a.oe_signup_reset_password').click(self.do_reset_password);
if (dbname) {
self.rpc("/auth_signup/get_config", {dbname: dbname}).then(function(result) {
self.signup_enabled = result.signup;
self.reset_password_enabled = result.reset_password;
if (!self.signup_enabled || self.$("form input[name=login]").val()){
self.set('login_mode', self.params.type || 'default');
} else {
self.set('login_mode', 'signup');
}
// in case of a signup, retrieve the user information from the token
if (self.params.token) {
self.rpc("/auth_signup/retrieve", {dbname: dbname, token: self.params.token})
.then(self.on_token_loaded, self.on_token_failed);
}
});
} else {
// TODO: support multiple database mode
self.set('login_mode', self.params.type || 'default');
}
});
},
on_token_loaded: function(result) {
// select the right the database
this.selected_db = result.db;
this.on_db_loaded([result.db]);
if (result.token) {
// switch to signup mode, set user name and login
this.set('login_mode', (this.params.type === 'reset' ? 'reset' : 'signup'));
this.$("form input[name=name]").val(result.name).attr("readonly", "readonly");
if (result.login) {
this.$("form input[name=login]").val(result.login).attr("readonly", "readonly");
} else {
this.$("form input[name=login]").val(result.email);
}
} else {
// remain in login mode, set login if present
delete this.params.token;
this.set('login_mode', 'default');
this.$("form input[name=login]").val(result.login || "");
}
},
on_token_failed: function(result, ev) {
if (ev) {
ev.preventDefault();
}
this.show_error(_t("Invalid signup token"));
delete this.params.db;
delete this.params.token;
this.set('login_mode', 'default');
},
get_params: function(){
// signup user (or reset password)
var db = this.$("form [name=db]").val();
var name = this.$("form input[name=name]").val();
var login = this.$("form input[name=login]").val();
var password = this.$("form input[name=password]").val();
var confirm_password = this.$("form input[name=confirm_password]").val();
if (!db) {
this.do_warn(_t("Login"), _t("No database selected !"));
return false;
} else if (!name) {
this.do_warn(_t("Login"), _t("Please enter a name."));
return false;
} else if (!login) {
this.do_warn(_t("Login"), _t("Please enter a username."));
return false;
} else if (!password || !confirm_password) {
this.do_warn(_t("Login"), _t("Please enter a password and confirm it."));
return false;
} else if (password !== confirm_password) {
this.do_warn(_t("Login"), _t("Passwords do not match; please retype them."));
return false;
}
var params = {
dbname : db,
token: this.params.token || "",
name: name,
login: login,
password: password,
};
return params;
},
on_submit: function(ev) {
if (ev) {
ev.preventDefault();
}
var login_mode = this.get('login_mode');
if (login_mode === 'signup' || login_mode === 'reset') {
var params = this.get_params();
if (_.isEmpty(params)){
return false;
}
var self = this,
super_ = this._super;
this.rpc('/auth_signup/signup', params)
.done(function(result) {
if (result.error) {
self.show_error(result.error);
} else {
super_.apply(self, [ev]);
}
});
} else {
// regular login
this._super(ev);
}
},
do_reset_password: function(ev) {
if (ev) {
ev.preventDefault();
}
var self = this;
var db = this.$("form [name=db]").val();
var login = this.$("form input[name=login]").val();
if (!db) {
this.do_warn(_t("Login"), _t("No database selected !"));
return $.Deferred().reject();
} else if (!login) {
this.do_warn(_t("Login"), _t("Please enter a username or email address."));
return $.Deferred().reject();
}
return self.rpc("/auth_signup/reset_password", { dbname: db, login: login }).done(function(result) {
self.show_error(_t("An email has been sent with credentials to reset your password"));
self.set('login_mode', 'default');
}).fail(function(result, ev) {
ev.preventDefault();
self.show_error(result.message);
});
get_password_field: function (field) {
var selector = 'input[name="' + field + '"][type="password"]:visible';
return this.$(selector)[0];
},
});
};

View File

@ -1,39 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- vim:fdl=1:
-->
<templates id="template" xml:space="preserve">
<t t-extend="Login">
<t t-jquery="form ul:first li:contains('Username')" t-operation="before">
<li data-modes="signup reset">Name</li>
<li data-modes="signup reset"><input name="name" type="text"/></li>
</t>
<t t-jquery="form ul:first li:contains('Username')" t-operation="replace">
<li data-modes="default">Username</li>
<li data-modes="signup reset">Username (Email)</li>
</t>
<t t-jquery="form ul:first li:has(input[name=login], input[name=password]), form ul:first li:contains('Password')">
this.attr('data-modes', 'default signup reset');
</t>
<t t-jquery="form ul:first li:has(input[name=password])" t-operation="after">
<li data-modes="signup reset">Confirm Password</li>
<li data-modes="signup reset"><input name="confirm_password" type="password"/></li>
</t>
<t t-jquery="form ul:first li:has(button[name=submit])" t-operation="replace">
<li>
<button name="submit">
<span data-modes="default">Log in</span>
<span data-modes="signup">Sign Up</span>
<span data-modes="reset">Reset password</span>
</button>
<a class="oe_signup_signup" data-modes="default" href="#">Sign Up</a>
<a class="oe_signup_back" data-modes="signup reset" href="#">Back to Login</a>
<a class="oe_signup_reset_password" data-modes="default" href="#">Reset password</a>
</li>
</t>
<t t-jquery=".oe_login_manage_db">
this.attr('data-modes', 'default');
</t>
</t>
</templates>

View File

@ -5,8 +5,8 @@
<data>
<template id="auth_signup.login" inherit_id="web.login" name="Login (overloaded by auth_signup)">
<xpath expr="//button[@type='submit']" position="before">
<a t-if="signup" href="/web/login?signup=1" class="btn btn-default pull-left">Sign up</a>
<a t-if="reset_password" href="/web/login?reset=1" class="btn btn-default pull-left">Reset Password</a>
<a t-if="signup" t-attf-href="?mode=signup{{ '&amp;debug' if debug else '' }}" class="btn btn-default pull-left">Sign up</a>
<a t-if="reset" t-attf-href="?mode=reset{{ '&amp;debug' if debug else '' }}" class="btn btn-default pull-left">Reset Password</a>
</xpath>
</template>
@ -20,40 +20,58 @@
<script type="text/javascript" t-att-src="js_file"></script>
</t>
</t>
<script type="text/javascript">
$(function() {
var s = new openerp.init(<t t-raw="modules"/>);
var login_form = new openerp.web.LoginForm($('.oe_signup_form'));
});
</script>
<t t-set="reset_without_token" t-value="mode == 'reset' and not token"/>
<form class="oe_signup_form" role="form" t-attf-action="/web/login{{ '?debug' if debug else '' }}" method="post">
<div class="form-group field-name">
<div class="form-group field-name" t-if="not reset_without_token">
<label for="name" class="control-label">Name</label>
<input type="text" name="name" t-att-value="name" id="name" class="form-control" placeholder="Enter your name" required="required" autofocus="autofocus"/>
<input type="text" name="name" t-att-value="name" id="name" class="form-control" placeholder="Enter your name"
required="required" autofocus="autofocus" t-att-disabled="'disabled' if mode == 'reset' and token else None"/>
</div>
<div class="form-group field-login">
<label for="login" class="control-label">Username (email)</label>
<input type="text" name="login" t-att-value="login" id="login" class="form-control" placeholder="Enter login" required="required"/>
<input type="text" name="login" t-att-value="login" id="login" class="form-control" placeholder="Enter login"
t-att-autofocus="'autofocus' if reset_without_token else None"
required="required" t-att-disabled="'disabled' if mode == 'reset' and token else None"/>
<input type="hidden" name="login" t-att-value="login" t-if="mode == 'reset' and token"/>
</div>
<div class="form-group field-password">
<div class="form-group field-password" t-if="not reset_without_token">
<label for="password" class="control-label">Password</label>
<input type="password" name="password" id="password" class="form-control" placeholder="Password" required="required"/>
<input type="password" name="password" id="password" class="form-control" placeholder="Password"
required="required" t-att-autofocus="'autofocus' if mode == 'reset' and token else None"/>
</div>
<div class="form-group field-confirm_password">
<div class="form-group field-confirm_password" t-if="not reset_without_token">
<label for="confirm_password" class="control-label">Confirm Password</label>
<input type="password" name="confirm_password" id="confirm_password" class="form-control" placeholder="Confirm your password" required="required"/>
</div>
<div class="oe_login_messages">
<p class="alert alert-danger" t-if="authentication_failed">
Wrong login/password
</p>
</div>
<p class="alert alert-danger" t-if="error">
<t t-esc="error"/>
</p>
<p class="alert alert-success" t-if="message">
<t t-esc="message"/>
</p>
<hr/>
<input type="hidden" name="redirect" t-att-value="redirect"/>
<input type="hidden" name="signup" value="1"/>
<input type="hidden" name="mode" t-att-value="mode"/>
<input type="hidden" name="token" t-att-value="token"/>
<div class="clearfix oe_login_buttons">
<a href="/web/login" class="btn btn-default pull-left">Back to Login</a>
<button type="submit" class="btn btn-primary pull-right">Signup</button>
<button type="submit" class="btn btn-primary pull-right">
<t t-if="mode == 'signup'">Signup</t>
<t t-if="mode == 'reset'">Reset password</t>
</button>
</div>
</form>