Fixed API Query permissions in User Settings (#18680)
refs https://www.notion.so/ghost/Cannot-fetch-invites-error-shown-for-authors-edc00af822d844e7add114fd834fc8fc - the problem is that certain users don't have permissions to make certain API calls. - This adds a new hook that validates the current user against permissions before a query can be made. --- <!-- Leave the line below if you'd like GitHub Copilot to generate a summary from your commit --> <!-- copilot:summary --> ### <samp>🤖 Generated by Copilot at 9d9cc07</samp> Added a `usePermission` hook and a `permissions` option for custom API queries to implement role-based permissions in the admin settings app.
This commit is contained in:
parent
099db95278
commit
a9ad08cf89
@ -1,4 +1,3 @@
|
||||
import nql from '@tryghost/nql';
|
||||
import {Setting} from './settings';
|
||||
import {createMutation, createQuery} from '../utils/api/hooks';
|
||||
|
||||
@ -49,11 +48,3 @@ export const useEditCustomThemeSettings = createMutation<CustomThemeSettingsResp
|
||||
update: newData => newData
|
||||
}
|
||||
});
|
||||
|
||||
export function isCustomThemeSettingVisible(setting: CustomThemeSetting, settingsKeyValueObj: Record<string, string>) {
|
||||
if (!setting.visibility) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return nql(setting.visibility).queryJSON(settingsKeyValueObj);
|
||||
}
|
||||
|
@ -20,7 +20,8 @@ const dataType = 'InvitesResponseType';
|
||||
|
||||
export const useBrowseInvites = createQuery<InvitesResponseType>({
|
||||
dataType,
|
||||
path: '/invites/'
|
||||
path: '/invites/',
|
||||
permissions: ['Owner', 'Administrator']
|
||||
});
|
||||
|
||||
export const useAddInvite = createMutation<InvitesResponseType, {email: string, roleId: string}>({
|
||||
|
@ -1,6 +1,7 @@
|
||||
import IframeBuffering from '../../../../utils/IframeBuffering';
|
||||
import React, {useCallback} from 'react';
|
||||
import {CustomThemeSetting, hiddenCustomThemeSettingValue, isCustomThemeSettingVisible} from '../../../../api/customThemeSettings';
|
||||
import {CustomThemeSetting, hiddenCustomThemeSettingValue} from '../../../../api/customThemeSettings';
|
||||
import {isCustomThemeSettingVisible} from '../../../../utils/isCustomThemeSettingsVisible';
|
||||
|
||||
type BrandSettings = {
|
||||
description: string;
|
||||
|
@ -8,9 +8,10 @@ import SettingGroupContent from '../../../../admin-x-ds/settings/SettingGroupCon
|
||||
import TextField from '../../../../admin-x-ds/global/form/TextField';
|
||||
import Toggle from '../../../../admin-x-ds/global/form/Toggle';
|
||||
import useHandleError from '../../../../utils/api/handleError';
|
||||
import {CustomThemeSetting, isCustomThemeSettingVisible} from '../../../../api/customThemeSettings';
|
||||
import {CustomThemeSetting} from '../../../../api/customThemeSettings';
|
||||
import {getImageUrl, useUploadImage} from '../../../../api/images';
|
||||
import {humanizeSettingKey} from '../../../../api/settings';
|
||||
import {isCustomThemeSettingVisible} from '../../../../utils/isCustomThemeSettingsVisible';
|
||||
|
||||
const ThemeSetting: React.FC<{
|
||||
setting: CustomThemeSetting,
|
||||
|
11
apps/admin-x-settings/src/hooks/usePermissions.ts
Normal file
11
apps/admin-x-settings/src/hooks/usePermissions.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import {UserRoleType} from '../api/roles';
|
||||
import {useGlobalData} from '../components/providers/GlobalDataProvider';
|
||||
|
||||
export const usePermission = (userRoles:string[]) => {
|
||||
const {currentUser} = useGlobalData();
|
||||
const currentUserRoles = currentUser?.roles.map(role => role.name);
|
||||
if (!currentUserRoles) {
|
||||
return false;
|
||||
}
|
||||
return userRoles.some((role => currentUserRoles.includes(role as UserRoleType)));
|
||||
};
|
@ -6,6 +6,7 @@ import {UseInfiniteQueryOptions, UseQueryOptions, useInfiniteQuery, useMutation,
|
||||
import {getGhostPaths} from '../helpers';
|
||||
import {useCallback, useEffect, useMemo} from 'react';
|
||||
import {usePage, usePagination} from '../../hooks/usePagination';
|
||||
import {usePermission} from '../../hooks/usePermissions';
|
||||
import {useSentryDSN, useServices} from '../../components/providers/ServiceProvider';
|
||||
|
||||
export interface Meta {
|
||||
@ -149,6 +150,7 @@ interface QueryOptions<ResponseData> {
|
||||
dataType: string
|
||||
path: string
|
||||
defaultSearchParams?: Record<string, string>;
|
||||
permissions?: string[];
|
||||
returnData?: (originalData: unknown) => ResponseData;
|
||||
}
|
||||
|
||||
@ -163,6 +165,7 @@ export const createQuery = <ResponseData>(options: QueryOptions<ResponseData>) =
|
||||
const handleError = useHandleError();
|
||||
|
||||
const result = useQuery<ResponseData>({
|
||||
enabled: options.permissions ? usePermission(options.permissions) : true,
|
||||
queryKey: [options.dataType, url],
|
||||
queryFn: () => fetchApi(url),
|
||||
...query
|
||||
|
@ -0,0 +1,10 @@
|
||||
import nql from '@tryghost/nql';
|
||||
import {CustomThemeSetting} from '../api/customThemeSettings';
|
||||
|
||||
export function isCustomThemeSettingVisible(setting: CustomThemeSetting, settingsKeyValueObj: Record<string, string>) {
|
||||
if (!setting.visibility) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return nql(setting.visibility).queryJSON(settingsKeyValueObj);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import * as assert from 'assert/strict';
|
||||
import {CustomThemeSetting, isCustomThemeSettingVisible} from '../../../src/api/customThemeSettings';
|
||||
import {CustomThemeSetting} from '../../../src/api/customThemeSettings';
|
||||
import {isCustomThemeSettingVisible} from '../../../src/utils/isCustomThemeSettingsVisible';
|
||||
|
||||
describe('isCustomThemeSettingVisible', function () {
|
||||
it('returns whether or not a custom theme setting is visible', function () {
|
||||
|
Loading…
Reference in New Issue
Block a user