details: https://code.tryton.org/tryton/commit/fed8901dbb27
branch: default
user: Adrià Tarroja Caubet <[email protected]>
date: Tue Sep 22 18:32:04 2026 +0200
description:
Allow trytond-admin to manage any user
Closes #13630
diffstat:
trytond/CHANGELOG | 1 +
trytond/trytond/admin.py | 58 ++++++++++++++++++++++-------------------
trytond/trytond/commandline.py | 20 ++++++++++----
3 files changed, 46 insertions(+), 33 deletions(-)
diffs (152 lines):
diff -r 16aae4ad4d69 -r fed8901dbb27 trytond/CHANGELOG
--- a/trytond/CHANGELOG Tue Sep 22 17:49:00 2026 +0200
+++ b/trytond/CHANGELOG Tue Sep 22 18:32:04 2026 +0200
@@ -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
diff -r 16aae4ad4d69 -r fed8901dbb27 trytond/trytond/admin.py
--- a/trytond/trytond/admin.py Tue Sep 22 17:49:00 2026 +0200
+++ b/trytond/trytond/admin.py Tue Sep 22 18:32:04 2026 +0200
@@ -13,7 +13,7 @@
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 @@
})
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 @@
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 @@
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:
diff -r 16aae4ad4d69 -r fed8901dbb27 trytond/trytond/commandline.py
--- a/trytond/trytond/commandline.py Tue Sep 22 17:49:00 2026 +0200
+++ b/trytond/trytond/commandline.py Tue Sep 22 18:32:04 2026 +0200
@@ -151,14 +151,22 @@
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 @@
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 '