[MERGE] server side login

bzr revid: fme@openerp.com-20140122133720-2cjcdymf6qqj213u
This commit is contained in:
Fabien Meghazi
2014-01-22 14:37:20 +01:00
10 changed files with 399 additions and 550 deletions
+4 -1
View File
@@ -12,7 +12,10 @@ This module provides the core of the OpenERP Web Client.
'depends': ['base'],
'auto_install': True,
'post_load': 'wsgi_postload',
'js' : [
'data': [
'views/webclient_templates.xml',
],
'js': [
"static/lib/es5-shim/es5-shim.min.js",
"static/lib/datejs/globalization/en-US.js",
"static/lib/datejs/core.js",
+121 -44
View File
@@ -6,6 +6,7 @@ import csv
import functools
import glob
import itertools
import jinja2
import logging
import operator
import datetime
@@ -16,8 +17,6 @@ import simplejson
import time
import urllib
import urllib2
import urlparse
import xmlrpclib
import zlib
from xml.etree import ElementTree
from cStringIO import StringIO
@@ -33,13 +32,18 @@ except ImportError:
import openerp
import openerp.modules.registry
from openerp.tools.translate import _
from openerp.tools import config
from openerp import http
from openerp.http import request, serialize_exception as _serialize_exception
from openerp.http import request, serialize_exception as _serialize_exception, LazyResponse
_logger = logging.getLogger(__name__)
env = jinja2.Environment(
loader=jinja2.PackageLoader('openerp.addons.web', "views"),
autoescape=True
)
env.filters["json"] = simplejson.dumps
#----------------------------------------------------------
# OpenERP Web helpers
#----------------------------------------------------------
@@ -108,12 +112,13 @@ def serialize_exception(f):
return werkzeug.exceptions.InternalServerError(simplejson.dumps(error))
return wrap
def redirect_with_hash(url, code=303):
# Most IE and Safari versions decided not to preserve location.hash upon
# redirect. And even if IE10 pretends to support it, it still fails
# inexplicably in case of multiple redirects (and we do have some).
# See extensive test page at http://greenbytes.de/tech/tc/httpredirects/
return "<html><head><script>window.location = '%s' + location.hash;</script></head></html>" % url
def redirect_with_hash(*args, **kw):
"""
.. deprecated:: 8.0
Use the ``http.redirect_with_hash()`` function instead.
"""
return http.redirect_with_hash(*args, **kw)
def module_topological_sort(modules):
""" Return a list of module names sorted so that their dependencies of the
@@ -512,6 +517,8 @@ def content_disposition(filename):
# OpenERP Web web Controllers
#----------------------------------------------------------
# TODO: to remove once the database manager has been migrated server side
# and `edi` + `pos` addons has been adapted to use render_bootstrap_template()
html_template = """<!DOCTYPE html>
<html style="height: 100%%">
<head>
@@ -538,53 +545,89 @@ html_template = """<!DOCTYPE html>
</html>
"""
def render_bootstrap_template(db, template, values=None, debug=False, lazy=False, **kw):
if request and request.debug:
debug = True
if values is None:
values = {}
values.update(kw)
values['debug'] = debug
for res in ['js', 'css']:
if res not in values:
values[res] = manifest_list(res, db=db, debug=debug)
if 'modules' not in values:
values['modules'] = module_boot(db=db)
values['modules'] = simplejson.dumps(values['modules'])
def callback(template, values):
registry = openerp.modules.registry.RegistryManager.get(db)
with registry.cursor() as cr:
view_obj = registry["ir.ui.view"]
return view_obj.render(cr, openerp.SUPERUSER_ID, template, values)
if lazy:
return LazyResponse(callback, template=template, values=values)
else:
return callback(template, values)
class Home(http.Controller):
@http.route('/', type='http', auth="none")
def index(self, s_action=None, db=None, debug=False, **kw):
query = dict(urlparse.parse_qsl(request.httprequest.query_string, keep_blank_values=True))
redirect = '/web' + '?' + urllib.urlencode(query)
return redirect_with_hash(redirect)
def index(self, s_action=None, db=None, **kw):
return http.local_redirect('/web', query=request.params)
@http.route('/web', type='http', auth="none")
def web_client(self, s_action=None, db=None, debug=False, **kw):
debug = debug != False
def web_client(self, s_action=None, db=None, **kw):
# if db not provided, use the session one
if not db:
db = request.session.db
lst = http.db_list(True)
if db not in lst:
db = None
guessed_db = http.db_monodb(request.httprequest)
if guessed_db is None and len(lst) > 0:
guessed_db = lst[0]
# if no database provided and no database in session, use monodb
if not db:
db = http.db_monodb(request.httprequest)
def redirect(db):
query = dict(urlparse.parse_qsl(request.httprequest.query_string, keep_blank_values=True))
query['db'] = db
redirect = request.httprequest.path + '?' + urllib.urlencode(query)
return redirect_with_hash(redirect)
# if no db can be found til here, send to the database selector
# the database selector will redirect to database manager if needed
if not db:
return http.local_redirect('/web/database/selector')
if db is None and guessed_db is not None:
return redirect(guessed_db)
# always switch the session to the computed db
if db != request.session.db:
request.session.logout()
request.session.db = db
if db is not None and db != request.session.db:
if request.session.uid:
html = render_bootstrap_template(db, "web.webclient_bootstrap")
return request.make_response(html, {'Cache-Control': 'no-cache', 'Content-Type': 'text/html; charset=utf-8'})
else:
return http.local_redirect('/web/login', query=request.params)
@http.route('/web/login', type='http', auth="none")
def web_login(self, redirect=None, db=None, **kw):
if db and db != request.session.db:
request.session.logout()
request.session.db = db
guessed_db = db
request.params.pop('db', None)
return http.local_redirect('/web/login', query=request.params)
js = "\n ".join('<script type="text/javascript" src="%s"></script>' % i for i in manifest_list('js', db=guessed_db, debug=debug))
css = "\n ".join('<link rel="stylesheet" href="%s">' % i for i in manifest_list('css', db=guessed_db, debug=debug))
if not request.session.db and not db:
return http.local_redirect('/web/database/selector')
r = html_template % {
'js': js,
'css': css,
'modules': simplejson.dumps(module_boot(db=guessed_db)),
'init': 'var wc = new s.web.WebClient();wc.appendTo($(document.body));'
}
return request.make_response(r, {'Cache-Control': 'no-cache', 'Content-Type': 'text/html; charset=utf-8'})
values = request.params.copy()
if not redirect:
redirect = '/web?' + request.httprequest.query_string
values['redirect'] = redirect
if request.httprequest.method == 'POST':
uid = request.session.authenticate(request.session.db, request.params['login'], request.params['password'])
if uid is not False:
return http.redirect_with_hash(redirect)
values['error'] = "Wrong login/password"
return render_bootstrap_template(request.session.db, 'web.login', values, lazy=True)
@http.route('/login', type='http', auth="none")
def login(self, db, login, key):
return login_and_redirect(db, login, key)
def login(self, db, login, key, redirect="/web", **kw):
return login_and_redirect(db, login, key, redirect_url=redirect)
class WebClient(http.Controller):
@@ -754,6 +797,37 @@ class Proxy(http.Controller):
class Database(http.Controller):
@http.route('/web/database/selector', type='http', auth="none")
def selector(self, **kw):
try:
dbs = http.db_list()
if not dbs:
return http.local_redirect('/web/database/manager')
except openerp.exceptions.AccessDenied:
dbs = False
return env.get_template("database_selector.html").render({
'databases': dbs,
'debug': request.debug,
})
@http.route('/web/database/manager', type='http', auth="none")
def manager(self, **kw):
# TODO: migrate the webclient's database manager to server side views
request.session.logout()
js = "\n ".join('<script type="text/javascript" src="%s"></script>' % i for i in manifest_list('js', debug=request.debug))
css = "\n ".join('<link rel="stylesheet" href="%s">' % i for i in manifest_list('css', debug=request.debug))
r = html_template % {
'js': js,
'css': css,
'modules': simplejson.dumps(module_boot()),
'init': """
var wc = new s.web.WebClient(null, { action: 'database_manager' });
wc.appendTo($(document.body));
"""
}
return r
@http.route('/web/database/get_list', type='json', auth="none")
def get_list(self):
# TODO change js to avoid calling this method if in monodb mode
@@ -768,12 +842,15 @@ class Database(http.Controller):
@http.route('/web/database/create', type='json', auth="none")
def create(self, fields):
params = dict(map(operator.itemgetter('name', 'value'), fields))
return request.session.proxy("db").create_database(
db_created = request.session.proxy("db").create_database(
params['super_admin_pwd'],
params['db_name'],
bool(params.get('demo_data')),
params['db_lang'],
params['create_admin_pwd'])
if db_created:
request.session.authenticate(params['db_name'], 'admin', params['create_admin_pwd'])
return db_created
@http.route('/web/database/duplicate', type='json', auth="none")
def duplicate(self, fields):
@@ -942,7 +1019,7 @@ class Session(http.Controller):
def destroy(self):
request.session.logout()
@http.route('/web/session/logout', type='http', auth="user")
@http.route('/web/session/logout', type='http', auth="none")
def logout(self, redirect='/web'):
request.session.logout()
return werkzeug.utils.redirect(redirect, 303)
+28 -148
View File
@@ -874,153 +874,6 @@
padding: 5px;
width: 32px;
}
.openerp .oe_login {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=);
text-align: center;
font-size: 14px;
height: 100%;
}
.openerp .oe_login ul, .openerp .oe_login li {
margin: 0;
list-style-type: none;
padding: 0 0 4px 0;
}
.openerp .oe_login button {
cursor: pointer;
padding: 6px 16px;
border: 1px solid #222222;
color: white;
margin: 0;
background-color: #8c1313;
background-image: -webkit-gradient(linear, left top, left bottom, from(#b92020), to(#600606));
background-image: -webkit-linear-gradient(top, #b92020, #600606);
background-image: -moz-linear-gradient(top, #b92020, #600606);
background-image: -ms-linear-gradient(top, #b92020, #600606);
background-image: -o-linear-gradient(top, #b92020, #600606);
background-image: linear-gradient(to bottom, #b92020, #600606);
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(155, 155, 155, 0.4) inset;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(155, 155, 155, 0.4) inset;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(155, 155, 155, 0.4) inset;
}
.openerp .oe_login input, .openerp .oe_login select {
width: 252px;
font-family: "Lucida Grande", Helvetica, Verdana, Arial;
border: 1px solid #999999;
background: whitesmoke;
-moz-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.4);
-webkit-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.4);
box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.4);
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
}
.openerp .oe_login input {
margin-bottom: 9px;
padding: 5px 6px;
}
.openerp .oe_login select {
padding: 1px;
}
.openerp .oe_login .oe_login_dbpane {
position: fixed;
top: 0;
right: 8px;
padding: 5px 10px;
color: #eeeeee;
border: solid 1px #333333;
background: #1e1e1e;
background: rgba(30, 30, 30, 0.94);
-moz-border-radius: 0 0 8px 8px;
-webkit-border-radius: 0 0 8px 8px;
border-radius: 0 0 8px 8px;
}
.openerp .oe_login .oe_login_dbpane input {
padding: 2px 4px;
margin: 4px 0;
}
.openerp .oe_login .oe_login_bottom {
position: absolute;
top: 50%;
left: 0;
right: 0;
bottom: 0;
text-shadow: 0 1px 1px #999999;
background-color: #8a0e0e;
background-image: -webkit-gradient(linear, left top, left bottom, from(#b41616), to(#600606));
background-image: -webkit-linear-gradient(top, #b41616, #600606);
background-image: -moz-linear-gradient(top, #b41616, #600606);
background-image: -ms-linear-gradient(top, #b41616, #600606);
background-image: -o-linear-gradient(top, #b41616, #600606);
background-image: linear-gradient(to bottom, #b41616, #600606);
}
.openerp .oe_login .oe_login_pane {
position: absolute;
top: 50%;
left: 50%;
margin: -160px -166px;
border: solid 1px #333333;
background: #1e1e1e;
background: rgba(30, 30, 30, 0.94);
padding: 22px 32px;
color: #eeeeee;
text-align: left;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
border-radius: 8px;
-moz-box-shadow: 0 0 18px rgba(0, 0, 0, 0.9);
-webkit-box-shadow: 0 0 18px rgba(0, 0, 0, 0.9);
box-shadow: 0 0 18px rgba(0, 0, 0, 0.9);
}
.openerp .oe_login .oe_login_pane h2 {
margin-top: 0;
font-size: 18px;
}
.openerp .oe_login .oe_login_logo {
position: absolute;
top: -70px;
left: 0;
width: 100%;
margin: 0 auto;
text-align: center;
}
.openerp .oe_login .oe_login_footer {
position: absolute;
bottom: -40px;
left: 0;
width: 100%;
text-align: center;
}
.openerp .oe_login .oe_login_footer a {
color: #eeeeee;
margin: 0 6px;
}
.openerp .oe_login .oe_login_footer a:hover {
text-decoration: underline;
}
.openerp .oe_login .oe_login_footer span {
font-weight: bold;
font-size: 16px;
}
.openerp .oe_login .oe_login_error_message {
display: none;
background-color: #b41616;
color: #eeeeee;
padding: 14px 18px;
margin-top: 15px;
text-align: center;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
}
.openerp .oe_login_invalid .oe_login_error_message {
display: inline-block;
}
.openerp .oe_database_manager {
background: white;
color: black;
@@ -1050,7 +903,7 @@
background-image: -moz-linear-gradient(top, #fc8787, maroon);
background-image: -ms-linear-gradient(top, #fc8787, maroon);
background-image: -o-linear-gradient(top, #fc8787, maroon);
background-image: linear-gradient(to bottom, #fc8787, maroon);
background-image: linear-gradient(to bottom, #fc8787, #800000);
}
.openerp .navbar .oe_topbar_anonymous_login a {
display: block;
@@ -3385,6 +3238,33 @@ div.ui-widget-overlay {
padding-bottom: 10px !important;
}
body.oe_single_form {
background: #eeeeee url(/web/static/src/img/form_sheetbg.png);
height: 100%;
}
body.oe_single_form .oe_single_form_logo {
padding: 10px;
text-align: center;
margin-bottom: 10px;
}
body.oe_single_form .oe_single_form_footer {
position: absolute;
bottom: -30px;
right: 0px;
width: 100%;
text-align: center;
}
body.oe_single_form .oe_single_form_container {
padding: 10px;
position: absolute;
left: 50%;
top: 50%;
width: 400px;
/* Set margins to offset 50% of the w/h */
margin-top: -200px;
margin-left: -200px;
}
.openerp_ie .placeholder {
color: #afafb6 !important;
font-style: italic !important;
+32 -102
View File
@@ -747,108 +747,6 @@ $sheet-padding: 16px
padding: 5px
width: 32px
// }}}
// Login {{{
.oe_login
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=)
text-align: center
font-size: 14px
height: 100%
ul, li
margin: 0
list-style-type: none
padding: 0 0 4px 0
button
cursor: pointer
padding: 6px 16px
border: 1px solid #222
color: white
margin: 0
@include vertical-gradient(#b92020, #600606)
@include radius(4px)
@include box-shadow((0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(155, 155, 155, 0.4) inset))
input, select
width: 252px
font-family: "Lucida Grande", Helvetica, Verdana, Arial
border: 1px solid #999999
background: whitesmoke
@include box-shadow(inset 0 1px 4px rgba(0, 0, 0, 0.4))
@include radius(3px)
input
margin-bottom: 9px
padding: 5px 6px
select
padding: 1px
.oe_login_dbpane
position: fixed
top: 0
right: 8px
padding: 5px 10px
color: #eee
border: solid 1px #333
background: #1e1e1e
background: rgba(30,30,30,0.94)
@include radius(0 0 8px 8px)
input
padding: 2px 4px
margin: 4px 0
.oe_login_bottom
position: absolute
top: 50%
left: 0
right: 0
bottom: 0
text-shadow: 0 1px 1px #999999
@include vertical-gradient(#b41616, #600606)
.oe_login_pane
position: absolute
top: 50%
left: 50%
margin: -160px -166px
border: solid 1px #333333
background: #1e1e1e
background: rgba(30,30,30,0.94)
padding: 22px 32px
color: #eee
text-align: left
@include radius(8px)
@include box-shadow(0 0 18px rgba(0, 0, 0, 0.9))
h2
margin-top: 0
font-size: 18px
.oe_login_logo
position: absolute
top: -70px
left: 0
width: 100%
margin: 0 auto
text-align: center
.oe_login_footer
position: absolute
bottom: -40px
left: 0
width: 100%
text-align: center
a
color: #eee
margin: 0 6px
&:hover
text-decoration: underline
span
font-weight: bold
font-size: 16px
.oe_login_error_message
display: none
background-color: #b41616
color: #eee
padding: 14px 18px
margin-top: 15px
text-align: center
@include radius(4px)
@include box-shadow(0 1px 4px rgba(0, 0, 0, 0.8))
.oe_login_invalid
.oe_login_error_message
display: inline-block
// }}}
// DatabaseManager {{{
.oe_database_manager
background: #fff
@@ -2698,6 +2596,38 @@ div.ui-widget-overlay
td
padding-bottom: 10px !important
// Server side single forms {{{
@mixin single-form($width: 400px)
padding: 10px
position: absolute
left: 50%
top: 50%
width: $width
/* Set margins to offset 50% of the w/h */
margin-top: -($width / 2)
margin-left: -($width / 2)
body.oe_single_form
background: #eee url(/web/static/src/img/form_sheetbg.png)
height: 100%
.oe_single_form_logo
padding: 10px
text-align: center
margin-bottom: 10px
.oe_single_form_footer
position: absolute
bottom: -30px
right: 0px
width: 100%
text-align: center
.oe_single_form_container
@include single-form(400px)
// }}}
// Internet Explorer 9+ specifics {{{
.openerp_ie
.placeholder
+47 -205
View File
@@ -475,19 +475,6 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
this.$el.find('#db-create, #db-drop, #db-backup, #db-restore, #db-change-password, #back-to-login').unbind('click').end().empty();
this._super();
},
/**
* Converts a .serializeArray() result into a dict. Does not bother folding
* multiple identical keys into an array, last key wins.
*
* @param {Array} array
*/
to_object: function (array) {
var result = {};
_(array).each(function (record) {
result[record.name] = record.value;
});
return result;
},
/**
* Blocks UI and replaces $.unblockUI by a noop to prevent third parties
* from unblocking the UI
@@ -525,25 +512,11 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
var self = this;
var fields = $(form).serializeArray();
self.rpc("/web/database/create", {'fields': fields}).done(function(result) {
var form_obj = self.to_object(fields);
var client_action = {
type: 'ir.actions.client',
tag: 'login',
params: {
'db': form_obj['db_name'],
'login': 'admin',
'password': form_obj['create_admin_pwd'],
'login_successful': function() {
var url = '/web?db=' + form_obj['db_name'];
if (self.session.debug) {
url += '&debug';
}
instance.web.redirect(url);
},
},
_push_me: false,
};
self.do_action(client_action);
if (result) {
instance.web.redirect('/web')
} else {
alert("Failed to create database");
}
});
},
do_duplicate: function(form) {
@@ -641,156 +614,20 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
},
do_exit: function () {
this.$el.remove();
instance.webclient.show_login();
instance.web.redirect('/web');
}
});
instance.web.client_actions.add("database_manager", "instance.web.DatabaseManager");
instance.web.Login = instance.web.Widget.extend({
template: "Login",
remember_credentials: true,
events: {
'change input[name=db],select[name=db]': function(ev) {
this.set('database_selector', $(ev.currentTarget).val());
},
},
instance.web.login = function() {
instance.web.redirect('/web/login');
};
instance.web.client_actions.add("login", "instance.web.login");
init: function(parent, action) {
this._super(parent);
this.has_local_storage = typeof(localStorage) != 'undefined';
this.db_list = null;
this.selected_db = null;
this.selected_login = null;
this.params = action.params || {};
if (_.isEmpty(this.params)) {
this.params = $.bbq.getState(true);
}
if (action && action.params && action.params.db) {
this.params.db = action.params.db;
} else if ($.deparam.querystring().db) {
this.params.db = $.deparam.querystring().db;
}
if (this.params.db) {
this.selected_db = this.params.db;
}
if (this.params.login_successful) {
this.on('login_successful', this, this.params.login_successful);
}
// some cleanup to remove any trace of that last login feature
if (typeof(localStorage) != 'undefined') {
var toRemove = [];
_.each(_.range(localStorage.length), function(i) {
var key = localStorage.key(i);
if (key.match(/^.*?\|last_password$/)) {
toRemove.push(key);
}
});
_.each(toRemove, function(k) {
localStorage.removeItem(k);
});
}
},
start: function() {
var self = this;
self.$el.find("form").submit(self.on_submit);
self.$el.find('.oe_login_manage_db').click(function() {
self.do_action("database_manager");
});
self.on('change:database_selector', this, function() {
this.database_selected(this.get('database_selector'));
});
var d = $.when();
if ($.param.fragment().token) {
self.params.token = $.param.fragment().token;
}
// used by dbmanager.do_create via internal client action
if (self.params.db && self.params.login && self.params.password) {
d = self.do_login(self.params.db, self.params.login, self.params.password);
} else {
d = self.rpc("/web/database/get_list", {})
.done(self.on_db_loaded)
.fail(self.on_db_failed)
.always(function() {
if (self.selected_db && self.has_local_storage && self.remember_credentials) {
self.$("[name=login]").val(localStorage.getItem(self.selected_db + '|last_login') || '');
}
});
}
return d;
},
database_selected: function(db) {
var params = $.deparam.querystring();
params.db = db;
this.$('.oe_login_dbpane').empty().text(_t('Loading...'));
this.$('[name=login], [name=password]').prop('readonly', true);
instance.web.redirect('/web?' + $.param(params));
},
on_db_loaded: function (result) {
var self = this;
this.db_list = result;
if (!this.selected_db) {
this.selected_db = result[0];
}
this.$("[name=db]").replaceWith(QWeb.render('Login.dblist', { db_list: this.db_list, selected_db: this.selected_db}));
if(this.db_list.length === 0) {
this.do_action("database_manager");
} else if(this.db_list.length === 1) {
this.$('div.oe_login_dbpane').hide();
} else {
this.$('div.oe_login_dbpane').show();
}
},
on_db_failed: function (error, event) {
if (error.data.name === 'openerp.exceptions.AccessDenied') {
event.preventDefault();
}
},
on_submit: function(ev) {
if(ev) {
ev.preventDefault();
}
var db = this.$("form [name=db]").val();
if (!db) {
this.do_warn(_t("Login"), _t("No database selected !"));
return false;
}
var login = this.$("form input[name=login]").val();
var password = this.$("form input[name=password]").val();
this.do_login(db, login, password);
},
/**
* Performs actual login operation, and UI-related stuff
*
* @param {String} db database to log in
* @param {String} login user login
* @param {String} password user password
*/
do_login: function (db, login, password) {
var self = this;
self.hide_error();
self.$(".oe_login_pane").fadeOut("slow");
return this.session.session_authenticate(db, login, password).then(function() {
if (self.has_local_storage && self.remember_credentials) {
localStorage.setItem(db + '|last_login', login);
}
self.trigger('login_successful');
}, function () {
self.$(".oe_login_pane").fadeIn("fast", function() {
self.show_error(_t("Invalid username or password"));
});
});
},
show_error: function(message) {
this.$el.addClass("oe_login_invalid");
this.$(".oe_login_error_message").text(message);
},
hide_error: function() {
this.$el.removeClass('oe_login_invalid');
},
});
instance.web.client_actions.add("login", "instance.web.Login");
instance.web.logout = function() {
instance.web.redirect('/web/session/logout');
};
instance.web.client_actions.add("logout", "instance.web.logout");
/**
@@ -1246,6 +1083,7 @@ instance.web.FullscreenWidget = instance.web.Widget.extend({
instance.web.Client = instance.web.Widget.extend({
init: function(parent, origin) {
instance.client = instance.webclient = this;
this.client_options = {};
this._super(parent);
this.origin = origin;
},
@@ -1316,8 +1154,11 @@ instance.web.WebClient = instance.web.Client.extend({
events: {
'click .oe_logo_edit_admin': 'logo_edit'
},
init: function(parent) {
init: function(parent, client_options) {
this._super(parent);
if (client_options) {
_.extend(this.client_options, client_options);
}
this._current_state = null;
this.menu_dm = new instance.web.DropMisordered();
this.action_mutex = new $.Mutex();
@@ -1331,11 +1172,13 @@ instance.web.WebClient = instance.web.Client.extend({
if (jQuery.deparam !== undefined && jQuery.deparam(jQuery.param.querystring()).kitten !== undefined) {
self.to_kitten();
}
if (!self.session.session_is_valid()) {
self.show_login();
} else {
if (self.session.session_is_valid()) {
self.show_application();
}
if (self.client_options.action) {
self.action_manager.do_action(self.client_options.action);
delete(self.client_options.action);
}
});
},
to_kitten: function() {
@@ -1385,25 +1228,6 @@ instance.web.WebClient = instance.web.Client.extend({
});
};
},
show_login: function() {
this.toggle_bars(false);
var state = $.bbq.getState(true);
var action = {
type: 'ir.actions.client',
tag: 'login',
_push_me: false,
};
this.action_manager.do_action(action);
this.action_manager.inner_widget.on('login_successful', this, function() {
if ('redirect' in state) {
openerp.web.redirect(state.redirect);
} else {
this.show_application(); // will load the state we just pushed
}
});
},
show_application: function() {
var self = this;
self.toggle_bars(true);
@@ -1418,6 +1242,10 @@ instance.web.WebClient = instance.web.Client.extend({
self.bind_hashchange();
self.set_title();
self.check_timezone();
if (self.client_options.action_post_login) {
self.action_manager.do_action(self.client_options.action_post_login);
delete(self.client_options.action_post_login);
}
},
update_logo: function() {
var img = this.session.url('/web/binary/company_logo');
@@ -1498,11 +1326,7 @@ instance.web.WebClient = instance.web.Client.extend({
on_logout: function() {
var self = this;
if (!this.has_uncommitted_changes()) {
this.session.session_logout().done(function () {
$(window).unbind('hashchange', self.on_hashchange);
self.do_push_state({});
window.location.reload();
});
self.action_manager.do_action('logout');
}
},
bind_hashchange: function() {
@@ -1659,6 +1483,24 @@ instance.web.embed = function (origin, dbname, login, key, action, options) {
client.insertAfter(currentScript);
};
openerp.web.LoginForm = openerp.web.Widget.extend({
init: function ($form) {
this._super(/* no parent */);
this.setElement($form);
this.$el.on('submit', this.on_submit);
this.start();
},
start: function () {
if (location.hash) {
this.$el.attr('action', this.$el.attr('action') + location.hash);
}
return this._super();
},
on_submit: function () {
return true;
},
});
})();
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
+1 -1
View File
@@ -252,7 +252,7 @@ instance.web.Session.include( /** @lends instance.web.Session# */{
return !!this.uid;
},
/**
* The session is validated either by login or by restoration of a previous session
* The session is validated by restoration of a previous session
*/
session_authenticate: function() {
var self = this;
-40
View File
@@ -58,46 +58,6 @@
</div>
</t>
<t t-name="Login">
<div class="oe_login">
<div class="oe_login_bottom"> </div>
<div class="oe_login_error_message"/>
<div class="oe_login_pane">
<div class="oe_login_logo"><img src='/web/static/src/img/logo2.png'/></div>
<form action="" method="post">
<div class="oe_login_dbpane" >
Database:
<input name="db" t-att-value="widget.selected_db || ''"/>
</div>
<ul>
<li>Username</li>
<li><input name="login" type="text" value="" autofocus="autofocus"/></li>
<li>Password</li>
<li><input name="password" type="password" value=""/></li>
<li><button name="submit">Log in</button></li>
</ul>
</form>
<div class="oe_login_footer">
<a href="#" class="oe_login_manage_db">Manage Databases</a> |
<a href="http://www.openerp.com" target="_blank">Powered by <span>OpenERP</span></a>
</div>
</div>
</div>
</t>
<t t-name="Login.dblist">
<select name="db">
<t t-foreach="db_list" t-as="db">
<t t-if="selected_db === db">
<option t-att-value="db" selected="true">
<t t-esc="db"/></option>
</t>
<t t-if="selected_db !== db">
<option t-att-value="db"><t t-esc="db"/></option>
</t>
</t>
</select>
</t>
<t t-name="DatabaseManager">
<div class="oe_view_manager_view_form">
<div class="oe_form">
+51
View File
@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html style="height: 100%">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>OpenERP</title>
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="/web/static/src/css/full.css">
<link rel="stylesheet" href="/web/static/lib/fontawesome/css/font-awesome.css">
<link rel="stylesheet" href="/web/static/lib/bootstrap/css/bootstrap.css">
<link rel="stylesheet" href="/web/static/src/css/base.css">
<body class="oe_single_form">
<div class="oe_single_form_container modal-content">
<form class="oe_dbselector_form" role="form" action="/web" method="get">
<div class="oe_single_form_logo">
<img src="/web/static/src/img/logo2.png"/>
</div>
<hr/>
<div class="form-group field-db">
<label for="db" class="control-label">Select database</label>
{% if databases %}
<select name="db" id="db" class="form-control" required="required" autofocus="autofocus">
<option></option>
{% for db in databases %}
<option value="{{ db }}">{{ db }}</option>
{% endfor %}
</select>
{% else %}
<input type="text" name="db" id="db" class="form-control" required="required" autofocus="autofocus"/>
{% endif %}
</div>
<hr/>
{% if debug %}
<input type="hidden" name="debug" value=""/>
{% endif %}
<input type="submit" value="Continue" class="btn btn-primary pull-right"/>
<div class="oe_single_form_footer">
<a class="oe_login_manage_db" href="/web/database/manager{% if debug %}?debug{% endif %}">Manage Databases</a> |
<a href="http://www.openerp.com" target="_blank">Powered by <span>OpenERP</span></a>
</div>
</form>
</div>
</body>
</html>
+115
View File
@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- vim:fdn=3:
-->
<openerp>
<data>
<template id="web.layout" name="Web layout">&lt;!DOCTYPE html&gt;
<html style="height: 100%">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>OpenERP</title>
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" href="/web/static/src/css/full.css" />
<t t-raw="head or ''"/>
</head>
<body t-att-class="body_classname">
<t t-raw="0"/>
</body>
</html>
</template>
<template id="web.webclient_bootstrap" name="Webclient Bootstrap">
<t t-call="web.layout">
<t t-set="head">
<t t-foreach="css" t-as="css_file">
<link rel="stylesheet" t-att-href="css_file"/>
</t>
<t t-foreach="js" t-as="js_file">
<script type="text/javascript" t-att-src="js_file"></script>
</t>
<script type="text/javascript">
$(function() {
var s = new openerp.init(<t t-raw="modules"/>);
<t t-if="init">
<t t-raw="init"/>
</t>
<t t-if="not init">
var wc = new s.web.WebClient();
wc.appendTo($(document.body));
</t>
});
</script>
</t>
</t>
</template>
<template id="web.login_layout" name="Login Layout">
<t t-call="web.layout">
<t t-set="body_classname" t-value="'oe_single_form'"/>
<div class="oe_single_form_container modal-content">
<div class="oe_single_form_logo">
<img src="/web/binary/company_logo"/>
</div>
<hr/>
<t t-raw="0"/>
</div>
</t>
</template>
<template id="web.login" name="Login">
<t t-call="web.login_layout">
<t t-set="head">
<t t-foreach="css" t-as="css_file">
<link rel="stylesheet" t-att-href="css_file"/>
</t>
<t t-foreach="js" t-as="js_file">
<script type="text/javascript" t-att-src="js_file"></script>
</t>
<script type="text/javascript">
$(function() {
var s = new openerp.init(<t t-raw="modules"/>);
var login_form = new openerp.web.LoginForm($('.oe_login_form'));
});
</script>
</t>
<form class="oe_login_form" role="form" t-attf-action="/web/login{{ '?debug' if debug else '' }}" method="post">
<div class="form-group field-login">
<label for="login" class="control-label">Login</label>
<input type="text" name="login" t-att-value="login" id="login" class="form-control" placeholder="Enter login" required="required" autofocus="autofocus"/>
</div>
<div class="form-group field-password">
<label for="password" class="control-label">Password</label>
<input type="password" name="password" id="password" class="form-control" placeholder="Password" required="required"/>
</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"/>
<div class="clearfix oe_login_buttons">
<button type="submit" class="btn btn-primary pull-right">Log in</button>
</div>
</form>
<div class="oe_single_form_footer" t-if="not disable_footer">
<t t-if="not disable_database_manager">
<a class="oe_login_manage_db" t-attf-href="/web/database/manager{{ '?debug' if debug else '' }}">Manage Databases</a>
<span class="oe_footer_seperator"> | </span>
</t>
<a href="http://www.openerp.com" target="_blank">Powered by <span>OpenERP</span></a>
</div>
</t>
</template>
</data>
</openerp>
@@ -11,15 +11,6 @@ instance.web.SearchView = instance.web.SearchView.extend({
}
});
// here you may tweak globals object, if any, and play with on_* or do_* callbacks on them
instance.web.Login = instance.web.Login.extend({
start: function() {
console.log('Hello there');
return this._super.apply(this,arguments);
}
});
};
// vim:et fdc=0 fdl=0: