Files
enterprise-addons/databases/wizard/databases_manage_users_wizard.py

190 lines
7.9 KiB
Python

import logging
from odoo import api, fields, models
from odoo.addons.databases.models.project_project import get_database_api_keys
from ..api import ApiError, OdooDatabaseApi
_logger = logging.getLogger(__name__)
class DatabasesInviteUsersWizard(models.TransientModel):
_name = 'databases.manage_users.wizard'
_description = 'Database Users Invitation Wizard'
database_ids = fields.Many2many(
comodel_name='project.project',
domain=[('database_hosting', 'not in', (False, 'other'))],
default=lambda self: self.env.context.get('active_ids')
)
mode = fields.Selection([
('invite', 'Invitation'),
('remove', 'Removal'),
], required=True)
state = fields.Selection([
('draft', 'Draft'),
('done', 'Done'),
], required=True, default='draft')
error_message = fields.Char(default='')
user_ids = fields.Many2many('res.users', domain=[('share', '=', False)])
summary_message = fields.Char(compute='_compute_summary_message')
everywhere_user_ids = fields.Many2many('res.users', compute='_compute_everywhere_user_ids')
removable_user_ids = fields.Many2many('res.users', compute='_compute_removable_user_ids')
@api.depends('database_ids')
def _compute_summary_message(self):
for record in self:
if record.state == 'draft':
if record.mode == 'invite':
if len(record.database_ids) == 1:
record.summary_message = self.env._(
"Select the users you want to invite to the database %(database_name)s.",
database_name=record.database_ids.name
)
else:
record.summary_message = self.env._(
"Select the users you want to invite to the %(nb_databases)s selected databases.",
nb_databases=len(record.database_ids)
)
else:
if len(record.database_ids) == 1:
record.summary_message = self.env._(
"Select the users you want to remove from the database %(database_name)s.",
database_name=record.database_ids.name
)
else:
record.summary_message = self.env._(
"Select the users you want to remove from the %(nb_databases)s selected databases.",
nb_databases=len(record.database_ids)
)
elif record.state == 'done':
if record.error_message:
record.summary_message = self.env._("An error occurred: %s", record.error_message)
elif record.mode == 'invite':
record.summary_message = self.env._(
"These users were successfully invited to %(nb_databases)s databases.",
nb_databases=len(record.database_ids)
)
else:
record.summary_message = self.env._(
"These users were successfully removed from %(nb_databases)s databases.",
nb_databases=len(record.database_ids)
)
@api.depends('database_ids.database_user_ids.local_user_id')
def _compute_everywhere_user_ids(self):
for rec in self:
if not rec.database_ids:
rec.everywhere_user_ids = None
continue
# Compute the intersection of local_user_ids in each database
dbit = iter(rec.database_ids)
everywhere_user_ids = next(dbit).database_user_ids.local_user_id
for db in dbit:
everywhere_user_ids &= db.database_user_ids.local_user_id
rec.everywhere_user_ids = everywhere_user_ids
@api.depends('database_ids.database_user_ids.local_user_id')
def _compute_removable_user_ids(self):
for rec in self:
rec.removable_user_ids = rec.database_ids.database_user_ids.local_user_id
def _open(self):
if self.mode == 'invite':
name = self.env._("Invitation is done")
elif self.mode == 'remove':
name = self.env._("User removal is done")
return {
'type': 'ir.actions.act_window',
'name': name,
'res_model': self._name,
'res_id': self.id,
'view_mode': 'form',
'target': 'new',
'views': [[False, 'form']],
}
def action_invite_users(self):
existing_users = {
(du.login, du.project_id.id)
for du in self.env['databases.user'].search([
('login', 'in', self.user_ids.mapped('login')),
('project_id', 'in', self.database_ids.ids),
])
}
new_users = self.env['databases.user'].create([
{
'project_id': db.id,
'login': user.login,
'name': user.name,
}
for db in self.database_ids
for user in self.user_ids
if (user.login, db.id) not in existing_users
])
database_api_keys = get_database_api_keys(new_users.project_id)
for db, db_users in new_users.grouped('project_id').items():
database_api_key = database_api_keys.get(db.id, '')
args = [db.database_url, db.database_name, db.database_api_login, database_api_key]
if not all(args):
self.error_message += self.env._(
"Error while connecting to %(url)s: We are missing the database name, the api login or the api key\n",
url=db.database_url,
)
db_users.unlink()
continue
db_api = OdooDatabaseApi(*args)
try:
db_api.invite_users(db_users.mapped('login'))
except ApiError as e:
_logger.warning('ApiError: Error while creating user on %s: %s', db.database_name, e.args[0])
self.error_message += self.env._(
"Error while creating users on %(dbname)s: %(message)s\n",
dbname=db.database_name,
message=e.args[0],
)
db_users.unlink()
continue
self.state = 'done'
return self._open()
def action_remove_users(self):
users_to_delete = self.env['databases.user'].search([
('login', 'in', self.user_ids.mapped('login')),
('project_id', 'in', self.database_ids.ids),
])
database_api_keys = get_database_api_keys(users_to_delete.project_id)
for db, db_users in users_to_delete.grouped('project_id').items():
database_api_key = database_api_keys.get(db.id, '')
args = [db.database_url, db.database_name, db.database_api_login, database_api_key]
if not all(args):
self.error_message += self.env._(
"Error while connecting to %(url)s: We are missing the database name, the api login or the api key\n",
url=db.database_url,
)
users_to_delete -= db_users
continue
db_api = OdooDatabaseApi(*args)
try:
db_api.remove_users(db_users.mapped('login'))
except ApiError as e:
_logger.warning('ApiError: Error while removing users from %s: %s', db.database_name, e.args[0])
self.error_message += self.env._(
"Error while removing users from %(dbname)s: %(message)s\n",
dbname=db.database_name,
message=e.args[0],
)
users_to_delete -= db_users
continue
users_to_delete.unlink()
self.state = 'done'
return self._open()