delete oauth2 clients
This commit is contained in:
parent
19f2a820eb
commit
0a90ca6bb9
@ -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>
|
||||
|
@ -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);
|
||||
}}
|
||||
>
|
||||
>>
|
||||
@ -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())
|
||||
)
|
||||
);
|
||||
}}
|
||||
>
|
||||
<<
|
||||
|
@ -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']) => {
|
||||
|
@ -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 {
|
||||
|
@ -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',
|
||||
|
@ -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('/');
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ input,
|
||||
button,
|
||||
textarea,
|
||||
a {
|
||||
transition: outline 0.15s linear;
|
||||
&:focus {
|
||||
outline: 4px solid #94cfff9c;
|
||||
}
|
||||
|
Reference in New Issue
Block a user