Allow trytond-admin to manage any user

Closes #13630
This commit is contained in:
Adrià Tarroja Caubet
2026-09-22 18:32:04 +02:00
parent b82603d258
commit bada63ef4b
3 changed files with 46 additions and 33 deletions
+1
View File
@@ -1,3 +1,4 @@
* Allow trytond-admin to manage any user
* Add bulk_create, bulk_delete, bulk_save and bulk_func to ModelStorage
* Add editable state on field
* Enforce readonly on field when checking access
+31 -27
View File
@@ -13,7 +13,7 @@ from trytond.pool import Pool
from trytond.sendmail import send_test_email
from trytond.tools import file_open, find_path
from trytond.tools.email_ import EmailNotValidError, validate_email
from trytond.transaction import Transaction, TransactionError
from trytond.transaction import Transaction, TransactionError, inactive_records
__all__ = ['run']
logger = logging.getLogger(__name__)
@@ -76,14 +76,14 @@ def run(options):
})
for db_name in options.database_names:
if options.admin_login:
admin_login = options.admin_login
login = options.login
administrator = options.administrator or init[db_name]
if options.email is not None:
email = options.email
elif init[db_name]:
while True:
email = input(
f'email for "{admin_login}" of "{db_name}"'
f'email for "{login}" of "{db_name}"'
' (empty for none): ')
if email:
try:
@@ -111,17 +111,17 @@ def run(options):
if not password and not options.reset_password:
while True:
password = getpass(
f'password for "{admin_login}" of "{db_name}": ')
f'password for "{login}" of "{db_name}": ')
password2 = getpass(
f'password confirmation for "{admin_login}": ')
f'password confirmation for "{login}": ')
if password != password2:
sys.stderr.write(
f'password confirmation for "{admin_login}" '
f'doesn\'t match "{admin_login}" password.\n')
f'password confirmation for "{login}" '
f'doesn\'t match "{login}" password.\n')
continue
if not password:
sys.stderr.write(
f'password for "{admin_login}" is required.\n')
f'password for "{login}" is required.\n')
continue
break
@@ -139,28 +139,32 @@ def run(options):
configuration.language = main_lang
if (init[db_name]
or options.administrator is not None
or options.email is not None
or options.password
or options.reset_password):
try:
admin, = User.search([
('id', '!=', 0),
('login', '=', admin_login),
('administrator', '=', True),
])
except ValueError:
admin = User()
admin.login = admin_login
admin.administrator = True
else:
if not admin.administrator:
admin.administrator = True
with inactive_records():
try:
user, = User.search([
('id', '!=', 0),
('login', '=', login),
])
except ValueError:
user = User(
login=login,
administrator=administrator,
active=True)
if user.active != options.active:
user.active = options.active
if user.administrator != administrator:
user.administrator = administrator
if email is not None:
admin.email = email
if not options.reset_password:
admin.password = password
admin.save()
user.email = email
if password:
user.password = password
user.save()
if options.reset_password:
User.reset_password([admin])
User.reset_password([user])
if options.hostname is not None:
configuration.hostname = options.hostname or None
if options.export_translations:
+14 -6
View File
@@ -151,14 +151,22 @@ def get_parser_admin():
action="store_true",
help="activate missing dependencies of updated modules")
parser.add_argument(
"--admin-login", dest="admin_login", default="admin",
help="login of an administrator user (default: admin)")
"--login", default="admin",
help="login of the user (default: admin)")
parser.add_argument(
"--administrator",
action=getattr(argparse, 'BooleanOptionalAction', 'store_true'),
help="set the user as administrator")
parser.add_argument(
"--active", default=True,
action=getattr(argparse, 'BooleanOptionalAction', 'store_true'),
help="activate the user")
parser.add_argument("--email", dest="email", type=validate_email,
help="set the admin email")
help="set the user email")
parser.add_argument("-p", "--password", dest="password",
action='store_true', help="set the administrator password")
action='store_true', help="set the user password")
parser.add_argument("--reset-password", dest='reset_password',
action='store_true', help="reset the administrator password")
action='store_true', help="reset the user password")
parser.add_argument("--test-email", dest='test_email', type=validate_email,
help="send a test email to the specified address")
parser.add_argument("-m", "--update-modules-list", action="store_true",
@@ -179,7 +187,7 @@ def get_parser_admin():
help="export module translations to locale folder")
parser.epilog = ('The first time a database is initialized '
'or when the password is set, the administrator password is read '
'or when the password is set, the user password is read '
'from file defined by TRYTONPASSFILE environment variable '
'or interactively asked from the user.\n'
'The config file can be specified in the TRYTOND_CONFIG '