1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-23 00:22:19 +01:00

fix: return 404 if the project doesn't exist (#8362)

This change adds a check for whether the project exists in the
database before trying to fetch data for it. If it doesn't exist,
you'll get a 404.
This commit is contained in:
Thomas Heartman 2024-10-04 15:43:02 +02:00 committed by GitHub
parent 1875c9b6d1
commit 2ac9c701c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 54 additions and 30 deletions

View File

@ -19,9 +19,7 @@ export class FakeOnboardingReadModel implements IOnboardingReadModel {
return Promise.resolve([]);
}
getOnboardingStatusForProject(
projectId: string,
): Promise<OnboardingStatus> {
throw new Error('Method not implemented.');
async getOnboardingStatusForProject(): Promise<OnboardingStatus | null> {
return null;
}
}

View File

@ -26,5 +26,7 @@ export type ProjectOnboarding = {
export interface IOnboardingReadModel {
getInstanceOnboardingMetrics(): Promise<InstanceOnboarding>;
getProjectsOnboardingMetrics(): Promise<Array<ProjectOnboarding>>;
getOnboardingStatusForProject(projectId: string): Promise<OnboardingStatus>;
getOnboardingStatusForProject(
projectId: string,
): Promise<OnboardingStatus | null>;
}

View File

@ -82,7 +82,16 @@ export class OnboardingReadModel implements IOnboardingReadModel {
async getOnboardingStatusForProject(
projectId: string,
): Promise<OnboardingStatus> {
): Promise<OnboardingStatus | null> {
const projectExists = await this.db('projects')
.select(1)
.where('id', projectId)
.first();
if (!projectExists) {
return null;
}
const feature = await this.db('features')
.select('name')
.where('project', projectId)

View File

@ -335,6 +335,14 @@ test('should return personal dashboard project details', async () => {
});
});
test("should return 404 if the project doesn't exist", async () => {
await loginUser('new_user@test.com');
await app.request
.get(`/api/admin/personal-dashboard/${randomId()}`)
.expect(404);
});
test('should return Unleash admins', async () => {
await loginUser('new_user@test.com');
const adminRoleId = 1;

View File

@ -21,6 +21,7 @@ import type { FeatureEventFormatter } from '../../addons/feature-event-formatter
import { generateImageUrl } from '../../util';
import type { PersonalDashboardProjectDetailsSchema } from '../../openapi';
import type { IRoleWithProject } from '../../types/stores/access-store';
import { NotFoundError } from '../../error';
export class PersonalDashboardService {
private personalDashboardReadModel: IPersonalDashboardReadModel;
@ -105,6 +106,17 @@ export class PersonalDashboardService {
userId: number,
projectId: string,
): Promise<PersonalDashboardProjectDetailsSchema> {
const onboardingStatus =
await this.onboardingReadModel.getOnboardingStatusForProject(
projectId,
);
if (!onboardingStatus) {
throw new NotFoundError(
`No project with id "${projectId}" exists.`,
);
}
const formatEvents = (recentEvents: IEvent[]) =>
recentEvents.map((event) => ({
summary: this.featureEventFormatter.format(event).text,
@ -122,29 +134,22 @@ export class PersonalDashboardService {
type: role.type as PersonalDashboardProjectDetailsSchema['roles'][number]['type'],
}));
const [latestEvents, onboardingStatus, owners, roles, healthScores] =
await Promise.all([
this.eventStore
.searchEvents({ limit: 4, offset: 0 }, [
{
field: 'project',
operator: 'IS',
values: [projectId],
},
])
.then(formatEvents),
this.onboardingReadModel.getOnboardingStatusForProject(
projectId,
),
this.projectOwnersReadModel.getProjectOwners(projectId),
this.accessStore
.getAllProjectRolesForUser(userId, projectId)
.then(filterRoles),
this.personalDashboardReadModel.getLatestHealthScores(
projectId,
8,
),
]);
const [latestEvents, owners, roles, healthScores] = await Promise.all([
this.eventStore
.searchEvents({ limit: 4, offset: 0 }, [
{
field: 'project',
operator: 'IS',
values: [projectId],
},
])
.then(formatEvents),
this.projectOwnersReadModel.getProjectOwners(projectId),
this.accessStore
.getAllProjectRolesForUser(userId, projectId)
.then(filterRoles),
this.personalDashboardReadModel.getLatestHealthScores(projectId, 8),
]);
let avgHealthCurrentWindow: number | null = null;
let avgHealthPastWindow: number | null = null;

View File

@ -1546,7 +1546,9 @@ export default class ProjectService {
updatedAt: project.updatedAt,
archivedAt: project.archivedAt,
createdAt: project.createdAt,
onboardingStatus,
onboardingStatus: onboardingStatus ?? {
status: 'onboarding-started',
},
environments,
featureTypeCounts,
members,