+
@@ -107,7 +107,7 @@
-
+
@@ -143,8 +143,9 @@
-
-
+
+
+
@@ -188,7 +189,7 @@
form
kanban,tree,form
- {'search_default_active_true':True}
+ {'search_default_open_true':True}
diff --git a/addons/note/security/ir.rule.xml b/addons/note/security/ir.rule.xml
index 82994b960c2..5f4882c3048 100644
--- a/addons/note/security/ir.rule.xml
+++ b/addons/note/security/ir.rule.xml
@@ -1,12 +1,21 @@
+
Only followers can access a sticky notes
['|',('message_follower_ids','=',False),('message_follower_ids','=',user.partner_id.id)]
+
+
+ Each user have his stage name
+
+ ['|',('user_id','=',False),('user_id','=',user.id)]
+
+
+
From 6dc01c405b63d8985f9cc90e8e09535c48be5a8c Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Mon, 17 Sep 2012 15:22:12 +0200
Subject: [PATCH 40/73] [IMP] portal: simplify portal access management wizard
bzr revid: rco@openerp.com-20120917132212-wo2wrjzja0xsuys8
---
addons/portal/wizard/portal_wizard.py | 369 +++++++-------------
addons/portal/wizard/portal_wizard_view.xml | 36 +-
2 files changed, 133 insertions(+), 272 deletions(-)
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index 969f74b5bd8..26fbb383e11 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -25,6 +25,7 @@ import random
from osv import osv, fields
from tools.translate import _
from tools.misc import email_re
+from openerp import SUPERUSER_ID
from base.res.res_partner import _lang_get
_logger = logging.getLogger(__name__)
@@ -48,8 +49,6 @@ OpenERP - Open Source Business Applications
http://www.openerp.com
""")
-ROOT_UID = 1
-
# character sets for passwords, excluding 0, O, o, 1, I, l
_PASSU = 'ABCDEFGHIJKLMNPQRSTUVWXYZ'
_PASSL = 'abcdefghijkmnpqrstuvwxyz'
@@ -70,277 +69,157 @@ def extract_email(email):
class wizard(osv.osv_memory):
"""
- A wizard to create portal users from instances of 'res.partner'. The purpose
- is to provide an OpenERP database access to customers or suppliers.
+ A wizard to manage the creation/removal of portal users.
"""
- _name = 'res.portal.wizard'
- _description = 'Portal Wizard'
+ _name = 'portal.wizard'
+ _description = 'Portal Access Management'
_columns = {
'partner_id': fields.many2one('res.partner', required=True, string="Partner"),
'portal_id': fields.many2one('res.groups', domain=[('is_portal', '=', True)], required=True,
- string='Portal',
- help="The portal in which new users must be added"),
- 'user_ids': fields.one2many('res.portal.wizard.user', 'wizard_id',
- string='Users'),
- 'message': fields.text(string='Invitation message',
- help="This text is included in the welcome email sent to the users"),
+ string='Portal', help="The portal that users can be added in or removed from."),
+ 'user_ids': fields.one2many('portal.wizard.user', 'wizard_id', string='Users'),
+ 'message': fields.text(string='Invitation Message',
+ help="This text is included in the welcome email sent to the users."),
}
- def default_get(self, cr, uid, fields, context=None):
- if context is None:
- context = {}
- partner_id = context.get('active_id', False)
- portal_id = context.get('portal_id', False)
- res = {}
- if not partner_id:
- return res
+ def _default_partner(self, cr, uid, context):
+ return context and context.get('active_id') or False
- if 'partner_id' in fields:
- res.update({'partner_id': partner_id})
-
- if 'user_ids' in fields and portal_id:
- user_ids = self.get_portal_users(cr, uid, [partner_id], portal_id, context=context)
- res.update({'user_ids': user_ids})
- return res
+ def _default_portal(self, cr, uid, context):
+ portal_ids = self.pool.get('res.groups').search(cr, uid, [('is_portal', '=', True)])
+ return portal_ids and portal_ids[0] or False
+ _defaults = {
+ 'partner_id': _default_partner,
+ 'portal_id': _default_portal,
+ }
def onchange_portal_id(self, cr, uid, ids, partner_id, portal_id, context=None):
- if not portal_id:
- return {'value': {}}
- user_list = self.get_portal_users(cr, uid, [partner_id], portal_id, context=context)
- return {'value': {'user_ids': user_list}}
-
-
- def _search_partner_user(self, cr, uid, partner_id, context=None):
- res_user = self.pool.get('res.users')
- partner = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context)
- if partner.parent_id:
- user_ids = res_user.search(cr, uid, [('login','=',partner.email)])
- else:
- user_ids = res_user.search(cr, uid, [('partner_id','=', partner.id)])
- return user_ids
-
- def _search_portal_user(self, cr, uid, partner_id, context=None):
- res_user = self.pool.get('res.users')
+ assert partner_id
+ # for each partner, determine corresponding portal.wizard.user records
res_partner = self.pool.get('res.partner')
- partner = res_partner.browse(cr, uid, partner_id, context=context)
- user_ids = res_user.search(cr, uid, [('login','=',partner.email)])
- user_id = False
- if user_ids and len(user_ids):
- user_id = user_ids[0]
- return user_id
+ partner_ids = [partner_id]
+ user_changes = []
+ for partner in res_partner.browse(cr, SUPERUSER_ID, partner_ids, context):
+ for contact in (partner.child_ids or [partner]):
+ in_portal = False
+ if contact.user_ids:
+ in_portal = portal_id in [g.id for g in contact.user_ids[0].groups_id]
+ user_changes.append((0, 0, {
+ 'partner_id': contact.id,
+ 'email': contact.email,
+ 'in_portal': in_portal,
+ }))
+ return {'value': {'user_ids': user_changes}}
- def _portal_user_dict(self, cr, uid, partner, portal_id, context=None):
- res_user = self.pool.get('res.users')
- users = []
- if partner.parent_id:
- lang = partner.parent_id.lang or 'en_US'
- company_id = partner.parent_id.id
- else:
- lang = partner.lang or 'en_US'
- company_id = partner.id
-
- def _portal_user(address):
- if not self._search_portal_user(cr, uid, address.id, context=context):
- if address.email:
- users.append({
- 'name': address.name,
- 'email': extract_email(address.email),
- 'lang': lang or 'en_US',
- 'partner_id': company_id,
- 'has_portal_user': False,
- })
-
- if not partner.child_ids:
- _portal_user(partner)
- for address in partner.child_ids:
- _portal_user(address)
- partner_user_ids = self._search_partner_user(cr, uid, partner.id, context=context)
- portal_users = [u.id for u in self.pool.get('res.groups').browse(cr, uid, portal_id, context=context).users]
- for user in res_user.browse(cr, uid, partner_user_ids, context=context):
- email = user and user.email or False
- has_portal_user = False
- if user.id in portal_users:
- has_portal_user = True
-
- if email:
- users.append({
- 'name': user and user.name,
- 'email': email and extract_email(email) or False,
- 'lang': lang or 'en_US',
- 'partner_id': company_id,
- 'has_portal_user': has_portal_user,
- 'user_id': user.id,
- })
- return users
-
- def get_portal_users(self, cr, uid, partner_ids, portal_id, context=None):
- users = []
- res_partner = self.pool.get('res.partner')
- for partner in res_partner.browse(cr, uid, partner_ids, context=context):
- users.extend(self._portal_user_dict(cr, uid, partner, portal_id, context=context))
- return users
-
-
- def action_manage_portal_access(self, cr, uid, ids, context=None):
- if context is None:
- context = {}
- clone_context = context
- clone_context['noshortcut'] = True # prevent shortcut creation
- context = dict(clone_context)
- res_portal_user = self.pool.get('res.portal.wizard.user')
- for data in self.browse(cr, uid, ids, context=context):
- if not data.user_ids:
- raise osv.except_osv(_('User required'),
- _('Create atleast one user for portal.'))
- portal_user_ids = [user.id for user in data.user_ids]
- res_portal_user.manage_portal_access(cr, uid, portal_user_ids, context=context)
+ def action_apply(self, cr, uid, ids, context=None):
+ wizard = self.browse(cr, uid, ids[0], context)
+ portal_user_ids = [user.id for user in wizard.user_ids]
+ self.pool.get('portal.wizard.user').action_apply(cr, uid, portal_user_ids, context)
return {'type': 'ir.actions.act_window_close'}
-wizard()
class wizard_user(osv.osv_memory):
"""
A model to configure users in the portal wizard.
"""
- _name = 'res.portal.wizard.user'
+ _name = 'portal.wizard.user'
_description = 'Portal User Config'
_columns = {
- 'wizard_id': fields.many2one('res.portal.wizard', required=True,
- string='Wizard'),
- 'name': fields.char(size=64, required=True,
- string='User Name',
- help="The user's real name"),
- 'email': fields.char(size=64, required=True,
- string='Email',
- help="Will be used as user login. "
- "Also necessary to send the account information to new users"),
- 'lang': fields.selection(_lang_get, required=True,
- string='Language',
- help="The language for the user's user interface"),
- 'partner_id': fields.related('wizard_id','partner_id',type='many2one',relation='res.partner',string='Partner',readonly=True),
- 'has_portal_user':fields.boolean('Has portal access'),
- 'user_id': fields.many2one('res.users', string="Related User")
+ 'wizard_id': fields.many2one('portal.wizard', string='Wizard', required=True),
+ 'partner_id': fields.many2one('res.partner', string='Contact', required=True, readonly=True),
+ 'email': fields.related('partner_id', 'email', type='char', string='Email'),
+ 'in_portal': fields.boolean('In Portal'),
}
- def _check_email(self, cr, uid, ids):
- """ check syntax of email address """
- for wuser in self.browse(cr, uid, ids):
- if not email_re.match(wuser.email): return False
- return True
-
- _constraints = [
- (_check_email, 'Invalid email address', ['email']),
- ]
-
- _defaults = {
- 'lang': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).partner_id.lang or 'en_US',
- 'partner_id': lambda self, cr, uid, ctx: ctx.get('active_id', False),
- }
-
- def send_email(self, cr, uid, portal_user, new_user_id, context=None):
- #TODO: use email template
- if context is None:
- context = {}
- ctx = dict(context)
+ def action_apply(self, cr, uid, ids, context=None):
res_users = self.pool.get('res.users')
- mail_mail = self.pool.get('mail.mail')
- user = res_users.browse(cr, ROOT_UID, uid, context)
+ for wizard_user in self.browse(cr, SUPERUSER_ID, ids, context):
+ portal = wizard_user.wizard_id.portal_id
+ user = self._retrieve_user(cr, SUPERUSER_ID, wizard_user, context)
+ if wizard_user.in_portal:
+ # create a user if necessary, and make sure it is in the portal group
+ if not user:
+ user = self._create_user(cr, SUPERUSER_ID, wizard_user, context)
+ if (not user.active) or (portal not in user.groups_id):
+ user.write({'active': True, 'groups_id': [(4, portal.id)]})
+ wizard_user = self.browse(cr, SUPERUSER_ID, wizard_user.id, context)
+ self._send_email(cr, uid, wizard_user, context)
+ else:
+ # remove the user (if it exists) from the portal group
+ if user:
+ if portal in user.groups_id:
+ values = {'groups_id': [(3, portal.id)]}
+ if len(user.groups_id) == 1:
+ values['active'] = False # deactivate user
+ user.write(values)
+
+ def _retrieve_user(self, cr, uid, wizard_user, context=None):
+ """ retrieve the (possibly inactive) user corresponding to wizard_user.partner_id
+ @param wizard_user: browse record of model portal.wizard.user
+ @return: browse record of model res.users
+ """
+ if wizard_user.partner_id.user_ids:
+ return wizard_user.partner_id.user_ids[0]
+ # the user may be inactive, search for it
+ res_users = self.pool.get('res.users')
+ domain = [('partner_id', '=', wizard_user.partner_id.id), ('active', '=', False)]
+ user_ids = res_users.search(cr, uid, domain)
+ return user_ids and res_users.browse(cr, uid, user_ids[0], context) or False
+
+ def _create_user(self, cr, uid, wizard_user, context=None):
+ """ create a new user for wizard_user.partner_id
+ @param wizard_user: browse record of model portal.wizard.user
+ @return: browse record of model res.users
+ """
+ res_users = self.pool.get('res.users')
+ create_context = dict(context or {}, noshortcut=True) # to prevent shortcut creation
+ values = {
+ 'login': wizard_user.email,
+ 'password': random_password(),
+ 'partner_id': wizard_user.partner_id.id,
+ 'groups_id': [(6, 0, [])],
+ 'share': True,
+ }
+ user_id = res_users.create(cr, uid, values, context=create_context)
+ return res_users.browse(cr, uid, user_id, context)
+
+ def _send_email(self, cr, uid, wizard_user, context=None):
+ """ send invitation email to a new portal user
+ @param wizard_user: browse record of model portal.wizard.user
+ @return: the id of the created mail.mail record
+ """
+ user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context)
if not user.email:
raise osv.except_osv(_('Email required'),
- _('You must have an email address in your User Preferences'
- ' to send emails.'))
-
- record = portal_user.wizard_id
- subject_data = {
- 'company': user.company_id.name,
+ _('You must have an email address in your User Preferences to send emails.'))
+
+ # determine subject and body in the portal user's language
+ portal_user = wizard_user.partner_id.user_ids[0]
+ main_context = context
+ context = dict(main_context or {}, lang=portal_user.lang)
+ data = {
+ 'company': user.company_id.name,
+ 'portal': wizard_user.wizard_id.portal_id.name,
+ 'message': wizard_user.wizard_id.message or "",
+ 'url': _("(missing url)"),
+ 'db': cr.dbname,
+ 'login': portal_user.login,
+ 'password': portal_user.password,
+ 'name': portal_user.name
}
- new_user = res_users.browse(cr, uid, new_user_id, context=context)
- ctx['lang'] = new_user.lang
- body_data = {
- 'portal': record.portal_id.name,
- 'message': record.message or "",
- 'url': record.portal_id.url or _("(missing url)"),
- 'db': cr.dbname,
- 'login': new_user.login,
- 'password': new_user.password,
- 'name': new_user.name
+ subject = _(WELCOME_EMAIL_SUBJECT) % data
+ body = _(WELCOME_EMAIL_BODY) % data
+
+ mail_mail = self.pool.get('mail.mail')
+ mail_values = {
+ 'email_from': user.email,
+ 'email_to': portal_user.email,
+ 'subject': subject,
+ 'body_html': '%s
' % body,
+ 'state': 'outgoing',
}
- body_data.update(subject_data)
- email_from = user.email
- email_to = portal_user.email
- subject = _(WELCOME_EMAIL_SUBJECT) % subject_data
- body = _(WELCOME_EMAIL_BODY) % body_data
- mail_id = mail_mail.create(cr, uid, {
- 'email_from': email_from ,
- 'email_to': email_to,
- 'subject': subject,
- 'state': 'outgoing',
- 'body_html': '%s
' % body}, context=ctx)
- return mail_id
-
- def create_new_user(self, cr, uid, portal_user, context=None):
- res_user = self.pool.get('res.users')
- portal = portal_user.wizard_id.portal_id
- partner = portal_user.partner_id
- action_id = portal.home_action_id and portal.home_action_id.id or False
- value = {
- 'name': portal_user.name,
- 'login': portal_user.email,
- 'password': random_password(),
- 'email': portal_user.email,
- 'lang': portal_user.lang,
- 'share': True,
- 'action_id': action_id,
- 'partner_id': partner.id,
- 'groups_id': [(6, 0, [])],
- }
- user_id = res_user.create(cr, ROOT_UID, value, context=context)
- portal_user.write({'user_id': user_id})
- self.send_email(cr, uid, portal_user, user_id, context=context)
- return user_id
-
- def link_portal_user(self, cr, uid, portal_id, user_id, context=None):
- res_groups = self.pool.get('res.groups')
- portal = res_groups.browse(cr, uid, portal_id, context=context)
- portal_user_ids = [u.id for u in portal.users]
- if user_id not in portal_user_ids:
- return portal.write({'users': [(4, user_id)]}, context=context)
- if user_id in portal_user_ids:
- return False
-
- def unlink_portal_user(self, cr, uid, portal_id, user_id, context=None):
- res_groups = self.pool.get('res.groups')
- return res_groups.write(cr, uid, [portal_id], {'users': [(3, user_id)]}, context=context)
-
- def unlink_user(self, cr, uid, user_id, context=None):
- #TODO: search portal groups
- res_user = self.pool.get('res.users')
- user = res_user.browse(cr, uid, user_id, context=context)
- if not user.groups_id:
- user.unlink(context=context)
- return True
-
-
- def manage_portal_access(self, cr, uid, ids, context=None):
- res_user = self.pool.get('res.users')
- for portal_user in self.browse(cr, uid, ids, context=context):
- portal = portal_user.wizard_id.portal_id
- user_id = portal_user.user_id and portal_user.user_id.id
- if not user_id:
- user_ids = res_user.search(cr, uid, [('login','=',portal_user.email)])
- user_id = user_ids and user_ids[0] or False
-
- if not user_id:
- user_id = self.create_new_user(cr, uid, portal_user, context=context)
- linked = self.link_portal_user(cr, uid, portal.id, user_id, context=context)
- #unlink existing user into portal
- if not linked and not portal_user.has_portal_user:
- self.unlink_portal_user(cr, uid, portal.id, user_id, context=context)
- #drop user if it does not has any access in any portal.
- self.unlink_user(cr, uid, user_id, context=context)
- return True
-wizard_user()
+ return mail_mail.create(cr, uid, mail_values, context=main_context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/portal/wizard/portal_wizard_view.xml b/addons/portal/wizard/portal_wizard_view.xml
index 7a81def67b0..e6d7901e2aa 100644
--- a/addons/portal/wizard/portal_wizard_view.xml
+++ b/addons/portal/wizard/portal_wizard_view.xml
@@ -5,7 +5,7 @@
@@ -13,18 +13,18 @@
Portal Access Management
- res.portal.wizard
+ portal.wizard
From 61ebb4042b5d7d0e98a1ac6be8cc63f917fd84de Mon Sep 17 00:00:00 2001
From: Christophe Matthieu
Date: Tue, 18 Sep 2012 17:11:08 +0200
Subject: [PATCH 51/73] [IMP] kanban: many2many_tags =>
bzr revid: chm@openerp.com-20120918151108-8fpv61vmlmbjkws7
---
addons/base_calendar/base_calendar_view.xml | 2 +-
addons/base_setup/res_partner_view.xml | 2 +-
addons/note/note_view.xml | 13 +++++++------
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/addons/base_calendar/base_calendar_view.xml b/addons/base_calendar/base_calendar_view.xml
index 89066ce74bb..0ea2be4f37f 100644
--- a/addons/base_calendar/base_calendar_view.xml
+++ b/addons/base_calendar/base_calendar_view.xml
@@ -418,7 +418,7 @@
ir.actions.act_window
calendar.event
form
- tree,form,calendar
+ calendar,tree,form
diff --git a/addons/base_setup/res_partner_view.xml b/addons/base_setup/res_partner_view.xml
index 5e54c0b8629..ad520799c1f 100644
--- a/addons/base_setup/res_partner_view.xml
+++ b/addons/base_setup/res_partner_view.xml
@@ -13,10 +13,10 @@
+
-
diff --git a/addons/note/note_view.xml b/addons/note/note_view.xml
index 5617fae4376..e7636aa4b85 100644
--- a/addons/note/note_view.xml
+++ b/addons/note/note_view.xml
@@ -2,8 +2,6 @@
-
-
note.stage.form
@@ -39,8 +37,6 @@
[('user_id','=',uid)]
-
-
note.note.kanban
@@ -85,7 +81,8 @@