0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-03 21:48:55 -05:00

fix(console,core): fix application count bug (#5270)

fix application count bug
This commit is contained in:
simeng-li 2024-01-23 11:22:26 +08:00 committed by GitHub
parent 4976154e6d
commit 42e9513ca1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 45 additions and 10 deletions

View file

@ -64,6 +64,7 @@ const useApplicationsData = (isThirdParty = false) => {
buildUrl(applicationsEndpoint, { buildUrl(applicationsEndpoint, {
page: String(firstPartyApplicationPage), page: String(firstPartyApplicationPage),
page_size: String(pageSize), page_size: String(pageSize),
isThirdParty: 'false',
}), }),
[firstPartyApplicationPage] [firstPartyApplicationPage]
); );

View file

@ -73,7 +73,7 @@ export const createApplicationQueries = (pool: CommonQueryMethods) => {
? sql`${fields.id} not in (${sql.join(excludeApplicationIds, sql`, `)})` ? sql`${fields.id} not in (${sql.join(excludeApplicationIds, sql`, `)})`
: sql``, : sql``,
types && types.length > 0 ? sql`${fields.type} in (${sql.join(types, sql`, `)})` : sql``, types && types.length > 0 ? sql`${fields.type} in (${sql.join(types, sql`, `)})` : sql``,
isThirdParty ? sql`${fields.isThirdParty} = true` : sql`${fields.isThirdParty} = false`, typeof isThirdParty === 'boolean' ? sql`${fields.isThirdParty} = ${isThirdParty}` : sql``,
buildApplicationConditions(search), buildApplicationConditions(search),
])} ])}
`); `);
@ -118,7 +118,7 @@ export const createApplicationQueries = (pool: CommonQueryMethods) => {
? sql`${fields.id} not in (${sql.join(excludeApplicationIds, sql`, `)})` ? sql`${fields.id} not in (${sql.join(excludeApplicationIds, sql`, `)})`
: sql``, : sql``,
types && types.length > 0 ? sql`${fields.type} in (${sql.join(types, sql`, `)})` : sql``, types && types.length > 0 ? sql`${fields.type} in (${sql.join(types, sql`, `)})` : sql``,
isThirdParty ? sql`${fields.isThirdParty} = true` : sql`${fields.isThirdParty} = false`, typeof isThirdParty === 'boolean' ? sql`${fields.isThirdParty} = ${isThirdParty}` : sql``,
buildApplicationConditions(search), buildApplicationConditions(search),
])} ])}
order by ${fields.createdAt} desc order by ${fields.createdAt} desc

View file

