()
| 89 | } |
| 90 | |
| 91 | export function SecretsManager() { |
| 92 | const roles = useAuthStore((state) => state.roles); |
| 93 | const canManageSecrets = hasAdminRole(roles); |
| 94 | const isReadOnly = !canManageSecrets; |
| 95 | const secrets = useSecretStore((state) => state.secrets); |
| 96 | const loading = useSecretStore((state) => state.loading); |
| 97 | const error = useSecretStore((state) => state.error); |
| 98 | const fetchSecrets = useSecretStore((state) => state.fetchSecrets); |
| 99 | const refreshSecrets = useSecretStore((state) => state.refresh); |
| 100 | const createSecret = useSecretStore((state) => state.createSecret); |
| 101 | const updateSecretMetadata = useSecretStore((state) => state.updateSecret); |
| 102 | const deleteSecretEntry = useSecretStore((state) => state.deleteSecret); |
| 103 | const rotateSecretValue = useSecretStore((state) => state.rotateSecret); |
| 104 | |
| 105 | const [formState, setFormState] = useState<FormState>(INITIAL_FORM); |
| 106 | const [formError, setFormError] = useState<string | null>(null); |
| 107 | const [formSuccess, setFormSuccess] = useState<string | null>(null); |
| 108 | const [isSubmitting, setIsSubmitting] = useState(false); |
| 109 | const disableCreate = isReadOnly || isSubmitting; |
| 110 | |
| 111 | const [listSuccess, setListSuccess] = useState<string | null>(null); |
| 112 | |
| 113 | const [isEditDialogOpen, setIsEditDialogOpen] = useState(false); |
| 114 | const [editingSecret, setEditingSecret] = useState<SecretSummary | null>(null); |
| 115 | const [editFormState, setEditFormState] = useState<EditFormState>(INITIAL_EDIT_FORM); |
| 116 | const [editError, setEditError] = useState<string | null>(null); |
| 117 | const [isEditing, setIsEditing] = useState(false); |
| 118 | const disableEditing = isReadOnly || isEditing; |
| 119 | |
| 120 | const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); |
| 121 | const [deleteTarget, setDeleteTarget] = useState<SecretSummary | null>(null); |
| 122 | const [deleteError, setDeleteError] = useState<string | null>(null); |
| 123 | const [isDeleting, setIsDeleting] = useState(false); |
| 124 | const disableDeleting = isReadOnly || isDeleting; |
| 125 | |
| 126 | useEffect(() => { |
| 127 | fetchSecrets().catch((err) => { |
| 128 | console.error('Failed to load secrets', err); |
| 129 | }); |
| 130 | }, [fetchSecrets]); |
| 131 | |
| 132 | useEffect(() => { |
| 133 | if (error) { |
| 134 | setListSuccess(null); |
| 135 | } |
| 136 | }, [error]); |
| 137 | |
| 138 | const handleChange = |
| 139 | (field: keyof FormState) => |
| 140 | (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { |
| 141 | setFormState((prev) => ({ |
| 142 | ...prev, |
| 143 | [field]: event.target.value, |
| 144 | })); |
| 145 | }; |
| 146 | |
| 147 | const handleEditChange = |
| 148 | (field: keyof EditFormState) => |
nothing calls this directly
no test coverage detected