delete oauth2 clients

This commit is contained in:
Evert Prants 2022-09-09 17:37:42 +03:00
parent 19f2a820eb
commit 0a90ca6bb9
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
7 changed files with 101 additions and 49 deletions

View File

@ -88,10 +88,12 @@ const EditClientModal = ({
isAdmin: boolean;
}>) => {
const formRef = useRef<HTMLFormElement>(null);
const scopeReq = useSWR<string[]>('/api/admin/oauth2/scopes');
const grantReq = useSWR<string[]>('/api/admin/oauth2/grants');
const { formData, handleInputChange, handleSubmit } = useForm<
Partial<OAuth2ClientListItem>
>(client || {}, () => {
>(client || { grants: 'authorization_code' }, () => {
toast
.promise(
publishJSON(
@ -151,6 +153,16 @@ const EditClientModal = ({
value={formData.scope || ''}
onChange={handleInputChange}
/>
{scopeReq.data && (
<span>
<b>Available:</b>{' '}
{scopeReq.data
.filter(
(item) => !formData.scope?.split(' ').includes(item)
)
.join(', ') || 'None'}
</span>
)}
</FormControl>
<FormControl>
<label htmlFor="grants">Allowed grant types</label>
@ -160,6 +172,16 @@ const EditClientModal = ({
value={formData.grants || ''}
onChange={handleInputChange}
/>
{grantReq.data && (
<span>
<b>Available:</b>{' '}
{grantReq.data
.filter(
(item) => !formData.grants?.split(' ').includes(item)
)
.join(', ') || 'None'}
</span>
)}
</FormControl>
{isAdmin && (
<>
@ -268,7 +290,7 @@ const OAuth2ClientCard = ({
<button
onClick={() =>
ModalService.open(EditClientModal, {
client: client,
client,
isAdmin,
update,
})
@ -290,7 +312,32 @@ const OAuth2ClientCard = ({
>
Copy secret
</button>
{!client.activated && <button>Delete client</button>}
{!client.activated && (
<button
onClick={() => {
toast
.promise(
publishJSON(
`/api/admin/oauth2/clients/${client.id}`,
'DELETE'
),
{
loading: 'Deleting client...',
success: 'Client deleted!',
error: (err) =>
`Deleting the client failed: ${err.message}`,
}
)
.then((data) => {
if (data) {
update();
}
});
}}
>
Delete client
</button>
)}
</Dropdown>
</div>
<span className={styles.clientDescription}>{client.description}</span>

View File

@ -47,7 +47,7 @@ const PrivilegeEditor = ({
user: UserListItem;
onChange: (privvy: Privilege[]) => void;
}) => {
const [toggle, setToggle] = useState(false);
const [userPrivvy, setUserPrivvy] = useState(user.privileges || []);
const [selectionAvailable, setSelectionAvailable] = useState<string[]>([]);
const [selectionExisting, setSelectionExisting] = useState<string[]>([]);
const [availablePrivileges, setAvailablePrivileges] = useState<Privilege[]>(
@ -61,7 +61,7 @@ const PrivilegeEditor = ({
({ id }) => !(user.privileges || []).some((privvy) => privvy.id === id)
)
);
}, [user, data, toggle]);
}, [user, data, userPrivvy]);
return (
<>
@ -91,10 +91,9 @@ const PrivilegeEditor = ({
const toAdd = availablePrivileges.filter(({ id }) =>
selectionAvailable.includes(id.toString())
);
user.privileges = [...(user.privileges || []), ...toAdd];
setToggle(!toggle);
setUserPrivvy([...(userPrivvy || []), ...toAdd]);
setSelectionAvailable([]);
onChange(user.privileges);
onChange(userPrivvy);
}}
>
&gt;&gt;
@ -104,12 +103,13 @@ const PrivilegeEditor = ({
disabled={!selectionExisting.length}
onClick={() => {
// Remove privileges
user.privileges = (user.privileges || []).filter(
({ id }) => !selectionExisting.includes(id.toString())
);
onChange(user.privileges);
onChange(userPrivvy);
setSelectionExisting([]);
setToggle(!toggle);
setUserPrivvy(
(userPrivvy || []).filter(
({ id }) => !selectionExisting.includes(id.toString())
)
);
}}
>
&lt;&lt;

View File

@ -7,7 +7,7 @@ export const Button = ({
children,
...props
}: {
variant?: 'default' | 'primary' | 'secondary';
variant?: 'default' | 'primary' | 'secondary' | 'link';
onClick: MouseEventHandler<HTMLButtonElement>;
children?: React.ReactNode;
} & JSX.IntrinsicElements['button']) => {

View File

@ -34,6 +34,12 @@
font-weight: 400;
border: 1px solid #a4a4a4;
box-shadow: inset 0 0 4px #0000001f;
+ span {
font-size: 0.875rem;
margin-top: 0.25rem;
color: rgb(100, 100, 100);
}
}
&:last-child {

View File

@ -21,11 +21,11 @@ const navItems = [
title: 'OAuth2',
privileges: [['admin', 'admin:oauth2'], 'self:oauth2'],
},
{
path: '/privileges',
title: 'Privileges',
privileges: ['admin', 'admin:user:privilege'],
},
// {
// path: '/privileges',
// title: 'Privileges',
// privileges: ['admin', 'admin:user:privilege'],
// },
{
path: '/documents',
title: 'Documents',

View File

@ -11,39 +11,37 @@ export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.query.code) {
if (!req.query.state) {
if (!req.query.code || !req.query.state) {
return res.redirect('/');
}
const getAuth = await getAccessToken(req.query.code as string);
const cookies = new Cookies(req, res, { keys: COOKIE_KEYS });
if (getAuth) {
const decrypted = decrypt(req.query.state as string);
const stateToken = cookies.get('validation', { signed: true });
const parsedState = JSON.parse(decrypted);
if (
parsedState.state !== stateToken ||
parsedState.redirect_uri !== redirect
) {
return res.redirect('/');
}
const getAuth = await getAccessToken(req.query.code as string);
const cookies = new Cookies(req, res, { keys: COOKIE_KEYS });
cookies.set('authorization', getAuth.access_token, {
expires: new Date(Date.now() + getAuth.expires_in * 1000),
secure: process.env.NODE_ENV === 'production',
signed: true,
});
if (getAuth) {
const decrypted = decrypt(req.query.state as string);
const stateToken = cookies.get('validation', { signed: true });
const parsedState = JSON.parse(decrypted);
if (
parsedState.state !== stateToken ||
parsedState.redirect_uri !== redirect
) {
return res.redirect('/');
}
cookies.set('authorization', getAuth.access_token, {
expires: new Date(Date.now() + getAuth.expires_in * 1000),
secure: process.env.NODE_ENV === 'production',
signed: true,
});
cookies.set('validation', undefined, {
expires: new Date(0),
secure: process.env.NODE_ENV === 'production',
signed: true,
});
}
res.redirect('/');
cookies.set('validation', undefined, {
expires: new Date(0),
secure: process.env.NODE_ENV === 'production',
signed: true,
});
}
res.redirect('/');
}

View File

@ -2,6 +2,7 @@ input,
button,
textarea,
a {
transition: outline 0.15s linear;
&:focus {
outline: 4px solid #94cfff9c;
}