# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from __future__ import annotations
import textwrap
from airflow.cli.cli_config import (
ARG_DB_FROM_REVISION,
ARG_DB_FROM_VERSION,
ARG_DB_REVISION__DOWNGRADE,
ARG_DB_REVISION__UPGRADE,
ARG_DB_SKIP_INIT,
ARG_DB_SQL_ONLY,
ARG_DB_VERSION__DOWNGRADE,
ARG_DB_VERSION__UPGRADE,
ARG_OUTPUT,
ARG_VERBOSE,
ARG_YES,
ActionCommand,
Arg,
lazy_load_command,
)
############
# # ARGS # #
############
# users
[docs]ARG_USERNAME = Arg(("-u", "--username"), help="Username of the user", required=True, type=str)
[docs]ARG_USERNAME_OPTIONAL = Arg(("-u", "--username"), help="Username of the user", type=str)
[docs]ARG_FIRSTNAME = Arg(("-f", "--firstname"), help="First name of the user", required=True, type=str)
[docs]ARG_LASTNAME = Arg(("-l", "--lastname"), help="Last name of the user", required=True, type=str)
[docs]ARG_ROLE = Arg(
("-r", "--role"),
help="Role of the user. Existing roles include Admin, User, Op, Viewer, and Public",
required=True,
type=str,
)
[docs]ARG_EMAIL = Arg(("-e", "--email"), help="Email of the user", required=True, type=str)
[docs]ARG_EMAIL_OPTIONAL = Arg(("-e", "--email"), help="Email of the user", type=str)
[docs]ARG_PASSWORD = Arg(
("-p", "--password"),
help="Password of the user, required to create a user without --use-random-password",
type=str,
)
[docs]ARG_USE_RANDOM_PASSWORD = Arg(
("--use-random-password",),
help="Do not prompt for password. Use random string instead."
" Required to create a user without --password ",
default=False,
action="store_true",
)
[docs]ARG_USER_IMPORT = Arg(
("import",),
metavar="FILEPATH",
help="Import users from JSON file. Example format::\n"
+ textwrap.indent(
textwrap.dedent(
"""
[
{
"email": "foo@bar.org",
"firstname": "Jon",
"lastname": "Doe",
"roles": ["Public"],
"username": "jondoe"
}
]"""
),
" " * 4,
),
)
[docs]ARG_USER_EXPORT = Arg(("export",), metavar="FILEPATH", help="Export all users to JSON file")
# roles
[docs]ARG_CREATE_ROLE = Arg(("-c", "--create"), help="Create a new role", action="store_true")
[docs]ARG_LIST_ROLES = Arg(("-l", "--list"), help="List roles", action="store_true")
[docs]ARG_ROLES = Arg(("role",), help="The name of a role", nargs="*")
[docs]ARG_PERMISSIONS = Arg(("-p", "--permission"), help="Show role permissions", action="store_true")
[docs]ARG_ROLE_RESOURCE = Arg(("-r", "--resource"), help="The name of permissions", nargs="*", required=True)
[docs]ARG_ROLE_ACTION = Arg(("-a", "--action"), help="The action of permissions", nargs="*")
[docs]ARG_ROLE_ACTION_REQUIRED = Arg(("-a", "--action"), help="The action of permissions", nargs="*", required=True)
[docs]ARG_ROLE_IMPORT = Arg(("file",), help="Import roles from JSON file", nargs=None)
[docs]ARG_ROLE_EXPORT = Arg(("file",), help="Export all roles to JSON file", nargs=None)
[docs]ARG_ROLE_EXPORT_FMT = Arg(
("-p", "--pretty"),
help="Format output JSON file by sorting role names and indenting by 4 spaces",
action="store_true",
)
# sync-perm
[docs]ARG_INCLUDE_DAGS = Arg(
("--include-dags",), help="If passed, DAG specific permissions will also be synced.", action="store_true"
)
################
# # COMMANDS # #
################
[docs]USERS_COMMANDS = (
ActionCommand(
name="list",
help="List users",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.users_list"),
args=(ARG_OUTPUT, ARG_VERBOSE),
),
ActionCommand(
name="create",
help="Create a user",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.users_create"),
args=(
ARG_ROLE,
ARG_USERNAME,
ARG_EMAIL,
ARG_FIRSTNAME,
ARG_LASTNAME,
ARG_PASSWORD,
ARG_USE_RANDOM_PASSWORD,
ARG_VERBOSE,
),
epilog=(
"examples:\n"
'To create an user with "Admin" role and username equals to "admin", run:\n'
"\n"
" $ airflow users create \\\n"
" --username admin \\\n"
" --firstname FIRST_NAME \\\n"
" --lastname LAST_NAME \\\n"
" --role Admin \\\n"
" --email admin@example.org"
),
),
ActionCommand(
name="reset-password",
help="Reset a user's password",
func=lazy_load_command(
"airflow.providers.fab.auth_manager.cli_commands.user_command.user_reset_password"
),
args=(
ARG_USERNAME_OPTIONAL,
ARG_EMAIL_OPTIONAL,
ARG_PASSWORD,
ARG_USE_RANDOM_PASSWORD,
ARG_VERBOSE,
),
epilog=(
"examples:\n"
'To reset an user with username equals to "admin", run:\n'
"\n"
" $ airflow users reset-password \\\n"
" --username admin"
),
),
ActionCommand(
name="delete",
help="Delete a user",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.users_delete"),
args=(ARG_USERNAME_OPTIONAL, ARG_EMAIL_OPTIONAL, ARG_VERBOSE),
),
ActionCommand(
name="add-role",
help="Add role to a user",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.add_role"),
args=(ARG_USERNAME_OPTIONAL, ARG_EMAIL_OPTIONAL, ARG_ROLE, ARG_VERBOSE),
),
ActionCommand(
name="remove-role",
help="Remove role from a user",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.remove_role"),
args=(ARG_USERNAME_OPTIONAL, ARG_EMAIL_OPTIONAL, ARG_ROLE, ARG_VERBOSE),
),
ActionCommand(
name="import",
help="Import users",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.users_import"),
args=(ARG_USER_IMPORT, ARG_VERBOSE),
),
ActionCommand(
name="export",
help="Export all users",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.user_command.users_export"),
args=(ARG_USER_EXPORT, ARG_VERBOSE),
),
)
[docs]ROLES_COMMANDS = (
ActionCommand(
name="list",
help="List roles",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.role_command.roles_list"),
args=(ARG_PERMISSIONS, ARG_OUTPUT, ARG_VERBOSE),
),
ActionCommand(
name="create",
help="Create role",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.role_command.roles_create"),
args=(ARG_ROLES, ARG_VERBOSE),
),
ActionCommand(
name="delete",
help="Delete role",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.role_command.roles_delete"),
args=(ARG_ROLES, ARG_VERBOSE),
),
ActionCommand(
name="add-perms",
help="Add roles permissions",
func=lazy_load_command(
"airflow.providers.fab.auth_manager.cli_commands.role_command.roles_add_perms"
),
args=(ARG_ROLES, ARG_ROLE_RESOURCE, ARG_ROLE_ACTION_REQUIRED, ARG_VERBOSE),
),
ActionCommand(
name="del-perms",
help="Delete roles permissions",
func=lazy_load_command(
"airflow.providers.fab.auth_manager.cli_commands.role_command.roles_del_perms"
),
args=(ARG_ROLES, ARG_ROLE_RESOURCE, ARG_ROLE_ACTION, ARG_VERBOSE),
),
ActionCommand(
name="export",
help="Export roles (without permissions) from db to JSON file",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.role_command.roles_export"),
args=(ARG_ROLE_EXPORT, ARG_ROLE_EXPORT_FMT, ARG_VERBOSE),
),
ActionCommand(
name="import",
help="Import roles (without permissions) from JSON file to db",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.role_command.roles_import"),
args=(ARG_ROLE_IMPORT, ARG_VERBOSE),
),
)
[docs]SYNC_PERM_COMMAND = ActionCommand(
name="sync-perm",
help="Update permissions for existing roles and optionally DAGs",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.sync_perm_command.sync_perm"),
args=(ARG_INCLUDE_DAGS, ARG_VERBOSE),
)
[docs]DB_COMMANDS = (
ActionCommand(
name="migrate",
help="Migrates the FAB metadata database to the latest version",
description=(
"Migrate the schema of the FAB metadata database. "
"Create the database if it does not exist "
"To print but not execute commands, use option ``--show-sql-only``. "
"If using options ``--from-revision`` or ``--from-version``, you must also use "
"``--show-sql-only``, because if actually *running* migrations, we should only "
"migrate from the *current* Alembic revision."
),
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.db_command.migratedb"),
args=(
ARG_DB_REVISION__UPGRADE,
ARG_DB_VERSION__UPGRADE,
ARG_DB_SQL_ONLY,
ARG_DB_FROM_REVISION,
ARG_DB_FROM_VERSION,
ARG_VERBOSE,
),
),
ActionCommand(
name="downgrade",
help="Downgrade the schema of the FAB metadata database.",
description=(
"Downgrade the schema of the FAB metadata database. "
"You must provide either `--to-revision` or `--to-version`. "
"To print but not execute commands, use option `--show-sql-only`. "
"If using options `--from-revision` or `--from-version`, you must also use `--show-sql-only`, "
"because if actually *running* migrations, we should only migrate from the *current* Alembic "
"revision."
),
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.db_command.downgrade"),
args=(
ARG_DB_REVISION__DOWNGRADE,
ARG_DB_VERSION__DOWNGRADE,
ARG_DB_SQL_ONLY,
ARG_YES,
ARG_DB_FROM_REVISION,
ARG_DB_FROM_VERSION,
ARG_VERBOSE,
),
),
ActionCommand(
name="reset",
help="Burn down and rebuild the FAB metadata database",
func=lazy_load_command("airflow.providers.fab.auth_manager.cli_commands.db_command.resetdb"),
args=(ARG_YES, ARG_DB_SKIP_INIT, ARG_VERBOSE),
),
)