@ -56,6 +56,19 @@ export default function applicationRoutes<T extends AuthedRouter>(
} = queries.applicationsRoles; } = queries.applicationsRoles;
const { findRoleByRoleName } = queries.roles; const { findRoleByRoleName } = queries.roles;
const parseIsThirdPartQueryParam = (isThirdPartyQuery: 'true' | 'false ' | undefined) => {
// FIXME: @simeng-li Remove this guard once Logto as IdP is ready
if (!EnvSet.values.isDevFeaturesEnabled) {
return false;
}
if (isThirdPartyQuery === undefined) {
return;
}
return isThirdPartyQuery === 'true';
};
router.get( router.get(
'/applications', '/applications',
koaPagination({ isOptional: true }), koaPagination({ isOptional: true }),
@ -72,7 +85,9 @@ export default function applicationRoutes<T extends AuthedRouter>(
excludeRoleId: string().optional(), excludeRoleId: string().optional(),
// FIXME: @simeng-li Remove this guard once Logto as IdP is ready // FIXME: @simeng-li Remove this guard once Logto as IdP is ready
...conditional( ...conditional(
EnvSet.values.isDevFeaturesEnabled && { isThirdParty: z.literal('true').optional() } EnvSet.values.isDevFeaturesEnabled && {
isThirdParty: z.union([z.literal('true'), z.literal('false')]).optional(),
}
), ),
}), }),
response: z.array(applicationResponseGuard), response: z.array(applicationResponseGuard),
@ -81,10 +96,10 @@ export default function applicationRoutes<T extends AuthedRouter>(
async (ctx, next) => { async (ctx, next) => {
const { limit, offset, disabled: paginationDisabled } = ctx.pagination; const { limit, offset, disabled: paginationDisabled } = ctx.pagination;
const { searchParams } = ctx.URL; const { searchParams } = ctx.URL;
const { types, excludeRoleId } = ctx.guard.query; const { types, excludeRoleId, isThirdParty: isThirdPartyParam } = ctx.guard.query;
// FIXME: @simeng-li Remove this guard once Logto as IdP is ready // @ts-expect-error FIXME: unknown type will be fixed once we have the isDevFeaturesEnabled guard removed
const isThirdParty = Boolean(ctx.guard.query.isThirdParty); const isThirdParty = parseIsThirdPartQueryParam(isThirdPartyParam);
// This will only parse the `search` query param, other params will be ignored. Please use query guard to validate them. // This will only parse the `search` query param, other params will be ignored. Please use query guard to validate them.
const search = parseSearchParamsForSearch(searchParams); const search = parseSearchParamsForSearch(searchParams);

View file

@ -28,7 +28,7 @@ export const createApplication = async (
export const getApplications = async ( export const getApplications = async (
types?: ApplicationType[], types?: ApplicationType[],
searchParameters?: Record<string, string>, searchParameters?: Record<string, string>,
isThirdParty?: boolean isThirdParty?: 'true' | 'false'
) => { ) => {
const searchParams = new URLSearchParams([ const searchParams = new URLSearchParams([
...(conditional(types && types.length > 0 && types.map((type) => ['types', type])) ?? []), ...(conditional(types && types.length > 0 && types.map((type) => ['types', type])) ?? []),
@ -37,7 +37,7 @@ export const getApplications = async (
Object.keys(searchParameters).length > 0 && Object.keys(searchParameters).length > 0 &&
Object.entries(searchParameters).map(([key, value]) => [key, value]) Object.entries(searchParameters).map(([key, value]) => [key, value])
) ?? []), ) ?? []),
...(conditional(isThirdParty && [['isThirdParty', 'true']]) ?? []), ...(conditional(isThirdParty && [['isThirdParty', isThirdParty]]) ?? []),
]); ]);
return authedAdminApi.get('applications', { searchParams }).json<Application[]>(); return authedAdminApi.get('applications', { searchParams }).json<Application[]>();

View file

@ -176,7 +176,7 @@ describe('admin console application', () => {
}); });
it('should fetch all non-third party applications created above', async () => { it('should fetch all non-third party applications created above', async () => {
const applications = await getApplications(); const applications = await getApplications(undefined, undefined, 'false');
const applicationNames = applications.map(({ name }) => name); const applicationNames = applications.map(({ name }) => name);
expect(applicationNames).toContain('test-create-app'); expect(applicationNames).toContain('test-create-app');
@ -194,13 +194,32 @@ describe('admin console application', () => {
} }
); );
const applications = await getApplications(undefined, undefined, true); const applications = await getApplications(undefined, undefined, 'true');
expect(applications.find(({ id }) => id === application.id)).toEqual(application); expect(applications.find(({ id }) => id === application.id)).toEqual(application);
expect(applications.some(({ isThirdParty }) => !isThirdParty)).toBe(false); expect(applications.some(({ isThirdParty }) => !isThirdParty)).toBe(false);
await deleteApplication(application.id); await deleteApplication(application.id);
}); });
it('should fetch all applications including third party applications', async () => {
const application = await createApplication(
'test-third-party-app',
ApplicationType.Traditional,
{
isThirdParty: true,
}
);
const applications = await getApplications();
const applicationNames = applications.map(({ name }) => name);
expect(applicationNames).toContain('test-create-app');
expect(applicationNames).toContain('test-update-app');
expect(applicationNames).toContain('test-third-party-app');
await deleteApplication(application.id);
});
it('should create m2m application successfully and can get only m2m applications by specifying types', async () => { it('should create m2m application successfully and can get only m2m applications by specifying types', async () => {
await createApplication('test-m2m-app-1', ApplicationType.MachineToMachine); await createApplication('test-m2m-app-1', ApplicationType.MachineToMachine);
await createApplication('test-m2m-app-2', ApplicationType.MachineToMachine); await createApplication('test-m2m-app-2', ApplicationType.MachineToMachine);