This is an automated email from the ASF dual-hosted git repository.

ephraimanierobi pushed a commit to branch v2-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit a51b679c386b5c3f9b95230c7c15556f85cbbfc5
Author: Brent Bovenzi <[email protected]>
AuthorDate: Thu Apr 28 13:20:56 2022 -0400

    Don't show grid actions if server would reject with permission denied 
(#23332)
    
    * Add edit permission check for grid actions
    
    * Remove if wrapper for meta tag
    
    * Use dag.can_edit
    
    (cherry picked from commit 67e8bdd691ded0e88760b3d59b9c58ba43fa9453)
---
 airflow/www/static/js/tree/Table.jsx               | 33 +++++++++++++---------
 .../js/tree/details/content/ConfirmDialog.jsx      |  2 +-
 .../js/tree/details/content/dagRun/ClearRun.jsx    | 11 +++++++-
 .../tree/details/content/dagRun/MarkFailedRun.jsx  |  5 +++-
 .../tree/details/content/dagRun/MarkSuccessRun.jsx |  5 +++-
 .../js/tree/details/content/dagRun/QueueRun.jsx    |  4 +++
 .../content/taskInstance/MappedInstances.jsx       |  3 +-
 .../content/taskInstance/taskActions/Clear.jsx     |  6 +++-
 .../taskInstance/taskActions/MarkFailed.jsx        |  7 +++--
 .../taskInstance/taskActions/MarkSuccess.jsx       |  7 +++--
 .../content/taskInstance/taskActions/Run.jsx       |  7 +++--
 airflow/www/templates/airflow/dag.html             |  3 +-
 12 files changed, 66 insertions(+), 27 deletions(-)

diff --git a/airflow/www/static/js/tree/Table.jsx 
b/airflow/www/static/js/tree/Table.jsx
index e500b08966..6f8e351d86 100644
--- a/airflow/www/static/js/tree/Table.jsx
+++ b/airflow/www/static/js/tree/Table.jsx
@@ -72,6 +72,24 @@ const Table = ({
   const lowerCount = (offset || 0) + 1;
   const upperCount = lowerCount + data.length - 1;
 
+  // Don't show row selection if selectRows doesn't exist
+  const selectProps = selectRows
+    ? [useRowSelect,
+      (hooks) => {
+        hooks.visibleColumns.push((cols) => [
+          {
+            id: 'selection',
+            Cell: ({ row }) => (
+              <div>
+                <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
+              </div>
+            ),
+          },
+          ...cols,
+        ]);
+      }]
+    : [];
+
   const {
     getTableProps,
     getTableBodyProps,
@@ -98,20 +116,7 @@ const Table = ({
     },
     useSortBy,
     usePagination,
-    useRowSelect,
-    (hooks) => {
-      hooks.visibleColumns.push((cols) => [
-        {
-          id: 'selection',
-          Cell: ({ row }) => (
-            <div>
-              <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
-            </div>
-          ),
-        },
-        ...cols,
-      ]);
-    },
+    ...selectProps,
   );
 
   const handleNext = () => {
diff --git a/airflow/www/static/js/tree/details/content/ConfirmDialog.jsx 
b/airflow/www/static/js/tree/details/content/ConfirmDialog.jsx
index 25d37d1276..823fddc4eb 100644
--- a/airflow/www/static/js/tree/details/content/ConfirmDialog.jsx
+++ b/airflow/www/static/js/tree/details/content/ConfirmDialog.jsx
@@ -55,7 +55,7 @@ const ConfirmDialog = ({
 
           <AlertDialogBody>
             <Text mb={2}>{description}</Text>
-            {body.map((ti) => (<Code key={ti} fontSize="lg">{ti}</Code>))}
+            {Array.isArray(body) && body.map((ti) => (<Code key={ti} 
fontSize="lg">{ti}</Code>))}
           </AlertDialogBody>
 
           <AlertDialogFooter>
diff --git a/airflow/www/static/js/tree/details/content/dagRun/ClearRun.jsx 
b/airflow/www/static/js/tree/details/content/dagRun/ClearRun.jsx
index c423ba9fca..97c9438184 100644
--- a/airflow/www/static/js/tree/details/content/dagRun/ClearRun.jsx
+++ b/airflow/www/static/js/tree/details/content/dagRun/ClearRun.jsx
@@ -22,6 +22,9 @@ import { Button, useDisclosure } from '@chakra-ui/react';
 
 import { useClearRun } from '../../../api';
 import ConfirmDialog from '../ConfirmDialog';
+import { getMetaValue } from '../../../../utils';
+
+const canEdit = getMetaValue('can_edit') === 'True';
 
 const ClearRun = ({ dagId, runId }) => {
   const [affectedTasks, setAffectedTasks] = useState([]);
@@ -42,7 +45,13 @@ const ClearRun = ({ dagId, runId }) => {
 
   return (
     <>
-      <Button onClick={onClick} isLoading={isLoading}>Clear existing 
tasks</Button>
+      <Button
+        onClick={onClick}
+        isLoading={isLoading}
+        isDisabled={!canEdit}
+      >
+        Clear existing tasks
+      </Button>
       <ConfirmDialog
         isOpen={isOpen}
         onClose={onClose}
diff --git 
a/airflow/www/static/js/tree/details/content/dagRun/MarkFailedRun.jsx 
b/airflow/www/static/js/tree/details/content/dagRun/MarkFailedRun.jsx
index 1d3eb54cb5..3de973fd11 100644
--- a/airflow/www/static/js/tree/details/content/dagRun/MarkFailedRun.jsx
+++ b/airflow/www/static/js/tree/details/content/dagRun/MarkFailedRun.jsx
@@ -22,6 +22,9 @@ import { Button, useDisclosure } from '@chakra-ui/react';
 
 import { useMarkFailedRun } from '../../../api';
 import ConfirmDialog from '../ConfirmDialog';
+import { getMetaValue } from '../../../../utils';
+
+const canEdit = getMetaValue('can_edit') === 'True';
 
 const MarkFailedRun = ({ dagId, runId }) => {
   const [affectedTasks, setAffectedTasks] = useState([]);
@@ -42,7 +45,7 @@ const MarkFailedRun = ({ dagId, runId }) => {
 
   return (
     <>
-      <Button onClick={onClick} colorScheme="red" isLoading={isLoading}>Mark 
Failed</Button>
+      <Button onClick={onClick} colorScheme="red" isLoading={isLoading} 
isDisabled={!canEdit}>Mark Failed</Button>
       <ConfirmDialog
         isOpen={isOpen}
         onClose={onClose}
diff --git 
a/airflow/www/static/js/tree/details/content/dagRun/MarkSuccessRun.jsx 
b/airflow/www/static/js/tree/details/content/dagRun/MarkSuccessRun.jsx
index fbc49a3461..97ce9d439d 100644
--- a/airflow/www/static/js/tree/details/content/dagRun/MarkSuccessRun.jsx
+++ b/airflow/www/static/js/tree/details/content/dagRun/MarkSuccessRun.jsx
@@ -22,6 +22,9 @@ import { Button, useDisclosure } from '@chakra-ui/react';
 
 import { useMarkSuccessRun } from '../../../api';
 import ConfirmDialog from '../ConfirmDialog';
+import { getMetaValue } from '../../../../utils';
+
+const canEdit = getMetaValue('can_edit') === 'True';
 
 const MarkSuccessRun = ({ dagId, runId }) => {
   const [affectedTasks, setAffectedTasks] = useState([]);
@@ -42,7 +45,7 @@ const MarkSuccessRun = ({ dagId, runId }) => {
 
   return (
     <>
-      <Button onClick={onClick} colorScheme="green" isLoading={isLoading}>Mark 
Success</Button>
+      <Button onClick={onClick} colorScheme="green" isLoading={isLoading} 
isDisabled={!canEdit}>Mark Success</Button>
       <ConfirmDialog
         isOpen={isOpen}
         onClose={onClose}
diff --git a/airflow/www/static/js/tree/details/content/dagRun/QueueRun.jsx 
b/airflow/www/static/js/tree/details/content/dagRun/QueueRun.jsx
index 8eb6552fcf..b974988c33 100644
--- a/airflow/www/static/js/tree/details/content/dagRun/QueueRun.jsx
+++ b/airflow/www/static/js/tree/details/content/dagRun/QueueRun.jsx
@@ -22,6 +22,9 @@ import { Button, useDisclosure } from '@chakra-ui/react';
 
 import { useQueueRun } from '../../../api';
 import ConfirmDialog from '../ConfirmDialog';
+import { getMetaValue } from '../../../../utils';
+
+const canEdit = getMetaValue('can_edit') === 'True';
 
 const QueueRun = ({ dagId, runId }) => {
   const [affectedTasks, setAffectedTasks] = useState([]);
@@ -49,6 +52,7 @@ const QueueRun = ({ dagId, runId }) => {
         isLoading={isLoading}
         ml="5px"
         title="Queue up new tasks to make the DAG run up-to-date with any DAG 
file changes."
+        isDisabled={!canEdit}
       >
         Queue up new tasks
       </Button>
diff --git 
a/airflow/www/static/js/tree/details/content/taskInstance/MappedInstances.jsx 
b/airflow/www/static/js/tree/details/content/taskInstance/MappedInstances.jsx
index 336b9d1f19..d2f211cd62 100644
--- 
a/airflow/www/static/js/tree/details/content/taskInstance/MappedInstances.jsx
+++ 
b/airflow/www/static/js/tree/details/content/taskInstance/MappedInstances.jsx
@@ -37,6 +37,7 @@ import { SimpleStatus } from '../../../StatusBox';
 import Table from '../../../Table';
 import Time from '../../../Time';
 
+const canEdit = getMetaValue('can_edit') === 'True';
 const renderedTemplatesUrl = getMetaValue('rendered_templates_url');
 const logUrl = getMetaValue('log_url');
 const taskUrl = getMetaValue('task_url');
@@ -148,7 +149,7 @@ const MappedInstances = ({
         pageSize={limit}
         setSortBy={setSortBy}
         isLoading={isLoading}
-        selectRows={selectRows}
+        selectRows={canEdit && selectRows}
       />
     </Box>
   );
diff --git 
a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx 
b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx
index 098cfdb793..3bbfafdcec 100644
--- 
a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx
+++ 
b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx
@@ -28,6 +28,9 @@ import {
 import ActionButton from './ActionButton';
 import ConfirmDialog from '../../ConfirmDialog';
 import { useClearTask } from '../../../../api';
+import { getMetaValue } from '../../../../../utils';
+
+const canEdit = getMetaValue('can_edit') === 'True';
 
 const Run = ({
   dagId,
@@ -96,7 +99,7 @@ const Run = ({
 
   return (
     <Flex justifyContent="space-between" width="100%">
-      <ButtonGroup isAttached variant="outline">
+      <ButtonGroup isAttached variant="outline" isDisabled={!canEdit}>
         <ActionButton bg={past && 'gray.100'} onClick={onTogglePast} 
name="Past" />
         <ActionButton bg={future && 'gray.100'} onClick={onToggleFuture} 
name="Future" />
         <ActionButton bg={upstream && 'gray.100'} onClick={onToggleUpstream} 
name="Upstream" />
@@ -108,6 +111,7 @@ const Run = ({
         colorScheme="blue"
         onClick={onClick}
         isLoading={isLoading}
+        isDisabled={!canEdit}
         title="Clearing deletes the previous state of the task instance, 
allowing it to get re-triggered by the scheduler or a backfill command"
       >
         Clear
diff --git 
a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx
 
b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx
index ffbaf8e321..6dd0ac13e2 100644
--- 
a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx
+++ 
b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx
@@ -28,6 +28,9 @@ import {
 import ActionButton from './ActionButton';
 import { useConfirmMarkTask, useMarkFailedTask } from '../../../../api';
 import ConfirmDialog from '../../ConfirmDialog';
+import { getMetaValue } from '../../../../../utils';
+
+const canEdit = getMetaValue('can_edit') === 'True';
 
 const MarkFailed = ({
   dagId,
@@ -90,13 +93,13 @@ const MarkFailed = ({
 
   return (
     <Flex justifyContent="space-between" width="100%">
-      <ButtonGroup isAttached variant="outline">
+      <ButtonGroup isAttached variant="outline" isDisabled={!canEdit}>
         <ActionButton bg={past && 'gray.100'} onClick={onTogglePast} 
name="Past" />
         <ActionButton bg={future && 'gray.100'} onClick={onToggleFuture} 
name="Future" />
         <ActionButton bg={upstream && 'gray.100'} onClick={onToggleUpstream} 
name="Upstream" />
         <ActionButton bg={downstream && 'gray.100'} 
onClick={onToggleDownstream} name="Downstream" />
       </ButtonGroup>
-      <Button colorScheme="red" onClick={onClick} isLoading={isLoading}>
+      <Button colorScheme="red" onClick={onClick} isLoading={isLoading} 
isDisabled={!canEdit}>
         Mark Failed
       </Button>
       <ConfirmDialog
diff --git 
a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx
 
b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx
index 5f6950c629..56f2b9efe3 100644
--- 
a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx
+++ 
b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx
@@ -28,6 +28,9 @@ import {
 import ConfirmDialog from '../../ConfirmDialog';
 import ActionButton from './ActionButton';
 import { useMarkSuccessTask, useConfirmMarkTask } from '../../../../api';
+import { getMetaValue } from '../../../../../utils';
+
+const canEdit = getMetaValue('can_edit') === 'True';
 
 const MarkSuccess = ({
   dagId, runId, taskId, mapIndexes,
@@ -85,13 +88,13 @@ const MarkSuccess = ({
 
   return (
     <Flex justifyContent="space-between" width="100%">
-      <ButtonGroup isAttached variant="outline">
+      <ButtonGroup isAttached variant="outline" isDisabled={!canEdit}>
         <ActionButton bg={past && 'gray.100'} onClick={onTogglePast} 
name="Past" />
         <ActionButton bg={future && 'gray.100'} onClick={onToggleFuture} 
name="Future" />
         <ActionButton bg={upstream && 'gray.100'} onClick={onToggleUpstream} 
name="Upstream" />
         <ActionButton bg={downstream && 'gray.100'} 
onClick={onToggleDownstream} name="Downstream" />
       </ButtonGroup>
-      <Button colorScheme="green" onClick={onClick} isLoading={isLoading}>
+      <Button colorScheme="green" onClick={onClick} isLoading={isLoading} 
isDisabled={!canEdit}>
         Mark Success
       </Button>
       <ConfirmDialog
diff --git 
a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Run.jsx 
b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Run.jsx
index 85d502aeed..19559a8266 100644
--- 
a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Run.jsx
+++ 
b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Run.jsx
@@ -25,6 +25,9 @@ import {
 } from '@chakra-ui/react';
 
 import { useRunTask } from '../../../../api';
+import { getMetaValue } from '../../../../../utils';
+
+const canEdit = getMetaValue('can_edit') === 'True';
 
 const Run = ({
   dagId,
@@ -54,7 +57,7 @@ const Run = ({
 
   return (
     <Flex justifyContent="space-between" width="100%">
-      <ButtonGroup isAttached variant="outline">
+      <ButtonGroup isAttached variant="outline" isDisabled={!canEdit}>
         <Button
           bg={ignoreAllDeps && 'gray.100'}
           onClick={onToggleAllDeps}
@@ -77,7 +80,7 @@ const Run = ({
           Ignore Task Deps
         </Button>
       </ButtonGroup>
-      <Button colorScheme="blue" onClick={onClick} isLoading={isLoading}>
+      <Button colorScheme="blue" onClick={onClick} isLoading={isLoading} 
isDisabled={!canEdit}>
         Run
       </Button>
     </Flex>
diff --git a/airflow/www/templates/airflow/dag.html 
b/airflow/www/templates/airflow/dag.html
index e7afde8af9..70adcf81d1 100644
--- a/airflow/www/templates/airflow/dag.html
+++ b/airflow/www/templates/airflow/dag.html
@@ -82,7 +82,8 @@
   {% endif %}
   {% if external_log_name is defined %}
   <meta name="external_log_name" content="{{ external_log_name }}">
-{% endif %}
+  {% endif %}
+  <meta name="can_edit" content="{{ dag.can_edit }}">
 {% endblock %}
 
 {% block content %}

Reply via email to