diff --git a/trytond/CHANGELOG b/trytond/CHANGELOG index a1f7091065..8b97fba934 100644 --- a/trytond/CHANGELOG +++ b/trytond/CHANGELOG @@ -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 --git a/trytond/trytond/admin.py b/trytond/trytond/admin.py index aae0f0b4c4..160c4a1de0 100644 --- a/trytond/trytond/admin.py +++ b/trytond/trytond/admin.py @@ -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: diff --git a/trytond/trytond/commandline.py b/trytond/trytond/commandline.py index 3ef76b0401..e9f61f17be 100644 --- a/trytond/trytond/commandline.py +++ b/trytond/trytond/commandline.py @@ -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 '