github.com/minio/console@v1.4.1/web-app/src/screens/Console/Policies/AddPolicyScreen.tsx (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2022 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 import React, { Fragment, useEffect, useState } from "react"; 18 import { 19 AddAccessRuleIcon, 20 BackLink, 21 Box, 22 Button, 23 FormLayout, 24 Grid, 25 InputBox, 26 PageLayout, 27 } from "mds"; 28 import AddPolicyHelpBox from "./AddPolicyHelpBox"; 29 import CodeMirrorWrapper from "../Common/FormComponents/CodeMirrorWrapper/CodeMirrorWrapper"; 30 import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper"; 31 import HelpMenu from "../HelpMenu"; 32 import { IAM_PAGES } from "../../../common/SecureComponent/permissions"; 33 import { setErrorSnackMessage, setHelpName } from "../../../systemSlice"; 34 import { useNavigate } from "react-router-dom"; 35 import { useAppDispatch } from "../../../store"; 36 import { emptyPolicy } from "./utils"; 37 import { api } from "../../../api"; 38 39 const AddPolicyScreen = () => { 40 const dispatch = useAppDispatch(); 41 const navigate = useNavigate(); 42 43 const [addLoading, setAddLoading] = useState<boolean>(false); 44 const [policyName, setPolicyName] = useState<string>(""); 45 const [policyDefinition, setPolicyDefinition] = useState<string>(emptyPolicy); 46 47 const addRecord = (event: React.FormEvent) => { 48 event.preventDefault(); 49 if (addLoading) { 50 return; 51 } 52 setAddLoading(true); 53 api.policies 54 .addPolicy({ 55 name: policyName, 56 policy: policyDefinition, 57 }) 58 .then((res) => { 59 setAddLoading(false); 60 navigate(`${IAM_PAGES.POLICIES}`); 61 }) 62 .catch((err) => { 63 setAddLoading(false); 64 dispatch( 65 setErrorSnackMessage({ 66 errorMessage: "There was an error creating a Policy ", 67 detailedError: 68 "There was an error creating a Policy: " + 69 (err.error.detailedMessage || "") + 70 ". Please check Policy syntax.", 71 }), 72 ); 73 }); 74 }; 75 76 const resetForm = () => { 77 setPolicyName(""); 78 setPolicyDefinition(""); 79 }; 80 81 const validatePolicyname = (policyName: string) => { 82 if (policyName.indexOf(" ") !== -1) { 83 return "Policy name cannot contain spaces"; 84 } else return ""; 85 }; 86 87 const validSave = 88 policyName.trim() !== "" && 89 policyName.indexOf(" ") === -1 && 90 policyDefinition.trim() !== ""; 91 92 useEffect(() => { 93 dispatch(setHelpName("add_policy")); 94 // eslint-disable-next-line react-hooks/exhaustive-deps 95 }, []); 96 return ( 97 <Fragment> 98 <Grid item xs={12}> 99 <PageHeaderWrapper 100 label={ 101 <BackLink 102 label={"Policies"} 103 onClick={() => navigate(IAM_PAGES.POLICIES)} 104 /> 105 } 106 actions={<HelpMenu />} 107 /> 108 <PageLayout> 109 <FormLayout 110 title={"Create Policy"} 111 icon={<AddAccessRuleIcon />} 112 helpBox={<AddPolicyHelpBox />} 113 > 114 <form 115 noValidate 116 autoComplete="off" 117 onSubmit={(e: React.FormEvent<HTMLFormElement>) => { 118 addRecord(e); 119 }} 120 > 121 <Grid container> 122 <Grid item xs={12}> 123 <InputBox 124 id="policy-name" 125 name="policy-name" 126 label="Policy Name" 127 autoFocus={true} 128 value={policyName} 129 error={validatePolicyname(policyName)} 130 onChange={(e: React.ChangeEvent<HTMLInputElement>) => { 131 setPolicyName(e.target.value); 132 }} 133 /> 134 </Grid> 135 <Grid item xs={12}> 136 <CodeMirrorWrapper 137 label={"Write Policy"} 138 value={policyDefinition} 139 onChange={(value) => { 140 setPolicyDefinition(value); 141 }} 142 editorHeight={"350px"} 143 helptip={ 144 <Fragment> 145 <a 146 target="blank" 147 href="https://min.io/docs/minio/kubernetes/upstream/administration/identity-access-management/policy-based-access-control.html#policy-document-structure" 148 > 149 Guide to access policy structure 150 </a> 151 </Fragment> 152 } 153 /> 154 </Grid> 155 <Grid item xs={12} sx={{ textAlign: "right" }}> 156 <Box 157 sx={{ 158 display: "flex", 159 alignItems: "center", 160 justifyContent: "flex-end", 161 marginTop: "20px", 162 gap: "15px", 163 }} 164 > 165 <Button 166 id={"clear"} 167 type="button" 168 variant="regular" 169 onClick={resetForm} 170 label={"Clear"} 171 /> 172 173 <Button 174 id={"save-policy"} 175 type="submit" 176 variant="callAction" 177 color="primary" 178 disabled={addLoading || !validSave} 179 label={"Save"} 180 /> 181 </Box> 182 </Grid> 183 </Grid> 184 </form> 185 </FormLayout> 186 </PageLayout> 187 </Grid> 188 </Fragment> 189 ); 190 }; 191 192 export default AddPolicyScreen;