github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/webui/src/pages/auth/policies/index.jsx (about) 1 import React, {useEffect, useState} from "react"; 2 import { useOutletContext } from "react-router-dom"; 3 import Button from "react-bootstrap/Button"; 4 5 import {auth} from "../../../lib/api"; 6 import {useAPIWithPagination} from "../../../lib/hooks/api"; 7 import {ConfirmationButton} from "../../../lib/components/modals"; 8 import {Paginator} from "../../../lib/components/pagination"; 9 import {PolicyEditor} from "../../../lib/components/policy"; 10 import { 11 ActionGroup, 12 ActionsBar, 13 Checkbox, 14 DataTable, 15 AlertError, 16 FormattedDate, 17 Loading, 18 RefreshButton, 19 Warning, 20 } from "../../../lib/components/controls"; 21 import {useRouter} from "../../../lib/hooks/router"; 22 import {useLoginConfigContext} from "../../../lib/hooks/conf"; 23 import {Link} from "../../../lib/components/nav"; 24 import { disallowPercentSign, INVALID_POLICY_ID_ERROR_MESSAGE } from "../validation"; 25 26 27 const PoliciesContainer = () => { 28 const [selected, setSelected] = useState([]); 29 const [deleteError, setDeleteError] = useState(null); 30 const [showCreate, setShowCreate] = useState(false); 31 const [refresh, setRefresh] = useState(false); 32 const [createModalError, setCreateModalError] = useState(null); 33 34 const router = useRouter(); 35 const after = (router.query.after) ? router.query.after : ""; 36 const { results, loading, error, nextPage } = useAPIWithPagination(() => { 37 return auth.listPolicies("", after); 38 }, [after, refresh]); 39 40 useEffect(() => { setSelected([]); }, [after, refresh]); 41 42 const {RBAC: rbac} = useLoginConfigContext(); 43 44 if (error) return <AlertError error={error}/>; 45 if (loading) return <Loading/>; 46 47 return ( 48 <> 49 <ActionsBar> 50 <ActionGroup orientation="left"> 51 <Button 52 variant="success" 53 onClick={() => setShowCreate(true)}> 54 Create Policy 55 </Button> 56 57 <ConfirmationButton 58 onConfirm={() => { 59 auth.deletePolicies(selected.map(p => p.id)) 60 .catch(err => setDeleteError(err)) 61 .then(() => { 62 setSelected([]); 63 setRefresh(!refresh); 64 }); 65 }} 66 disabled={(selected.length === 0)} 67 variant="danger" 68 msg={`Are you sure you'd like to delete ${selected.length} policies?`}> 69 Delete Selected 70 </ConfirmationButton> 71 </ActionGroup> 72 <ActionGroup orientation="right"> 73 <RefreshButton onClick={() => setRefresh(!refresh)}/> 74 </ActionGroup> 75 </ActionsBar> 76 {rbac === 'simplified' && <Warning> 77 <b>Deprecation Notice:</b> RBAC (Role-Based Access Control) is being deprecated 78 and will be replaced by ACL (Access Control Lists) in future releases. 79 For more information on the transition from RBAC to ACL, please visit 80 our <a href="https://docs.lakefs.io/posts/security_update.html">documentation page</a>. 81 </Warning>} 82 <div className="auth-learn-more"> 83 A policy defines the permissions of a user or a group. <a href="https://docs.lakefs.io/reference/authorization.html#authorization" target="_blank" rel="noopener noreferrer">Learn more.</a> 84 </div> 85 86 {(!!deleteError) && <AlertError error={deleteError}/>} 87 88 <PolicyEditor 89 onSubmit={(policyId, policyBody) => { 90 return auth.createPolicy(policyId, policyBody).then(() => { 91 setSelected([]); 92 setCreateModalError(null); 93 setShowCreate(false); 94 setRefresh(!refresh); 95 }).catch((err) => { 96 setCreateModalError(err.message); 97 }) 98 }} 99 onHide={() => { 100 setCreateModalError(null); 101 setShowCreate(false) 102 }} 103 show={showCreate} 104 validationFunction={disallowPercentSign(INVALID_POLICY_ID_ERROR_MESSAGE)} 105 externalError={createModalError} 106 /> 107 108 <DataTable 109 results={results} 110 headers={['', 'Policy ID', 'Created At']} 111 keyFn={policy => policy.id} 112 rowFn={policy => [ 113 <Checkbox 114 name={policy.id} 115 onAdd={() => setSelected([...selected, policy])} 116 onRemove={() => setSelected(selected.filter(p => p !== policy))} 117 />, 118 <Link href={{pathname: '/auth/policies/:policyId', params: {policyId: policy.id}}}> 119 {policy.id} 120 </Link>, 121 <FormattedDate dateValue={policy.creation_date}/> 122 ]}/> 123 124 <Paginator 125 nextPage={nextPage} 126 after={after} 127 onPaginate={after => router.push({pathname: '/auth/policies', query: {after}})} 128 /> 129 </> 130 ); 131 }; 132 133 134 const PoliciesPage = () => { 135 const [setActiveTab] = useOutletContext(); 136 useEffect(() => setActiveTab("policies"), [setActiveTab]); 137 return <PoliciesContainer/>; 138 }; 139 140 export default PoliciesPage;