Skip to content

Commit

Permalink
move to unfied policy command
Browse files Browse the repository at this point in the history
Signed-off-by: orweis <[email protected]>
  • Loading branch information
orweis committed Oct 28, 2024
1 parent ec64300 commit ece0578
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 104 deletions.
132 changes: 132 additions & 0 deletions source/commands/opa/policy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import React from 'react';
import { Box, Newline, Text } from 'ink';
import zod from 'zod';
import { option } from 'pastel';
import Spinner from 'ink-spinner';
import { keyAccountOption } from '../../options/keychain.js';
import { inspect } from 'util';
import { loadAuthToken } from '../../lib/auth.js';
import { TextInput, UnorderedList, Select } from '@inkjs/ui';
import Fuse from 'fuse.js';

export const options = zod.object({
serverUrl: zod
.string()
.default('http://localhost:8181')
.describe(
option({
description: 'The OPA server URL',
alias: 's',
}),
),
apiKey: zod
.string()
.optional()
.describe(
option({
description:
'The API key for the OPA Server and Permit env, project or Workspace',
}),
),
keyAccount: keyAccountOption,
});

type Props = {
options: zod.infer<typeof options>;
};

interface QueryResult {
result: { result: Array<any> };
status: number;
}

export default function List({ options }: Props) {
const [error, setError] = React.useState(null);
// result of API
const [res, setRes] = React.useState<QueryResult>({
result: { result: [] },
status: 0,
});
// selection
const [selection, setSelection] = React.useState<any>(undefined);
const [selectionFilter, setSelectionFilter] = React.useState('');

const queryOPA = async (apiKey: String, path?: String) => {
const document = path ? `/${path}` : '';
const response = await fetch(
`${options.serverUrl}/v1/policies${document}`,
// pass api key if not empty
{ headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : {} },
);
const data = await response.json();
setRes({ result: data, status: response.status });
};

React.useEffect(() => {
const performQuery = async () => {
const apiKey = options.apiKey || (await loadAuthToken());
await queryOPA(apiKey);
};
performQuery().catch(err => setError(err));
}, []);

const policyItems = res.result.result.map(i => {
return { label: i.id, value: i };
});
const fuse = new Fuse(policyItems, {
keys: ['label', 'id'],
minMatchCharLength: 0,
});
const filtered = fuse.search(selectionFilter).map(i => i.item);
const view = filtered.length === 0 ? policyItems : filtered;

return (
<>
<Text color={'green'}>
Listing Policies on Opa Server={options.serverUrl}
</Text>
{res.status === 0 && error === null && <Spinner type="dots" />}
{res.status === 200 && (
<>
{!selection && (
<>
<Text>
Showing {view.length} of {policyItems?.length} policies:
</Text>

<Box flexDirection="column" gap={1}>
<TextInput
placeholder="Type text to filter list"
onSubmit={setSelection}
onChange={setSelectionFilter}
suggestions={policyItems.map(i => i.label)}
/>
</Box>
<Box padding={2} flexDirection="column" gap={1}>
<Select options={view} onChange={setSelection} />
</Box>
</>
)}
{!!selection && (
<Box flexDirection="column" gap={1}>
<Text>
{inspect(selection, {
colors: true,
depth: null,
maxArrayLength: Infinity,
})}
</Text>
</Box>
)}
</>
)}
{error && (
<Box>
<Text color="red">Request failed: {JSON.stringify(error)}</Text>
<Newline />
<Text>{JSON.stringify(res)}</Text>
</Box>
)}
</>
);
}
104 changes: 0 additions & 104 deletions source/commands/opa/policy/list.tsx

This file was deleted.

0 comments on commit ece0578

Please sign in to comment.