Move user details view to fab auth manager (#32756)
diff --git a/airflow/auth/managers/base_auth_manager.py b/airflow/auth/managers/base_auth_manager.py
index 6f148cd..6456160 100644
--- a/airflow/auth/managers/base_auth_manager.py
+++ b/airflow/auth/managers/base_auth_manager.py
@@ -52,6 +52,11 @@
"""Return the login page url."""
...
+ @abstractmethod
+ def get_url_user_profile(self) -> str:
+ """Return the url to a page displaying info about the current user."""
+ ...
+
def get_security_manager_override_class(self) -> type:
"""
Return the security manager override class.
diff --git a/airflow/auth/managers/fab/fab_auth_manager.py b/airflow/auth/managers/fab/fab_auth_manager.py
index 6dee27c..c009ff6 100644
--- a/airflow/auth/managers/fab/fab_auth_manager.py
+++ b/airflow/auth/managers/fab/fab_auth_manager.py
@@ -59,3 +59,9 @@
return url_for(f"{self.security_manager.auth_view.endpoint}.login", next=kwargs["next_url"])
else:
return url_for(f"{self.security_manager.auth_view.endpoint}.login")
+
+ def get_url_user_profile(self) -> str:
+ """Return the url to a page displaying info about the current user."""
+ if not self.security_manager.user_view:
+ raise AirflowException("`user_view` not defined in the security manager.")
+ return url_for(f"{self.security_manager.user_view.endpoint}.userinfo")
diff --git a/airflow/auth/managers/fab/views/__init__.py b/airflow/auth/managers/fab/views/__init__.py
new file mode 100644
index 0000000..13a8339
--- /dev/null
+++ b/airflow/auth/managers/fab/views/__init__.py
@@ -0,0 +1,16 @@
+# 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.
diff --git a/airflow/auth/managers/fab/views/user_details.py b/airflow/auth/managers/fab/views/user_details.py
new file mode 100644
index 0000000..d8aed53
--- /dev/null
+++ b/airflow/auth/managers/fab/views/user_details.py
@@ -0,0 +1,55 @@
+# 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
+
+from flask_appbuilder.security.views import UserDBModelView
+
+from airflow.security import permissions
+from airflow.www.fab_security.views import MultiResourceUserMixin
+
+
+class CustomUserDBModelView(MultiResourceUserMixin, UserDBModelView):
+ """Customize permission names for FAB's builtin UserDBModelView."""
+
+ _class_permission_name = permissions.RESOURCE_USER
+
+ class_permission_name_mapping = {
+ "resetmypassword": permissions.RESOURCE_MY_PASSWORD,
+ "resetpasswords": permissions.RESOURCE_PASSWORD,
+ "userinfoedit": permissions.RESOURCE_MY_PROFILE,
+ "userinfo": permissions.RESOURCE_MY_PROFILE,
+ }
+
+ method_permission_name = {
+ "add": "create",
+ "download": "read",
+ "show": "read",
+ "list": "read",
+ "edit": "edit",
+ "delete": "delete",
+ "resetmypassword": "read",
+ "resetpasswords": "read",
+ "userinfo": "read",
+ "userinfoedit": "read",
+ }
+
+ base_permissions = [
+ permissions.ACTION_CAN_CREATE,
+ permissions.ACTION_CAN_READ,
+ permissions.ACTION_CAN_EDIT,
+ permissions.ACTION_CAN_DELETE,
+ ]
diff --git a/airflow/www/extensions/init_appbuilder.py b/airflow/www/extensions/init_appbuilder.py
index 5a492f9..2537ea8 100644
--- a/airflow/www/extensions/init_appbuilder.py
+++ b/airflow/www/extensions/init_appbuilder.py
@@ -596,10 +596,6 @@
def get_url_for_index(self):
return url_for(f"{self.indexview.endpoint}.{self.indexview.default_view}")
- @property
- def get_url_for_userinfo(self):
- return url_for(f"{self.sm.user_view.endpoint}.userinfo")
-
def get_url_for_locale(self, lang):
return url_for(
f"{self.bm.locale_view.endpoint}.{self.bm.locale_view.default_view}",
diff --git a/airflow/www/fab_security/views.py b/airflow/www/fab_security/views.py
index 24e09e7..8e1dd62 100644
--- a/airflow/www/fab_security/views.py
+++ b/airflow/www/fab_security/views.py
@@ -26,7 +26,6 @@
ResetMyPasswordView,
ResetPasswordView,
RoleModelView,
- UserDBModelView,
UserInfoEditView,
UserLDAPModelView,
UserOAuthModelView,
@@ -229,39 +228,6 @@
)
-class CustomUserDBModelView(MultiResourceUserMixin, UserDBModelView):
- """Customize permission names for FAB's builtin UserDBModelView."""
-
- _class_permission_name = permissions.RESOURCE_USER
-
- class_permission_name_mapping = {
- "resetmypassword": permissions.RESOURCE_MY_PASSWORD,
- "resetpasswords": permissions.RESOURCE_PASSWORD,
- "userinfoedit": permissions.RESOURCE_MY_PROFILE,
- "userinfo": permissions.RESOURCE_MY_PROFILE,
- }
-
- method_permission_name = {
- "add": "create",
- "download": "read",
- "show": "read",
- "list": "read",
- "edit": "edit",
- "delete": "delete",
- "resetmypassword": "read",
- "resetpasswords": "read",
- "userinfo": "read",
- "userinfoedit": "read",
- }
-
- base_permissions = [
- permissions.ACTION_CAN_CREATE,
- permissions.ACTION_CAN_READ,
- permissions.ACTION_CAN_EDIT,
- permissions.ACTION_CAN_DELETE,
- ]
-
-
class CustomUserLDAPModelView(MultiResourceUserMixin, UserLDAPModelView):
"""Customize permission names for FAB's builtin UserLDAPModelView."""
diff --git a/airflow/www/security.py b/airflow/www/security.py
index 101b55d..7f534e7 100644
--- a/airflow/www/security.py
+++ b/airflow/www/security.py
@@ -24,6 +24,7 @@
from sqlalchemy import or_
from sqlalchemy.orm import Session, joinedload
+from airflow.auth.managers.fab.views.user_details import CustomUserDBModelView
from airflow.exceptions import AirflowException, RemovedInAirflow3Warning
from airflow.models import DagBag, DagModel
from airflow.security import permissions
@@ -37,7 +38,6 @@
CustomResetMyPasswordView,
CustomResetPasswordView,
CustomRoleModelView,
- CustomUserDBModelView,
CustomUserInfoEditView,
CustomUserLDAPModelView,
CustomUserOAuthModelView,
diff --git a/airflow/www/templates/appbuilder/navbar_right.html b/airflow/www/templates/appbuilder/navbar_right.html
index e26b6fa..7252b96 100644
--- a/airflow/www/templates/appbuilder/navbar_right.html
+++ b/airflow/www/templates/appbuilder/navbar_right.html
@@ -73,7 +73,7 @@
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
- <li><a href="{{appbuilder.get_url_for_userinfo}}"><span class="material-icons">account_circle</span>{{_("Your Profile")}}</a></li>
+ <li><a href="{{auth_manager.get_url_user_profile()}}"><span class="material-icons">account_circle</span>{{_("Your Profile")}}</a></li>
<li role="separator" class="divider"></li>
<li><a href="{{appbuilder.get_url_for_logout}}"><span class="material-icons">exit_to_app</span>{{_("Log Out")}}</a></li>
</ul>