delete oauth2 clients
This commit is contained in:
parent
19f2a820eb
commit
0a90ca6bb9
@ -88,10 +88,12 @@ const EditClientModal = ({
|
|||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
}>) => {
|
}>) => {
|
||||||
const formRef = useRef<HTMLFormElement>(null);
|
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<
|
const { formData, handleInputChange, handleSubmit } = useForm<
|
||||||
Partial<OAuth2ClientListItem>
|
Partial<OAuth2ClientListItem>
|
||||||
>(client || {}, () => {
|
>(client || { grants: 'authorization_code' }, () => {
|
||||||
toast
|
toast
|
||||||
.promise(
|
.promise(
|
||||||
publishJSON(
|
publishJSON(
|
||||||
@ -151,6 +153,16 @@ const EditClientModal = ({
|
|||||||
value={formData.scope || ''}
|
value={formData.scope || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
/>
|
/>
|
||||||
|
{scopeReq.data && (
|
||||||
|
<span>
|
||||||
|
<b>Available:</b>{' '}
|
||||||
|
{scopeReq.data
|
||||||
|
.filter(
|
||||||
|
(item) => !formData.scope?.split(' ').includes(item)
|
||||||
|
)
|
||||||
|
.join(', ') || 'None'}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<label htmlFor="grants">Allowed grant types</label>
|
<label htmlFor="grants">Allowed grant types</label>
|
||||||
@ -160,6 +172,16 @@ const EditClientModal = ({
|
|||||||
value={formData.grants || ''}
|
value={formData.grants || ''}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
/>
|
/>
|
||||||
|
{grantReq.data && (
|
||||||
|
<span>
|
||||||
|
<b>Available:</b>{' '}
|
||||||
|
{grantReq.data
|
||||||
|
.filter(
|
||||||
|
(item) => !formData.grants?.split(' ').includes(item)
|
||||||
|
)
|
||||||
|
.join(', ') || 'None'}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
{isAdmin && (
|
{isAdmin && (
|
||||||
<>
|
<>
|
||||||
@ -268,7 +290,7 @@ const OAuth2ClientCard = ({
|
|||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
ModalService.open(EditClientModal, {
|
ModalService.open(EditClientModal, {
|
||||||
client: client,
|
client,
|
||||||
isAdmin,
|
isAdmin,
|
||||||
update,
|
update,
|
||||||
})
|
})
|
||||||
@ -290,7 +312,32 @@ const OAuth2ClientCard = ({
|
|||||||
>
|
>
|
||||||
Copy secret
|
Copy secret
|
||||||
</button>
|
</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>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
<span className={styles.clientDescription}>{client.description}</span>
|
<span className={styles.clientDescription}>{client.description}</span>
|
||||||
|
@ -47,7 +47,7 @@ const PrivilegeEditor = ({
|
|||||||
user: UserListItem;
|
user: UserListItem;
|
||||||
onChange: (privvy: Privilege[]) => void;
|
onChange: (privvy: Privilege[]) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const [toggle, setToggle] = useState(false);
|
const [userPrivvy, setUserPrivvy] = useState(user.privileges || []);
|
||||||
const [selectionAvailable, setSelectionAvailable] = useState<string[]>([]);
|
const [selectionAvailable, setSelectionAvailable] = useState<string[]>([]);
|
||||||
const [selectionExisting, setSelectionExisting] = useState<string[]>([]);
|
const [selectionExisting, setSelectionExisting] = useState<string[]>([]);
|
||||||
const [availablePrivileges, setAvailablePrivileges] = useState<Privilege[]>(
|
const [availablePrivileges, setAvailablePrivileges] = useState<Privilege[]>(
|
||||||
@ -61,7 +61,7 @@ const PrivilegeEditor = ({
|
|||||||
({ id }) => !(user.privileges || []).some((privvy) => privvy.id === id)
|
({ id }) => !(user.privileges || []).some((privvy) => privvy.id === id)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}, [user, data, toggle]);
|
}, [user, data, userPrivvy]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -91,10 +91,9 @@ const PrivilegeEditor = ({
|
|||||||
const toAdd = availablePrivileges.filter(({ id }) =>
|
const toAdd = availablePrivileges.filter(({ id }) =>
|
||||||
selectionAvailable.includes(id.toString())
|
selectionAvailable.includes(id.toString())
|
||||||
);
|
);
|
||||||
user.privileges = [...(user.privileges || []), ...toAdd];
|
setUserPrivvy([...(userPrivvy || []), ...toAdd]);
|
||||||
setToggle(!toggle);
|
|
||||||
setSelectionAvailable([]);
|
setSelectionAvailable([]);
|
||||||
onChange(user.privileges);
|
onChange(userPrivvy);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
>>
|
>>
|
||||||
@ -104,12 +103,13 @@ const PrivilegeEditor = ({
|
|||||||
disabled={!selectionExisting.length}
|
disabled={!selectionExisting.length}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// Remove privileges
|
// Remove privileges
|
||||||
user.privileges = (user.privileges || []).filter(
|
onChange(userPrivvy);
|
||||||
({ id }) => !selectionExisting.includes(id.toString())
|
|
||||||
);
|
|
||||||
onChange(user.privileges);
|
|
||||||
setSelectionExisting([]);
|
setSelectionExisting([]);
|
||||||
setToggle(!toggle);
|
setUserPrivvy(
|
||||||
|
(userPrivvy || []).filter(
|
||||||
|
({ id }) => !selectionExisting.includes(id.toString())
|
||||||
|
)
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<<
|
<<
|
||||||
|
@ -7,7 +7,7 @@ export const Button = ({
|
|||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
variant?: 'default' | 'primary' | 'secondary';
|
variant?: 'default' | 'primary' | 'secondary' | 'link';
|
||||||
onClick: MouseEventHandler<HTMLButtonElement>;
|
onClick: MouseEventHandler<HTMLButtonElement>;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
} & JSX.IntrinsicElements['button']) => {
|
} & JSX.IntrinsicElements['button']) => {
|
||||||
|
@ -34,6 +34,12 @@
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
border: 1px solid #a4a4a4;
|
border: 1px solid #a4a4a4;
|
||||||
box-shadow: inset 0 0 4px #0000001f;
|
box-shadow: inset 0 0 4px #0000001f;
|
||||||
|
|
||||||
|
+ span {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
color: rgb(100, 100, 100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
|
@ -21,11 +21,11 @@ const navItems = [
|
|||||||
title: 'OAuth2',
|
title: 'OAuth2',
|
||||||
privileges: [['admin', 'admin:oauth2'], 'self:oauth2'],
|
privileges: [['admin', 'admin:oauth2'], 'self:oauth2'],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
path: '/privileges',
|
// path: '/privileges',
|
||||||
title: 'Privileges',
|
// title: 'Privileges',
|
||||||
privileges: ['admin', 'admin:user:privilege'],
|
// privileges: ['admin', 'admin:user:privilege'],
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
path: '/documents',
|
path: '/documents',
|
||||||
title: 'Documents',
|
title: 'Documents',
|
||||||
|
@ -11,39 +11,37 @@ export default async function handler(
|
|||||||
req: NextApiRequest,
|
req: NextApiRequest,
|
||||||
res: NextApiResponse
|
res: NextApiResponse
|
||||||
) {
|
) {
|
||||||
if (req.query.code) {
|
if (!req.query.code || !req.query.state) {
|
||||||
if (!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('/');
|
return res.redirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAuth = await getAccessToken(req.query.code as string);
|
cookies.set('authorization', getAuth.access_token, {
|
||||||
const cookies = new Cookies(req, res, { keys: COOKIE_KEYS });
|
expires: new Date(Date.now() + getAuth.expires_in * 1000),
|
||||||
|
secure: process.env.NODE_ENV === 'production',
|
||||||
|
signed: true,
|
||||||
|
});
|
||||||
|
|
||||||
if (getAuth) {
|
cookies.set('validation', undefined, {
|
||||||
const decrypted = decrypt(req.query.state as string);
|
expires: new Date(0),
|
||||||
const stateToken = cookies.get('validation', { signed: true });
|
secure: process.env.NODE_ENV === 'production',
|
||||||
const parsedState = JSON.parse(decrypted);
|
signed: true,
|
||||||
|
});
|
||||||
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('/');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res.redirect('/');
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ input,
|
|||||||
button,
|
button,
|
||||||
textarea,
|
textarea,
|
||||||
a {
|
a {
|
||||||
|
transition: outline 0.15s linear;
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: 4px solid #94cfff9c;
|
outline: 4px solid #94cfff9c;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user