diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml
index 5aca260bc12..143c5514141 100644
--- a/addons/account/account_invoice_view.xml
+++ b/addons/account/account_invoice_view.xml
@@ -273,6 +273,7 @@
+
@@ -426,6 +427,7 @@
+
diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml
index 2de4d6176b0..64e1cf22156 100644
--- a/addons/account_voucher/account_voucher_view.xml
+++ b/addons/account_voucher/account_voucher_view.xml
@@ -111,6 +111,7 @@
+
diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml
index 45144be24d4..503c3aeaa5e 100644
--- a/addons/account_voucher/voucher_payment_receipt_view.xml
+++ b/addons/account_voucher/voucher_payment_receipt_view.xml
@@ -240,6 +240,7 @@
+
@@ -408,6 +409,7 @@
+
diff --git a/addons/account_voucher/voucher_sales_purchase_view.xml b/addons/account_voucher/voucher_sales_purchase_view.xml
index 965e2600f24..5bcecfa268e 100644
--- a/addons/account_voucher/voucher_sales_purchase_view.xml
+++ b/addons/account_voucher/voucher_sales_purchase_view.xml
@@ -147,6 +147,7 @@
+
@@ -301,6 +302,7 @@
+
diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py
index 165af37888d..3231b1e6d95 100644
--- a/addons/analytic/analytic.py
+++ b/addons/analytic/analytic.py
@@ -297,7 +297,6 @@ class account_analytic_account(osv.osv):
def create_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
- self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
self.message_append_note(cr, uid, [obj.id], body=_("Contract for %s has been created .") % (obj.partner_id.name), context=context)
account_analytic_account()
diff --git a/addons/analytic/analytic_view.xml b/addons/analytic/analytic_view.xml
index ccd77638fd9..16100e73fff 100644
--- a/addons/analytic/analytic_view.xml
+++ b/addons/analytic/analytic_view.xml
@@ -45,6 +45,7 @@
+
diff --git a/addons/auth_oauth/__init__.py b/addons/auth_oauth/__init__.py
new file mode 100644
index 00000000000..c9acce48a16
--- /dev/null
+++ b/addons/auth_oauth/__init__.py
@@ -0,0 +1,3 @@
+import controllers
+import auth_oauth
+import res_users
diff --git a/addons/auth_oauth/__openerp__.py b/addons/auth_oauth/__openerp__.py
new file mode 100644
index 00000000000..6c79bba2151
--- /dev/null
+++ b/addons/auth_oauth/__openerp__.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2010-2012 OpenERP s.a. ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+
+{
+ 'name': 'OAuth2 Authentication',
+ 'version': '1.0',
+ 'category': 'Tools',
+ 'description': """Allow users to login through Google OAuth2.""",
+ 'author': 'Victor Tabuenca',
+ 'maintainer': 'OpenERP s.a.',
+ 'website': 'http://www.openerp.com',
+ 'depends': ['base', 'web'],
+ 'data': [
+ 'auth_oauth_data.xml'
+ ],
+ 'update_xml': [
+ 'auth_oauth_view.xml'
+ ],
+ 'js': [
+ 'static/src/js/auth_oauth.js',
+ ],
+ 'css': [
+ 'static/lib/zocial/css/zocial.css',
+ ],
+ 'qweb': [
+ 'static/src/xml/auth_oauth.xml',
+ ],
+ 'installable': True,
+ 'auto_install': False,
+}
diff --git a/addons/auth_oauth/auth_oauth.py b/addons/auth_oauth/auth_oauth.py
new file mode 100644
index 00000000000..e258505868d
--- /dev/null
+++ b/addons/auth_oauth/auth_oauth.py
@@ -0,0 +1,22 @@
+from openerp.osv import osv, fields
+
+class auth_oauth_providers(osv.osv):
+ """Class defining the configuration values of an OAuth2 provider"""
+
+ _name = 'auth.oauth.provider'
+ _description = 'OAuth2 provider'
+ _order = 'name'
+
+ _columns = {
+ 'name' : fields.char('Provider name', required=True), # Name of the OAuth2 entity, Google, LinkedIn, etc
+ 'client_id' : fields.char('Client ID', required=True), # Our identifier
+ 'auth_endpoint' : fields.char('Authentication URL', required=True), # OAuth provider URL to authenticate users
+ 'scope' : fields.char('Scope'), # OAUth user data desired to access
+ 'validation_endpoint' : fields.char('Validation URL'), # OAuth provider URL to validate tokens
+ 'data_endpoint' : fields.char('Data URL'),
+ 'css_class' : fields.char('CSS class'),
+ 'body' : fields.char('Body'),
+ 'active' : fields.boolean('Active'),
+ 'sequence' : fields.integer(),
+ }
+
diff --git a/addons/auth_oauth/auth_oauth_data.xml b/addons/auth_oauth/auth_oauth_data.xml
new file mode 100644
index 00000000000..021a03b2742
--- /dev/null
+++ b/addons/auth_oauth/auth_oauth_data.xml
@@ -0,0 +1,38 @@
+
+
+
+
+ Facebook Graph
+ facebook_client_id
+ https://www.facebook.com/dialog/oauth
+
+ https://graph.facebook.com/me/permissions
+
+ zocial facebook
+ Sign in with facebook
+ True
+
+
+ Google OAuth2
+ 108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com
+ https://accounts.google.com/o/oauth2/auth
+ https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile
+ https://www.googleapis.com/oauth2/v1/tokeninfo
+ https://www.googleapis.com/oauth2/v1/userinfo
+ zocial google
+ Sign in with google
+ True
+
+
+
+
diff --git a/addons/auth_oauth/auth_oauth_view.xml b/addons/auth_oauth/auth_oauth_view.xml
new file mode 100644
index 00000000000..678c347c84d
--- /dev/null
+++ b/addons/auth_oauth/auth_oauth_view.xml
@@ -0,0 +1,46 @@
+
+
+
+
+ auth.oauth.provider.form
+ auth.oauth.provider
+ form
+
+
+
+
+
+ auth.oauth.provider.list
+ auth.oauth.provider
+ tree
+
+
+
+
+
+
+
+
+
+ Providers
+ auth.oauth.provider
+ form
+ tree,form
+
+
+
+
diff --git a/addons/auth_oauth/controllers/__init__.py b/addons/auth_oauth/controllers/__init__.py
new file mode 100644
index 00000000000..e11f9ba81bb
--- /dev/null
+++ b/addons/auth_oauth/controllers/__init__.py
@@ -0,0 +1,3 @@
+import main
+
+# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py
new file mode 100644
index 00000000000..28f550b4bda
--- /dev/null
+++ b/addons/auth_oauth/controllers/main.py
@@ -0,0 +1,47 @@
+import logging
+
+import simplejson
+import werkzeug.urls
+import werkzeug.utils
+
+import openerp.modules.registry
+import openerp.addons.web.controllers.main
+import openerp.addons.web.common.http as openerpweb
+
+_logger = logging.getLogger(__name__)
+
+class OAuthController(openerpweb.Controller):
+ _cp_path = '/auth_oauth'
+
+ @openerpweb.jsonrequest
+ def list_providers(self, req, dbname):
+ registry = openerp.modules.registry.RegistryManager.get(dbname)
+ with registry.cursor() as cr:
+ providers = registry.get('auth.oauth.provider')
+ l = providers.read(cr, 1, providers.search(cr, 1, []))
+ return l
+
+ @openerpweb.httprequest
+ def signin(self, req, **kw):
+ state = simplejson.loads(kw['state'])
+ dbname = state['d']
+ provider = state['p']
+ registry = openerp.modules.registry.RegistryManager.get(dbname)
+ with registry.cursor() as cr:
+ try:
+ u = registry.get('res.users')
+ credentials = u.auth_oauth(cr, 1, provider, kw)
+ cr.commit()
+ return openerp.addons.web.controllers.main.login_and_redirect(req, *credentials)
+ except AttributeError:
+ # auth_signup is not installed
+ _logger.error("auth_signup not installed on database %s: oauth sign up cancelled."%dbname)
+ url = "/#action=login&oauth_error=1"
+ except Exception,e:
+ # signup error
+ _logger.exception('oops')
+ url = "/#action=login&oauth_error=2"
+ return openerp.addons.web.controllers.main.set_cookie_and_redirect(req, url)
+
+
+# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py
new file mode 100644
index 00000000000..3dbab849942
--- /dev/null
+++ b/addons/auth_oauth/res_users.py
@@ -0,0 +1,70 @@
+import logging
+
+import urllib
+import urllib2
+import simplejson
+
+import openerp
+from openerp.osv import osv, fields
+
+_logger = logging.getLogger(__name__)
+
+class res_users(osv.Model):
+ _inherit = 'res.users'
+
+ _columns = {
+ 'oauth_provider_id': fields.many2one('auth.oauth.provider','OAuth Provider'),
+ 'oauth_uid': fields.char('OAuth User ID', help="Oauth Provider user_id"),
+ 'oauth_access_token': fields.char('OAuth Token', readonly=True),
+ }
+
+ def auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None):
+ params = urllib.urlencode({'access_token':access_token})
+ url = endpoint + '?' + params
+ f = urllib2.urlopen(url)
+ response = f.read()
+ return simplejson.loads(response)
+
+ def auth_oauth(self, cr, uid, provider, params, context=None):
+ # Advice by Google (to avoid Confused Deputy Problem)
+ # if validation.audience != OUR_CLIENT_ID:
+ # abort()
+ # else:
+ # continue with the process
+ access_token = params.get('access_token')
+ p = self.pool.get('auth.oauth.provider').browse(cr, uid, provider, context=context)
+
+ validation = self.auth_oauth_rpc(cr, uid, p.validation_endpoint, access_token)
+ if validation.get("error"):
+ raise openerp.exceptions.AccessDenied
+ login = validation['email']
+ oauth_uid = validation['user_id']
+ name = self.auth_oauth_rpc(cr, uid, p.data_endpoint, access_token)['name']
+
+ credentials = (cr.dbname, login, access_token)
+ res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)])
+ if res:
+ self.write(cr, uid, res[0], {'oauth_access_token':access_token})
+ else:
+ # New user
+ new_user = {
+ 'name': name,
+ 'login': login,
+ 'user_email': login,
+ 'oauth_provider_id': 1,
+ 'oauth_uid': oauth_uid,
+ 'oauth_access_token': access_token,
+ 'active': True,
+ }
+ self.auth_signup_create(cr, uid, new_user)
+ return credentials
+
+ def check_credentials(self, cr, uid, password):
+ try:
+ return super(res_users, self).check_credentials(cr, uid, password)
+ except openerp.exceptions.AccessDenied:
+ res = self.search(cr, 1, [('id','=',uid),('oauth_access_token','=',password)])
+ if not res:
+ raise
+
+#
diff --git a/addons/auth_oauth/res_users.xml b/addons/auth_oauth/res_users.xml
new file mode 100644
index 00000000000..995dbfbd52a
--- /dev/null
+++ b/addons/auth_oauth/res_users.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ res.users.form
+ res.users
+ form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/auth_oauth/static/lib/zocial/README.md b/addons/auth_oauth/static/lib/zocial/README.md
new file mode 100644
index 00000000000..213132677af
--- /dev/null
+++ b/addons/auth_oauth/static/lib/zocial/README.md
@@ -0,0 +1,31 @@
+# Zocial CSS social buttons
+
+I basically rewrote this entire set so they are full vector buttons, meaning:
+
+- @font-face icons
+- custom font file for all social icons
+- icon font use private unicode spaces for accessibility
+- em sizing based on button font-size
+- support for about 83 different services
+- buttons and icons supported
+- no raster images (sweet)
+- works splendidly on any browser supporting @font-face
+- CSS3 degrades gracefully in IE8 and below etc.
+- also includes generic icon-less primary and secondary buttons
+
+## How to use these buttons
+
+ Button label here
+
+or
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.ttf b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.ttf
new file mode 100755
index 00000000000..94809d3a57f
Binary files /dev/null and b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.ttf differ
diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.woff b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.woff
new file mode 100755
index 00000000000..1d6c4abc9d9
Binary files /dev/null and b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.woff differ
diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial.css b/addons/auth_oauth/static/lib/zocial/css/zocial.css
new file mode 100644
index 00000000000..89fc7450631
--- /dev/null
+++ b/addons/auth_oauth/static/lib/zocial/css/zocial.css
@@ -0,0 +1,420 @@
+@charset "UTF-8";
+
+/*!
+Code written by Sam Collins (@smcllns) of www.eventasaur.us
+You are free to use this work commercially
+You are free to extend this work without permissions from the author (just do so tastefully eh?)
+Enjoy
+*/
+
+/* Reference icons from font-files */
+
+@font-face {
+ font-family: 'zocial';
+ font-style: normal;
+ font-weight: normal;
+ src: url('zocial-regular-webfont.eot');
+ src: url('zocial-regular-webfont.eot?#iefix') format('embedded-opentype'),
+ url('zocial-regular-webfont.woff') format('woff'),
+ url('zocial-regular-webfont.ttf') format('truetype'),
+ url('zocial-regular-webfont.svg#ZocialRegular') format('svg');
+ unicode-range: U+0-U+10FFFF;
+}
+
+/* Button structure */
+
+.zocial,
+a.zocial {
+ border: 1px solid #777;
+ border-color: rgba(0,0,0,0.2);
+ border-bottom-color: #333;
+ border-bottom-color: rgba(0,0,0,0.4);
+ color: #fff;
+ -moz-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.4), inset 0 0 0.1em rgba(255,255,255,0.9);
+ -webkit-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.4), inset 0 0 0.1em rgba(255,255,255,0.9);
+ box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.4), inset 0 0 0.1em rgba(255,255,255,0.9);
+ cursor: pointer;
+ display: inline-block;
+ font: bold 100%/2.1 "Lucida Grande", Tahoma, sans-serif;
+ padding: 0 .95em 0 0;
+ text-align: center;
+ text-decoration: none;
+ text-shadow: 0 1px 0 rgba(0,0,0,0.5);
+ white-space: nowrap;
+
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+
+ position: relative;
+
+ -moz-border-radius: .3em;
+ -webkit-border-radius: .3em;
+ border-radius: .3em;
+}
+
+.zocial:before {
+ content: "";
+ border-right: 0.075em solid rgba(0,0,0,0.1);
+ float: left;
+ font: 120%/1.65 zocial;
+ font-style: normal;
+ font-weight: normal;
+ margin: 0 0.5em 0 0;
+ padding: 0 0.5em;
+ text-align: center;
+ text-decoration: none;
+ text-transform: none;
+
+ -moz-box-shadow: 0.075em 0 0 rgba(255,255,255,0.25);
+ -webkit-box-shadow: 0.075em 0 0 rgba(255,255,255,0.25);
+ box-shadow: 0.075em 0 0 rgba(255,255,255,0.25);
+
+ -webkit-font-smoothing: antialiased;
+}
+
+.zocial:active {
+ outline: none; /* outline is visible on :focus */
+}
+
+/* Buttons can be displayed as standalone icons by adding a class of "icon" */
+
+.zocial.icon {
+ overflow: hidden;
+ max-width: 2.4em;
+ padding-left: 0;
+ padding-right: 0;
+ max-height: 2.15em;
+ white-space: nowrap;
+}
+.zocial.icon:before {
+ padding: 0;
+ width: 2em;
+ height: 2em;
+
+ box-shadow: none;
+ border: none;
+}
+
+/* Gradients */
+
+.zocial {
+ background-image: -moz-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1));
+ background-image: -ms-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1));
+ background-image: -o-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1));
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,.1)), color-stop(49%, rgba(255,255,255,.05)), color-stop(51%, rgba(0,0,0,.05)), to(rgba(0,0,0,.1)));
+ background-image: -webkit-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1));
+ background-image: linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1));
+}
+
+.zocial:hover, .zocial:focus {
+ background-image: -moz-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15));
+ background-image: -ms-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15));
+ background-image: -o-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15));
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,.15)), color-stop(49%, rgba(255,255,255,.15)), color-stop(51%, rgba(0,0,0,.1)), to(rgba(0,0,0,.15)));
+ background-image: -webkit-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15));
+ background-image: linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15));
+}
+
+.zocial:active {
+ background-image: -moz-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1));
+ background-image: -ms-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1));
+ background-image: -o-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1));
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,.1)), color-stop(30%, rgba(255,255,255,0)), color-stop(50%, transparent), to(rgba(0,0,0,.1)));
+ background-image: -webkit-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1));
+ background-image: linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1));
+}
+
+/* Adjustments for light background buttons */
+
+.zocial.bitcoin,
+.zocial.cloudapp,
+.zocial.dropbox,
+.zocial.email,
+.zocial.eventful,
+.zocial.github,
+.zocial.gmail,
+.zocial.instapaper,
+.zocial.itunes,
+.zocial.ninetyninedesigns,
+.zocial.openid,
+.zocial.plancast,
+.zocial.posterous,
+.zocial.reddit,
+.zocial.secondary,
+.zocial.viadeo,
+.zocial.weibo,
+.zocial.wikipedia {
+ border: 1px solid #aaa;
+ border-color: rgba(0,0,0,0.3);
+ border-bottom-color: #777;
+ border-bottom-color: rgba(0,0,0,0.5);
+ -moz-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.7), inset 0 0 0.08em rgba(255,255,255,0.5);
+ -webkit-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.7), inset 0 0 0.08em rgba(255,255,255,0.5);
+ box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.7), inset 0 0 0.08em rgba(255,255,255,0.5);
+ text-shadow: 0 1px 0 rgba(255,255,255,0.8);
+}
+
+/* :hover adjustments for light background buttons */
+
+.zocial.bitcoin:focus,
+.zocial.bitcoin:hover,
+.zocial.dropbox:focus,
+.zocial.dropbox:hover,
+.zocial.email:focus,
+.zocial.email:hover,
+.zocial.eventful:focus,
+.zocial.eventful:hover,
+.zocial.github:focus,
+.zocial.github:hover,
+.zocial.gmail:focus,
+.zocial.gmail:hover,
+.zocial.instapaper:focus,
+.zocial.instapaper:hover,
+.zocial.itunes:focus,
+.zocial.itunes:hover,
+.zocial.ninetyninedesigns:focus,
+.zocial.ninetyninedesigns:hover,
+.zocial.openid:focus,
+.zocial.openid:hover,
+.zocial.plancast:focus,
+.zocial.plancast:hover,
+.zocial.posterous:focus,
+.zocial.posterous:hover,
+.zocial.reddit:focus,
+.zocial.reddit:hover,
+.zocial.secondary:focus,
+.zocial.secondary:hover,
+.zocial.twitter:focus,
+.zocial.viadeo:focus,
+.zocial.viadeo:hover,
+.zocial.weibo:focus,
+.zocial.weibo:hover,
+.zocial.wikipedia:focus,
+.zocial.wikipedia:hover {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0.5)), color-stop(49%, rgba(255,255,255,0.2)), color-stop(51%, rgba(0,0,0,0.05)), to(rgba(0,0,0,0.15)));
+ background-image: -moz-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15));
+ background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15));
+ background-image: -o-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15));
+ background-image: -ms-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15));
+ background-image: linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15));
+}
+
+/* :active adjustments for light background buttons */
+
+.zocial.bitcoin:active,
+.zocial.dropbox:active,
+.zocial.email:active,
+.zocial.eventful:active,
+.zocial.github:active,
+.zocial.gmail:active,
+.zocial.instapaper:active,
+.zocial.itunes:active,
+.zocial.ninetyninedesigns:active,
+.zocial.openid:active,
+.zocial.plancast:active,
+.zocial.posterous:active,
+.zocial.reddit:active,
+.zocial.secondary:active,
+.zocial.viadeo:active,
+.zocial.weibo:active,
+.zocial.wikipedia:active {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0)), color-stop(30%, rgba(255,255,255,0)), color-stop(50%, rgba(0,0,0,0)), to(rgba(0,0,0,0.1)));
+ background-image: -moz-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1));
+ background-image: -webkit-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1));
+ background-image: -o-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1));
+ background-image: -ms-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1));
+ background-image: linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1));
+}
+
+/* Button icon and color */
+/* Icon characters are stored in unicode private area */
+.zocial.amazon:before {content: "\E040";}
+.zocial.android:before {content: "\E005";}
+.zocial.angellist:before {content: "\E06C";}
+.zocial.aol:before {content: "\E001";}
+.zocial.appstore:before {content: "\E020";}
+.zocial.bitcoin:before {content: "\E011"; color: #f7931a;}
+.zocial.blogger:before {content: "\E021";}
+.zocial.call:before {content: "\E016";}
+.zocial.cal:before {content: "\E00D";}
+.zocial.cart:before {content: "\E06A";}
+.zocial.chrome:before {content: "\E03A";}
+.zocial.cloudapp:before {content: "\E042";}
+.zocial.creativecommons:before {content: "\E022";}
+.zocial.delicious:before {content: "\E002";}
+.zocial.digg:before {content: "\E01A";}
+.zocial.disqus:before {content: "\E030";}
+.zocial.dribbble:before {content: "\E023";}
+.zocial.dropbox:before {content: "\E043"; color: #1f75cc;}
+.zocial.email:before {content: "\E03C"; color: #312c2a;}
+.zocial.eventasaurus:before {content: "\E055"; color: #9de428;}
+.zocial.eventbrite:before {content: "\E05B";}
+.zocial.eventful:before {content: "\E006"; color: #0066CC;}
+.zocial.evernote:before {content: "\E024";}
+.zocial.facebook:before {content: "\E045";}
+.zocial.fivehundredpx:before {content: "\E00F"; color: #29b6ff;}
+.zocial.flattr:before {content: "\E004";}
+.zocial.flickr:before {content: "\E025";}
+.zocial.forrst:before {content: "\E019"; color: #50894f;}
+.zocial.foursquare:before {content: "\E013";}
+.zocial.github:before {content: "\E046";}
+.zocial.gmail:before {content: "\E04C"; color: #f00;}
+.zocial.google:before {content: "\E026";}
+.zocial.googleplay:before {content: "\E05E";}
+.zocial.googleplus:before {content: "\E00A";}
+.zocial.gowalla:before {content: "\E01F";}
+.zocial.grooveshark:before {content: "\E017";}
+.zocial.guest:before {content: "\E01E";}
+.zocial.html5:before {content: "\E014";}
+.zocial.ie:before {content: "\E015";}
+.zocial.instagram:before {content: "\E06D";}
+.zocial.instapaper:before {content: "\E028";}
+.zocial.intensedebate:before {content: "\E05A";}
+.zocial.itunes:before {content: "\E048"; color: #1a6dd2;}
+.zocial.klout:before {content: "\E02A"; }
+.zocial.lanyrd:before {content: "\E00C";}
+.zocial.lastfm:before {content: "\E04B";}
+.zocial.linkedin:before {content: "\E02B";}
+.zocial.macstore:before {content: "\E03D";}
+.zocial.meetup:before {content: "\E02C";}
+.zocial.myspace:before {content: "\E03E";}
+.zocial.ninetyninedesigns:before {content: "\E018"; color: #f50;}
+.zocial.openid:before {content: "\E04E"; color: #ff921d;}
+.zocial.opentable:before {content: "\E05F";}
+.zocial.paypal:before {content: "\E003";}
+.zocial.pinboard:before {content: "\E04D";}
+.zocial.pinterest:before {content: "\E010";}
+.zocial.plancast:before {content: "\E02F";}
+.zocial.plurk:before {content: "\E049";}
+.zocial.podcast:before {content: "\E03F";}
+.zocial.posterous:before {content: "\E05D";}
+.zocial.print:before {content: "\E06B";}
+.zocial.quora:before {content: "\E050";}
+.zocial.reddit:before {content: "\E01D"; color: red;}
+.zocial.rss:before {content: "\E031";}
+.zocial.scribd:before {content: "\E05C"; color: #00d5ea;}
+.zocial.skype:before {content: "\E032";}
+.zocial.smashing:before {content: "\E009";}
+.zocial.songkick:before {content: "\E04A";}
+.zocial.soundcloud:before {content: "\E052";}
+.zocial.spotify:before {content: "\E01C";}
+.zocial.stumbleupon:before {content: "\E00E";}
+.zocial.tumblr:before {content: "\E053";}
+.zocial.twitter:before {content: "\E033";}
+.zocial.viadeo:before {content: "\E027"; color: #f59b20;}
+.zocial.vimeo:before {content: "\E035";}
+.zocial.weibo:before {content: "\E029"; color: #e6162d;}
+.zocial.wikipedia:before {content: "\E00B";}
+.zocial.windows:before {content: "\E036";}
+.zocial.xing:before {content: "\E037"}
+.zocial.wordpress:before {content: "\E056";}
+.zocial.yahoo:before {content: "\E038";}
+.zocial.yelp:before {content: "\E058";}
+.zocial.youtube:before {content: "\E034";}
+
+/* Button background and text color */
+
+.zocial.amazon {background-color: #ffad1d; color: #030037; text-shadow: 0 1px 0 rgba(255,255,255,0.5);}
+.zocial.android {background-color: #a4c639;}
+.zocial.angellist {background-color: #000;}
+.zocial.aol {background-color: #f00;}
+.zocial.appstore {background-color: #000;}
+.zocial.bitcoin {background-color: #efefef; color: #4d4d4d;}
+.zocial.blogger {background-color: #ee5a22;}
+.zocial.call {background-color: #008000;}
+.zocial.cal {background-color: #d63538;}
+.zocial.cart {background-color: #333;}
+.zocial.chrome {background-color: #006cd4;}
+.zocial.cloudapp {background-color: #fff; color: #312c2a;}
+.zocial.creativecommons {background-color: #000;}
+.zocial.delicious {background-color: #3271cb;}
+.zocial.digg {background-color: #164673;}
+.zocial.disqus {background-color: #5d8aad;}
+.zocial.dribbble {background-color: #ea4c89;}
+.zocial.dropbox {background-color: #fff; color: #312c2a;}
+.zocial.email {background-color: #f0f0eb; color: #312c2a;}
+.zocial.eventasaurus {background-color: #192931; color: #fff;}
+.zocial.eventbrite {background-color: #ff5616;}
+.zocial.eventful {background-color: #fff; color: #47ab15;}
+.zocial.evernote {background-color: #6bb130; color: #fff;}
+.zocial.facebook {background-color: #4863ae;}
+.zocial.fivehundredpx {background-color: #333;}
+.zocial.flattr {background-color: #8aba42;}
+.zocial.flickr {background-color: #ff0084;}
+.zocial.forrst {background-color: #1e360d;}
+.zocial.foursquare {background-color: #44a8e0;}
+.zocial.github {background-color: #fbfbfb; color: #050505;}
+.zocial.gmail {background-color: #efefef; color: #222;}
+.zocial.google {background-color: #4e6cf7;}
+.zocial.googleplay {background-color: #000;}
+.zocial.googleplus {background-color: #dd4b39;}
+.zocial.gowalla {background-color: #ff720a;}
+.zocial.grooveshark {background-color: #111; color:#eee;}
+.zocial.guest {background-color: #1b4d6d;}
+.zocial.html5 {background-color: #ff3617;}
+.zocial.ie {background-color: #00a1d9;}
+.zocial.instapaper {background-color: #eee; color: #222;}
+.zocial.instagram {background-color: #3f729b;}
+.zocial.intensedebate {background-color: #0099e1;}
+.zocial.klout {background-color: #e34a25;}
+.zocial.itunes {background-color: #efefeb; color: #312c2a;}
+.zocial.lanyrd {background-color: #2e6ac2;}
+.zocial.lastfm {background-color: #dc1a23;}
+.zocial.linkedin {background-color: #0083a8;}
+.zocial.macstore {background-color: #007dcb}
+.zocial.meetup {background-color: #ff0026;}
+.zocial.myspace {background-color: #000;}
+.zocial.ninetyninedesigns {background-color: #fff; color: #072243;}
+.zocial.openid {background-color: #f5f5f5; color: #333;}
+.zocial.opentable {background-color: #990000;}
+.zocial.paypal {background-color: #fff; color: #32689a; text-shadow: 0 1px 0 rgba(255,255,255,0.5);}
+.zocial.pinboard {background-color: blue;}
+.zocial.pinterest {background-color: #c91618;}
+.zocial.plancast {background-color: #e7ebed; color: #333;}
+.zocial.plurk {background-color: #cf682f;}
+.zocial.podcast {background-color: #9365ce;}
+.zocial.posterous {background-color: #ffd959; color: #bc7134;}
+.zocial.print {background-color: #f0f0eb; color: #222; text-shadow: 0 1px 0 rgba(255,255,255,0.8);}
+.zocial.quora {background-color: #a82400;}
+.zocial.reddit {background-color: #fff; color: #222;}
+.zocial.rss {background-color: #ff7f25;}
+.zocial.scribd {background-color: #231c1a;}
+.zocial.skype {background-color: #00a2ed;}
+.zocial.smashing {background-color: #ff4f27;}
+.zocial.songkick {background-color: #ff0050;}
+.zocial.soundcloud {background-color: #ff4500;}
+.zocial.spotify {background-color: #60af00;}
+.zocial.stumbleupon {background-color: #eb4924;}
+.zocial.tumblr {background-color: #374a61;}
+.zocial.twitter {background-color: #46c0fb;}
+.zocial.viadeo {background-color: #fff; color: #000;}
+.zocial.vimeo {background-color: #00a2cd;}
+.zocial.weibo {background-color: #faf6f1; color: #000;}
+.zocial.wikipedia {background-color: #fff; color: #000;}
+.zocial.windows {background-color: #0052a4; color: #fff;}
+.zocial.wordpress {background-color: #464646;}
+.zocial.xing {background-color: #0A5D5E;}
+.zocial.yahoo {background-color: #a200c2;}
+.zocial.yelp {background-color: #e60010;}
+.zocial.youtube {background-color: #f00;}
+
+/*
+The Miscellaneous Buttons
+These button have no icons and can be general purpose buttons while ensuring consistent button style
+Credit to @guillermovs for suggesting
+*/
+
+.zocial.primary, .zocial.secondary {margin: 0.1em 0; padding: 0 1em;}
+.zocial.primary:before, .zocial.secondary:before {display: none;}
+.zocial.primary {background-color: #333;}
+.zocial.secondary {background-color: #f0f0eb; color: #222; text-shadow: 0 1px 0 rgba(255,255,255,0.8);}
+
+/* Any browser-specific adjustments */
+
+button:-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+
diff --git a/addons/auth_oauth/static/lib/zocial/sample.html b/addons/auth_oauth/static/lib/zocial/sample.html
new file mode 100644
index 00000000000..98dec554ff1
--- /dev/null
+++ b/addons/auth_oauth/static/lib/zocial/sample.html
@@ -0,0 +1,265 @@
+
+
+
+
+ Zocial CSS3 Buttons
+
+
+
+
+
+
+
+
+
+
+ The Popular Kids
+ Sign in with Facebook
+ Sign in with Google+
+
+ Sign in with LinkedIn
+
+ The Cool Kids
+ Sync with Dropbox
+ Clip to Evernote
+ Follow me on Forrst
+ Sign in with Dribbble
+ Sign in to CloudApp
+ Fork me on Github
+ Play on Spotify
+ Read It Later
+ Follow me on Soundcloud
+ Follow me on Tumblr
+ Read on Smashing Magazine
+ Available on iTunes
+ Available on the App Store
+ Available on the Mac App Store
+ Available on Android Market
+ Follow me on Pinterest
+ Follow me on Quora
+ Attend on Lanyrd
+
+ The Not-So-Cool But Have-To-Be-Invited Kids
+ Pay with Paypal
+ Sign in with Amazon
+ Call me on Skype
+ Sign in with Last.fm
+ Write a review on Yelp
+ Check in with foursquare
+ Influence with Klout
+
+ The Older (but Solid) Kids
+ View on Wikipedia
+
+ Sign in with IntenseDebate
+ Sign in with Google
+ Sign in with Gmail
+ Upload to Vimeo
+ Read more on Scribd
+ Subscribe on YouTube
+ Sign in with WordPress
+ Sign in with Songkick
+ Sign in with Posterous
+ Sign in with Eventbrite
+ Tip with Flattr
+ Follow me on Plancast
+
+
+ The Kids That Kinda Smell but Some People Don't Mind
+ Submit resume for CEO
+ Download Internet Explorer 5
+ Report bugs with Meetup.com
+ Learn how-to-use OpenID
+ Register now for HTML6
+ Chat with your parents
+
+ The Kids That Nobody Normally Notices
+ Sign in as guest
+ View Creative Commons Licence
+
+ Add to Chrome
+
+ The He's-My-Son-So-Of-Course-He's-Here Kid
+ Sign up for Eventasaurus
+
+ Kids By Request
+ Join me on Weibo
+ Sign in with Plurk
+ Play on Grooveshark
+ Post on Blogger
+ Sign in with Viadeo
+ Subscribe to this Podcast
+ View Portfolio on 500px
+ Bitcoin accepted here
+ View Portfolio on 99Designs
+ Bookmark with Pinboard
+ Stumble!
+ Find me on Myspace
+ Sign in with Windows Live
+ Find Events with Eventful
+ Sign in with Xing
+ Upload to Flickr
+ Sign in with Del.icio.us
+ Download from Google Play
+ Reserve with OpenTable
+ Digg this
+ Share on Reddit
+ Fund us on AngelList
+ Sign-in with Instagram
+
+ The Multi-Purpose Kids (Credit: Pictos Icons )
+
+ Call a phone
+ Send a message
+ Add to calendar
+ Add to cart
+ Print this page
+ Primary action
+ Secondary action
+
+
+ Icon versions of the above
+ Sign in with Facebook
+ Sign in with Google+
+
+ Sign in with Google
+ Sign in with LinkedIn
+ Pay with Paypal
+ Sign in with Amazon
+ Sync with Dropbox
+ Clip to Evernote
+ Call me on Skype
+ Sign in as guest
+ Play on Spotify
+ Sign in with Last.fm
+ Sign in with Songkick
+ Follow me on Forrst
+ Sign in with Dribbble
+ Sign in to CloudApp
+ Fork me on Github
+ Follow me on Pinterest
+ Follow me on Quora
+ Bookmark with Pinboard
+ Attend on Lanyrd
+ Download on iTunes
+ Download on Android
+
+ Sign in with Yahoo
+ Upload to Vimeo
+ Add to Chrome
+ Get a new browser
+ Made from HTML5
+ Read It Later
+ Read more on Scribd
+ View on Wikipedia
+ Tip with Flattr
+ Follow me on Tumblr
+ Subscribe to my Posterous
+ Check in with Gowalla
+ Check in with foursquare
+ Write a review on Yelp
+ Follow me on Soundcloud
+ Read on Smashing Magazine
+ Sign in with WordPress
+ Sign in with IntenseDebate
+ Sign in with OpenID
+ Sign in with Gmail
+ Sign in with Eventbrite
+ Sign in with Eventasaurus
+ Sign in with Meetup.com
+ Sign in with AIM
+ Follow me on Plancast
+ Subscribe on YouTube
+ Available on the Mac App Store
+ View Creative Commons Licence
+
+ Follow me on Weibo
+ Follow me on Plurk
+ Follow me on Grooveshark
+ Post on Blogger
+ Sign in with Viadeo
+ Subscribe to this Podcast
+ View Portfolio on 500px
+ Bitcoin accepted here
+ View Portfolio on 99Designs
+ Stumble!
+ Download on iTunes
+ Find me on Myspace
+ Sign in with Windows Live
+ Find Events with Eventful
+ Influence with Klout
+ Sign in with Xing
+ Upload to Flickr
+ Sign in with Del.icio.us
+ Download from Google Play
+ Reserve with OpenTable
+ Digg this
+ Share on Reddit
+ Fund us on AngelList
+ Sign-in with Instagram
+ Call a phone
+ Send a message
+ Add to calendar
+ Print this page
+ Add to cart
+
+
+
+ Thanks to @guillermovs , @kamens , @vizualover , and @leaverou for code refinements and suggestions.
+
+ Massive thanks to @drewwilson for making the multi-purpose buttons possible with his incredible Pictos icons .
+
+ See code samples at zocial.smcllns.com — ask questions to @smcllns
+
+
+
+
+
+
+
+
diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js
new file mode 100644
index 00000000000..eae423fae1f
--- /dev/null
+++ b/addons/auth_oauth/static/src/js/auth_oauth.js
@@ -0,0 +1,64 @@
+openerp.auth_oauth = function(instance) {
+ var QWeb = instance.web.qweb;
+
+ instance.web.Login = instance.web.Login.extend({
+ start: function(parent, params) {
+ var d = this._super.apply(this, arguments);
+ this.$element.on('click', 'a.zocial', this.on_oauth_sign_in);
+ this.oauth_providers = [];
+ if(this.params.oauth_error === 1) {
+ this.do_warn("Sign up error.","Sign up is not allowed on this database.");
+ } else if(this.params.oauth_error === 2) {
+ this.do_warn("Authentication error","");
+ }
+ return d.then(this.do_oauth_load);
+ },
+ do_oauth_load: function() {
+ var db = this.$("form [name=db]").val();
+ if (db) {
+ this.rpc("/auth_oauth/list_providers", { dbname: db }).then(this.on_oauth_loaded);
+ }
+ },
+ on_oauth_loaded: function(result) {
+ this.oauth_providers = result;
+ console.log(result);
+ var buttons = QWeb.render("auth_oauth.Login.button",{"widget":this});
+ console.log(buttons);
+ this.$(".oe_login_pane form ul").after(buttons);
+ },
+ on_oauth_sign_in: function(ev) {
+ ev.preventDefault();
+ var index = $(ev.target).data('index');
+ var p = this.oauth_providers[index];
+ var ret = location.protocol+"//"+location.host+"/";
+ var dbname = self.$("form [name=db]").val();
+ var state_object = {
+ d: dbname,
+ p: p.id
+ }
+ var state = JSON.stringify(state_object);
+ var params = {
+ response_type: 'token',
+ client_id: p.client_id,
+ redirect_uri: ret,
+ scope: p.scope,
+ state: state,
+ };
+ var url = p.auth_endpoint + '?' + $.param(params);
+ window.location = url;
+ },
+ });
+
+ instance.web.WebClient = instance.web.WebClient.extend({
+ start: function() {
+ this._super.apply(this, arguments);
+ var params = $.deparam(window.location.hash.substring(1));
+ // alert(JSON.stringify(params));
+ if (params.hasOwnProperty('access_token')) {
+ var url = "/auth_oauth/signin" + '?' + $.param(params);
+ window.location = url;
+ }
+ },
+ });
+
+};
diff --git a/addons/auth_oauth/static/src/xml/auth_oauth.xml b/addons/auth_oauth/static/src/xml/auth_oauth.xml
new file mode 100644
index 00000000000..c2693804e59
--- /dev/null
+++ b/addons/auth_oauth/static/src/xml/auth_oauth.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/addons/auth_openid/controllers/main.py b/addons/auth_openid/controllers/main.py
index dc81730daf2..eba711dae7a 100644
--- a/addons/auth_openid/controllers/main.py
+++ b/addons/auth_openid/controllers/main.py
@@ -28,6 +28,7 @@ import werkzeug.urls
import werkzeug.exceptions
from openerp.modules.registry import RegistryManager
+from openerp.addons.web.controllers.main import login_and_redirect, set_cookie_and_redirect
try:
import openerp.addons.web.common.http as openerpweb
except ImportError:
@@ -159,7 +160,7 @@ class OpenIDController(openerpweb.Controller):
def process(self, req, **kw):
session = getattr(req.session, 'openid_session', None)
if not session:
- return werkzeug.utils.redirect('/')
+ return set_cookie_and_redirect(req, '/')
oidconsumer = consumer.Consumer(session, self._store, consumer_class=GoogleAppsAwareConsumer)
@@ -168,12 +169,11 @@ class OpenIDController(openerpweb.Controller):
display_identifier = info.getDisplayIdentifier()
session['status'] = info.status
- user_id = None
if info.status == consumer.SUCCESS:
dbname = session['dbname']
- with utils.cursor(dbname) as cr:
- registry = RegistryManager.get(dbname)
+ registry = RegistryManager.get(dbname)
+ with registry.cursor() as cr:
Modules = registry.get('ir.module.module')
installed = Modules.search_count(cr, 1, ['&', ('name', '=', 'auth_openid'), ('state', '=', 'installed')]) == 1
@@ -206,10 +206,9 @@ class OpenIDController(openerpweb.Controller):
# TODO fill empty fields with the ones from sreg/ax
cr.commit()
- req.session.authenticate(dbname, login, key, {})
+ return login_and_redirect(req, dbname, login, key)
- if not user_id:
- session['message'] = 'This OpenID identifier is not associated to any active users'
+ session['message'] = 'This OpenID identifier is not associated to any active users'
elif info.status == consumer.SETUP_NEEDED:
session['message'] = info.setup_url
@@ -223,8 +222,7 @@ class OpenIDController(openerpweb.Controller):
# information in a log.
session['message'] = 'Verification failed.'
- fragment = '#loginerror' if not user_id else ''
- return werkzeug.utils.redirect('/' + fragment)
+ return set_cookie_and_redirect(req, '/#action=login&loginerror=1')
@openerpweb.jsonrequest
def status(self, req):
diff --git a/addons/auth_openid/res_users.py b/addons/auth_openid/res_users.py
index 506c7e1c094..9b02ce42991 100644
--- a/addons/auth_openid/res_users.py
+++ b/addons/auth_openid/res_users.py
@@ -2,7 +2,7 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2010-2011 OpenERP s.a. ().
+# Copyright (C) 2010-2012 OpenERP s.a. ().
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -18,6 +18,7 @@
# along with this program. If not, see .
#
##############################################################################
+from openerp.modules.registry import RegistryManager
from openerp.osv import osv, fields
import openerp.exceptions
import tools
@@ -64,7 +65,7 @@ class res_users(osv.osv):
if result:
return result
else:
- with utils.cursor(db) as cr:
+ with RegistryManager.get(db).cursor() as cr:
cr.execute("""UPDATE res_users
SET login_date=now() AT TIME ZONE 'UTC'
WHERE login=%s AND openid_key=%s AND active=%s RETURNING id""",
@@ -73,14 +74,13 @@ class res_users(osv.osv):
cr.commit()
return res[0] if res else False
-
def check(self, db, uid, passwd):
try:
return super(res_users, self).check(db, uid, passwd)
except openerp.exceptions.AccessDenied:
if not passwd:
raise
- with utils.cursor(db) as cr:
+ with RegistryManager.get(db).cursor() as cr:
cr.execute('''SELECT COUNT(1)
FROM res_users
WHERE id=%s
diff --git a/addons/auth_openid/static/src/js/auth_openid.js b/addons/auth_openid/static/src/js/auth_openid.js
index fd6ec01cc0f..1417bc471ce 100644
--- a/addons/auth_openid/static/src/js/auth_openid.js
+++ b/addons/auth_openid/static/src/js/auth_openid.js
@@ -8,7 +8,7 @@ instance.web.Login = instance.web.Login.extend({
this._super.apply(this, arguments);
var self = this;
- this._default_error_message = this.$element.find('.login_error_message').text();
+ this._default_error_message = this.$element.find('.oe_login_error_message').text();
this.$openid_selected_button = $();
this.$openid_selected_input = $();
@@ -40,8 +40,7 @@ instance.web.Login = instance.web.Login.extend({
}
});
- this._check_fragment();
-
+ this._check_error();
},
@@ -67,11 +66,9 @@ instance.web.Login = instance.web.Login.extend({
},
- _check_fragment: function() {
+ _check_error: function() {
var self = this;
- var fragment = jQuery.deparam.fragment();
- console.log(fragment);
- if (fragment.loginerror !== undefined) {
+ if (this.params.loginerror !== undefined) {
this.rpc('/auth_openid/login/status', {}, function(result) {
if (_.contains(['success', 'failure'], result.status) && result.message) {
self.do_warn('Invalid OpenID Login', result.message);
@@ -132,11 +129,12 @@ instance.web.Login = instance.web.Login.extend({
do_warn: function(title, msg) {
//console.warn(title, msg);
- this.$element.find('.login_error_message').text(msg).show();
+ this.$element.find('.oe_login_error_message').text(msg).show();
+ this._super(title, msg);
},
reset_error_message: function() {
- this.$element.find('.login_error_message').text(this._default_error_message);
+ this.$element.find('.oe_login_error_message').text(this._default_error_message);
}
});
diff --git a/addons/auth_openid/static/src/xml/auth_openid.xml b/addons/auth_openid/static/src/xml/auth_openid.xml
index 34894555668..aa61d161657 100644
--- a/addons/auth_openid/static/src/xml/auth_openid.xml
+++ b/addons/auth_openid/static/src/xml/auth_openid.xml
@@ -3,7 +3,7 @@
-
+
-
-
-
- Google Apps Domain:
-
-
-
- Username:
-
-
-
- OpenID URL:
-
-
-
-
-
-
+
Google Apps Domain
@@ -54,7 +37,7 @@
-
+
this.each(function() {
var $i = $(this),
dp = $i.find('input').attr('name');
diff --git a/addons/auth_openid/utils.py b/addons/auth_openid/utils.py
index 444b5eeaa05..806198f99c2 100644
--- a/addons/auth_openid/utils.py
+++ b/addons/auth_openid/utils.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2010-2011 OpenERP s.a. ().
+# Copyright (C) 2010-2012 OpenERP s.a. ().
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -15,11 +15,9 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
+# along with this program. If not, see .
#
##############################################################################
-from contextlib import contextmanager
-from openerp.modules.registry import RegistryManager
KEY_LENGTH = 16
@@ -35,14 +33,4 @@ SREG2AX = { # from http://www.axschema.org/types/#sreg
'timezone': 'http://axschema.org/pref/timezone',
}
-
-@contextmanager
-def cursor(db):
- cr = RegistryManager.get(db).db.cursor()
- try:
- yield cr
- finally:
- cr.close()
-
-
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/auth_signup/__init__.py b/addons/auth_signup/__init__.py
index 1a120e52d18..2331ae629a8 100644
--- a/addons/auth_signup/__init__.py
+++ b/addons/auth_signup/__init__.py
@@ -19,5 +19,6 @@
#
##############################################################################
+import controllers
import res_config
-import auth_signup
+import res_users
diff --git a/addons/auth_signup/__openerp__.py b/addons/auth_signup/__openerp__.py
index 227d5f1017d..765a36ef252 100644
--- a/addons/auth_signup/__openerp__.py
+++ b/addons/auth_signup/__openerp__.py
@@ -27,16 +27,13 @@
'category': 'Authentication',
'website': 'http://www.openerp.com',
'installable': True,
- 'depends': ['auth_anonymous', 'base_setup'],
+ 'depends': ['base_setup'],
'data': [
'res_config.xml',
],
'js': [
'static/src/js/auth_signup.js',
],
- 'css': [
- 'static/src/css/auth_signup.css',
- ],
'qweb': [
'static/src/xml/auth_signup.xml',
],
diff --git a/addons/auth_signup/auth_signup.py b/addons/auth_signup/auth_signup.py
deleted file mode 100644
index 96d1ea132de..00000000000
--- a/addons/auth_signup/auth_signup.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2012-today OpenERP SA ()
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see
-#
-##############################################################################
-
-from openerp.osv import osv, fields
-
-class signup_signup(osv.TransientModel):
- _name = 'auth.signup'
-
- # TODO add captcha
- _columns = {
- 'name': fields.char('Name', size=64),
- 'email': fields.char('Email', size=64),
- 'password': fields.char('Password', size=64),
- }
-
- def create(self, cr, uid, values, context=None):
- # NOTE here, invalid values raises exceptions to avoid storing
- # sensitive data into the database (which then are available to anyone)
-
- new_user = {
- 'name': values['name'],
- 'login': values['email'],
- 'email': values['email'],
- 'password': values['password'],
- 'active': True,
- }
-
- user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth.signup_template_user_id', 0)
- if user_template_id:
- self.pool.get('res.users').copy(cr, 1, user_template_id, new_user, context=context)
- else:
- self.pool.get('res.users').create(cr, 1, new_user, context=context)
-
- # Dont store anything
- return 0
diff --git a/addons/auth_signup/controllers/__init__.py b/addons/auth_signup/controllers/__init__.py
new file mode 100644
index 00000000000..e11f9ba81bb
--- /dev/null
+++ b/addons/auth_signup/controllers/__init__.py
@@ -0,0 +1,3 @@
+import main
+
+# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py
new file mode 100644
index 00000000000..0ed2151d12b
--- /dev/null
+++ b/addons/auth_signup/controllers/main.py
@@ -0,0 +1,34 @@
+import logging
+
+import werkzeug.urls
+
+from openerp.modules.registry import RegistryManager
+from openerp.addons.web.controllers.main import login_and_redirect
+import openerp.addons.web.common.http as openerpweb
+
+_logger = logging.getLogger(__name__)
+
+class OpenIDController(openerpweb.Controller):
+ _cp_path = '/auth_signup'
+
+ @openerpweb.httprequest
+ def signup(self, req, dbname, name, login, password):
+ url = '/'
+ registry = RegistryManager.get(dbname)
+ with registry.cursor() as cr:
+ try:
+ Users = registry.get('res.users')
+ credentials = Users.auth_signup(cr, 1, name, login, password)
+ cr.commit()
+ return login_and_redirect(req, *credentials)
+ except AttributeError:
+ # auth_signup is not installed
+ _logger.exception('attribute error when signup')
+ url = "/#action=auth_signup&error=NA" # Not Available
+ except Exception:
+ # signup error
+ _logger.exception('error when signup')
+ url = "/#action=auth_signup&error=UE" # Unexcpected Error
+ return werkzeug.utils.redirect(url)
+
+# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py
new file mode 100644
index 00000000000..1d77a3f9473
--- /dev/null
+++ b/addons/auth_signup/res_users.py
@@ -0,0 +1,46 @@
+import openerp
+from openerp.osv import osv
+
+class res_users(osv.Model):
+ _inherit = 'res.users'
+
+ def auth_signup_create(self, cr, uid, new_user, context=None):
+ # new_user:
+ # login
+ # email
+ # name (optional)
+ # partner_id (optional)
+ # groups (optional)
+ # sign (for partner_id and groups)
+ #
+ user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth.signup_template_user_id', 0)
+ if user_template_id:
+ self.pool.get('res.users').copy(cr, 1, user_template_id, new_user, context=context)
+ else:
+ self.pool.get('res.users').create(cr, 1, new_user, context=context)
+
+ def auth_signup(self, cr, uid, name, login, password, context=None):
+ r = (cr.dbname, login, password)
+ res = self.search(cr, uid, [("login", "=", login)])
+ if res:
+ # Existing user
+ user_id = res[0]
+ try:
+ self.check(cr.dbname, user_id, password)
+ # Same password
+ except openerp.exceptions.AccessDenied:
+ # Different password
+ raise
+ else:
+ # New user
+ new_user = {
+ 'name': name,
+ 'login': login,
+ 'user_email': login,
+ 'password': password,
+ 'active': True,
+ }
+ self.auth_signup_create(cr, uid, new_user)
+ return r
+
+#
diff --git a/addons/auth_signup/static/src/css/auth_signup.css b/addons/auth_signup/static/src/css/auth_signup.css
deleted file mode 100644
index 1e8d7d9d8d8..00000000000
--- a/addons/auth_signup/static/src/css/auth_signup.css
+++ /dev/null
@@ -1,9 +0,0 @@
-.openerp .oe_login .oe_login_pane ul.oe_signup a {
- color: #eeeeee;
- margin: 0 8px;
-}
-.openerp .oe_login .oe_login_pane ul.oe_signup a:hover {
- text-decoration: underline;
-}
-
-
diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js
index 9dda111f044..2ab13aa7598 100644
--- a/addons/auth_signup/static/src/js/auth_signup.js
+++ b/addons/auth_signup/static/src/js/auth_signup.js
@@ -1,65 +1,38 @@
openerp.auth_signup = function(instance) {
+ instance.auth_signup = instance.auth_signup || {};
var _t = instance.web._t;
instance.web.Login.include({
start: function() {
var self = this;
-
this.$('a.oe_signup').click(function() {
- var db = self.$("form [name=db]").val();
- if (!db) {
- self.do_warn(_t("Login"), _t("No database selected!"));
- return false;
- }
-
- var cnx = instance.session;
- if (cnx.session_is_valid()) {
- self._signup();
- } else {
- cnx.session_authenticate(db, 'anonymous', 'anonymous', true).then(function() {
- self._signup();
- }).fail(function(error, event) {
- console.log(error);
- // cannot log as anonymous or auth_signup not installed
- self.do_warn(_t('Sign Up'), _.str.sprintf(_t('Signup functionnality is not available for database %s'), db), true);
- });
- }
+ var dbname = self.$("form [name=db]").val();
+ self.do_action({
+ type: 'ir.actions.client',
+ tag: 'auth_signup.signup',
+ params: {'dbname': dbname},
+ target: 'new',
+ name: 'Sign up'
+ });
return true;
});
return this._super();
-
},
-
- _signup: function() {
- this.do_action({
- type: 'ir.actions.client',
- tag: 'auth_signup.signup',
- target: 'new',
- name: 'Sign up'
- });
- }
});
- instance.auth_signup = instance.auth_signup || {};
instance.auth_signup.Signup = instance.web.Widget.extend({
template: 'auth_signup.signup',
- init: function() {
- this._super.apply(this, arguments);
- this.dataset = new instance.web.DataSet(this, 'auth.signup');
+ init: function(parent, params) {
+ this.params = params;
+ return this._super();
},
start: function() {
var self = this;
- this.$('input[type=password]').change(function() {
+ this.$('input[name=password_confirmation]').keyup(function() {
var v = $(this).val();
- var e = !_.isEmpty(v);
- if (e) {
- e =_.all(self.$('input[type=password]'), function(i) {
- return $(i).val() === v;
- });
- }
var $b = self.$('button');
- if (e) {
+ if (_.isEmpty(v) || self.$('input[name=password]').val() === v) {
$b.removeAttr('disabled');
} else {
$b.attr('disabled', 'disabled');
@@ -70,36 +43,18 @@ openerp.auth_signup = function(instance) {
if(ev) {
ev.preventDefault();
}
- var name = self.$('input[name=name]').val();
- var email = self.$('input[name=email]').val();
- var password = self.$('input[name=password]').val();
-
- self.dataset.create({
- name: name,
- email: email,
- password: password
- }, function() {
- self.do_action({
- type: 'ir.actions.client',
- tag: 'login',
- params: {
- db: instance.session.db,
- login: email,
- password: password,
- login_successful: function() {
- self.do_action('home');
- }
- }
- });
- });
- return false;
-
+ var params = {
+ dbname : self.params.dbname,
+ name: self.$('input[name=name]').val(),
+ login: self.$('input[name=email]').val(),
+ password: self.$('input[name=password]').val(),
+ };
+ var url = "/auth_signup/signup?" + $.param(params);
+ window.location = url;
});
- return $.when(this._super());
+ return this._super();
}
-
});
instance.web.client_actions.add("auth_signup.signup", "instance.auth_signup.Signup");
-
};
diff --git a/addons/auth_signup/static/src/xml/auth_signup.xml b/addons/auth_signup/static/src/xml/auth_signup.xml
index 92343d96281..c2eec846d15 100644
--- a/addons/auth_signup/static/src/xml/auth_signup.xml
+++ b/addons/auth_signup/static/src/xml/auth_signup.xml
@@ -14,10 +14,10 @@
diff --git a/addons/base_calendar/crm_meeting_view.xml b/addons/base_calendar/crm_meeting_view.xml
index b57d7dcb2c7..9776d66b839 100644
--- a/addons/base_calendar/crm_meeting_view.xml
+++ b/addons/base_calendar/crm_meeting_view.xml
@@ -232,6 +232,7 @@
+
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index a0ec728a4d8..146417a7abb 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -859,13 +859,10 @@ class crm_lead(base_stage, osv.osv):
# OpenChatter methods and notifications
# ----------------------------------------
- def message_get_subscribers(self, cr, uid, ids, context=None):
- """ Override to add the salesman. """
- user_ids = super(crm_lead, self).message_get_subscribers(cr, uid, ids, context=context)
- for obj in self.browse(cr, uid, ids, context=context):
- if obj.user_id and not obj.user_id.id in user_ids:
- user_ids.append(obj.user_id.id)
- return user_ids
+ def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
+ """ Add 'user_id' to the monitored fields """
+ res = super(crm_lead, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
+ return res + ['user_id']
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
""" Override of the (void) default notification method. """
diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml
index 9b187ed4417..e47e0cafcad 100644
--- a/addons/crm/crm_lead_view.xml
+++ b/addons/crm/crm_lead_view.xml
@@ -222,6 +222,7 @@
+
@@ -532,6 +533,7 @@
+
diff --git a/addons/crm/crm_phonecall.py b/addons/crm/crm_phonecall.py
index 7a544da5dc1..e2c2a2b02da 100644
--- a/addons/crm/crm_phonecall.py
+++ b/addons/crm/crm_phonecall.py
@@ -271,7 +271,6 @@ class crm_phonecall(base_state, osv.osv):
def case_open_send_note(self, cr, uid, ids, context=None):
lead_obj = self.pool.get('crm.lead')
for phonecall in self.browse(cr, uid, ids, context=context):
- phonecall.message_subscribe([phonecall.user_id.id], context=context)
if phonecall.opportunity_id:
lead = phonecall.opportunity_id
# convert datetime field to a datetime, using server format, then
diff --git a/addons/crm/crm_phonecall_view.xml b/addons/crm/crm_phonecall_view.xml
index 1639d075f3e..2f885e09b61 100644
--- a/addons/crm/crm_phonecall_view.xml
+++ b/addons/crm/crm_phonecall_view.xml
@@ -152,6 +152,7 @@
+
diff --git a/addons/crm_claim/crm_claim_view.xml b/addons/crm_claim/crm_claim_view.xml
index cf5d1a780e8..820fb38e58a 100644
--- a/addons/crm_claim/crm_claim_view.xml
+++ b/addons/crm_claim/crm_claim_view.xml
@@ -182,6 +182,7 @@
+
diff --git a/addons/crm_helpdesk/crm_helpdesk_view.xml b/addons/crm_helpdesk/crm_helpdesk_view.xml
index 02c6603280a..5399c9880ca 100644
--- a/addons/crm_helpdesk/crm_helpdesk_view.xml
+++ b/addons/crm_helpdesk/crm_helpdesk_view.xml
@@ -100,6 +100,7 @@
+
diff --git a/addons/event/event_view.xml b/addons/event/event_view.xml
index c550d36016c..bfed55b17cf 100644
--- a/addons/event/event_view.xml
+++ b/addons/event/event_view.xml
@@ -196,6 +196,7 @@
+
@@ -477,6 +478,7 @@
+
diff --git a/addons/hr_expense/hr_expense_view.xml b/addons/hr_expense/hr_expense_view.xml
index 506b9d7183f..a810b87dad0 100644
--- a/addons/hr_expense/hr_expense_view.xml
+++ b/addons/hr_expense/hr_expense_view.xml
@@ -120,6 +120,7 @@
+
diff --git a/addons/hr_holidays/hr_holidays.py b/addons/hr_holidays/hr_holidays.py
index 0134fc79fdd..e888f9b5c3b 100644
--- a/addons/hr_holidays/hr_holidays.py
+++ b/addons/hr_holidays/hr_holidays.py
@@ -364,15 +364,11 @@ class hr_holidays(osv.osv):
dom = ['|'] + dom + [ ('state','=','validate1') ]
return dom
- def message_get_subscribers(self, cr, uid, ids, context=None):
- """ Override to add employee and its manager. """
- user_ids = super(hr_holidays, self).message_get_subscribers(cr, uid, ids, context=context)
- for obj in self.browse(cr, uid, ids, context=context):
- if obj.user_id and not obj.user_id.id in user_ids:
- user_ids.append(obj.user_id.id)
- if obj.employee_id.parent_id and not obj.employee_id.parent_id.user_id.id in user_ids:
- user_ids.append(obj.employee_id.parent_id.user_id.id)
- return user_ids
+ def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
+ """ Add 'user_id' and 'manager' to the monitored fields """
+ res = super(hr_holidays, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
+ # TODO: add manager
+ return res + ['user_id']
def create_notificate(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
diff --git a/addons/hr_holidays/hr_holidays_view.xml b/addons/hr_holidays/hr_holidays_view.xml
index 40cdda25529..89ce641b271 100644
--- a/addons/hr_holidays/hr_holidays_view.xml
+++ b/addons/hr_holidays/hr_holidays_view.xml
@@ -136,6 +136,7 @@
+
@@ -182,6 +183,7 @@
+
diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py
index 2e5b7b6403e..0ace2574d65 100644
--- a/addons/hr_recruitment/hr_recruitment.py
+++ b/addons/hr_recruitment/hr_recruitment.py
@@ -461,13 +461,10 @@ class hr_applicant(base_stage, osv.Model):
# OpenChatter methods and notifications
# -------------------------------------------------------
- def message_get_subscribers(self, cr, uid, ids, context=None):
- """ Override to add responsible user. """
- user_ids = super(hr_applicant, self).message_get_subscribers(cr, uid, ids, context=context)
- for obj in self.browse(cr, uid, ids, context=context):
- if obj.user_id and not obj.user_id.id in user_ids:
- user_ids.append(obj.user_id.id)
- return user_ids
+ def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
+ """ Add 'user_id' to the monitored fields """
+ res = super(hr_applicant, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
+ return res + ['user_id']
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
""" Override of the (void) default notification method. """
diff --git a/addons/hr_recruitment/hr_recruitment_view.xml b/addons/hr_recruitment/hr_recruitment_view.xml
index 507874a6fda..548b4f93ead 100644
--- a/addons/hr_recruitment/hr_recruitment_view.xml
+++ b/addons/hr_recruitment/hr_recruitment_view.xml
@@ -181,6 +181,7 @@
+
diff --git a/addons/idea/idea_view.xml b/addons/idea/idea_view.xml
index 18c81a497d0..eab3d03ceea 100644
--- a/addons/idea/idea_view.xml
+++ b/addons/idea/idea_view.xml
@@ -78,6 +78,7 @@
+
diff --git a/addons/mail/__init__.py b/addons/mail/__init__.py
index 54e20a6a9ef..49ee9e18995 100644
--- a/addons/mail/__init__.py
+++ b/addons/mail/__init__.py
@@ -22,9 +22,10 @@
import mail_alias
import mail_message
import mail_mail
+import mail_followers
import mail_thread
import mail_group
-import mail_subscription
+import ir_needaction
import res_partner
import res_users
import report
diff --git a/addons/mail/__openerp__.py b/addons/mail/__openerp__.py
index fea3d603f6a..0e1caabcf65 100644
--- a/addons/mail/__openerp__.py
+++ b/addons/mail/__openerp__.py
@@ -64,7 +64,7 @@ The main features of the module are:
'wizard/mail_compose_message_view.xml',
'res_config_view.xml',
'mail_message_view.xml',
- 'mail_subscription_view.xml',
+ 'mail_followers_view.xml',
'mail_thread_view.xml',
'mail_group_view.xml',
'res_partner_view.xml',
@@ -102,9 +102,11 @@ The main features of the module are:
'js': [
'static/lib/jquery.expander/jquery.expander.js',
'static/src/js/mail.js',
+ 'static/src/js/mail_followers.js',
],
'qweb': [
'static/src/xml/mail.xml',
+ 'static/src/xml/mail_followers.xml',
],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/mail/mail_subscription.py b/addons/mail/mail_followers.py
similarity index 89%
rename from addons/mail/mail_subscription.py
rename to addons/mail/mail_followers.py
index f5ca21f0fa1..24ab4a56b4d 100644
--- a/addons/mail/mail_subscription.py
+++ b/addons/mail/mail_followers.py
@@ -22,17 +22,20 @@
from osv import osv
from osv import fields
-class mail_subscription(osv.osv):
- """
- mail_subscription holds the data related to the follow mechanism inside OpenERP.
+class mail_followers(osv.Model):
+ """ mail_followers holds the data related to the follow mechanism inside
+ OpenERP. Users can choose to follow documents (records) of any kind that
+ inherits from mail.thread. Following documents allow to receive
+ notifications for new messages.
A subscription is characterized by:
:param: res_model: model of the followed objects
:param: res_id: ID of resource (may be 0 for every objects)
"""
- _name = 'mail.subscription'
+ _name = 'mail.followers'
_rec_name = 'id'
+ _log_access = False
_order = 'res_model asc'
- _description = 'Mail subscription'
+ _description = 'Mail Document Followers'
_columns = {
'res_model': fields.char('Related Document Model', size=128,
required=True, select=1,
@@ -43,10 +46,8 @@ class mail_subscription(osv.osv):
ondelete='cascade', required=True, select=1),
}
-class mail_notification(osv.osv):
- """
- mail_notification is a relational table modeling messages pushed to users.
- :param: read: not used currently
+class mail_notification(osv.Model):
+ """ mail_notification is a relational table modeling messages pushed to users.
"""
_name = 'mail.notification'
_rec_name = 'id'
diff --git a/addons/mail/mail_subscription_view.xml b/addons/mail/mail_followers_view.xml
similarity index 61%
rename from addons/mail/mail_subscription_view.xml
rename to addons/mail/mail_followers_view.xml
index 19e31cf8fc9..62e93430675 100644
--- a/addons/mail/mail_subscription_view.xml
+++ b/addons/mail/mail_followers_view.xml
@@ -2,16 +2,14 @@
-
-
-
- mail.subscription.tree
- mail.subscription
+
+
+ mail.followers.tree
+ mail.followers
+ tree
10
-
+
@@ -19,26 +17,22 @@
-
-
+
mail.notification.tree
mail.notification
10
-
+
-
-
- Subscriptions
- mail.subscription
+
+ Followers
+ mail.followers
form
tree,form
@@ -50,9 +44,9 @@
tree,form
-
- -->
+
+ -->
@@ -1133,6 +1134,7 @@
+