Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions apps/web/app/api/timesheet/activity/report/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NextRequest } from 'next/server';
import { NextRequest, NextResponse } from 'next/server';
import { authenticatedGuard } from '@/core/services/server/guards/authenticated-guard-app';
import { getActivityReportRequest } from '@/core/services/server/requests/timesheet';
import { IActivityRequestParams } from '@/core/services/server/requests/timesheet';
import { ETimeLogType } from '@/core/types/generics/enums/timer';
Expand All @@ -11,7 +12,15 @@ export const runtime = 'nodejs';
* Fetches activity report data based on provided query parameters
*/
export async function GET(req: NextRequest) {
const res = new NextResponse();

try {
// Authenticate before reading parameters: the guard answers 401 to a rejected token and 503 when
// the session check could not reach Gauzy, so an outage never looks like an expired session
const guard = await authenticatedGuard(req, res);
if (!guard.user) return guard.deny();
const { access_token } = guard;

const searchParams = req.nextUrl.searchParams;

const params: Partial<IActivityRequestParams> = {
Expand Down Expand Up @@ -63,7 +72,7 @@ export async function GET(req: NextRequest) {
}

// Fetch activity report data
const data = await getActivityReportRequest(params as IActivityRequestParams);
const { data } = await getActivityReportRequest(params as IActivityRequestParams, access_token);

return new Response(JSON.stringify(data), {
status: 200,
Expand Down
15 changes: 12 additions & 3 deletions apps/web/app/api/timesheet/time-log/report/daily/route.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { NextRequest } from 'next/server';
import { NextRequest, NextResponse } from 'next/server';
import { authenticatedGuard } from '@/core/services/server/guards/authenticated-guard-app';
import { getTimeLogReportDailyRequest } from '@/core/services/server/requests/timesheet';
import { ITimeLogRequestParams } from '@/core/services/server/requests/timesheet';

export const dynamic = 'force-dynamic';
export const runtime = 'nodejs';

export async function GET(req: NextRequest) {
const res = new NextResponse();

try {
// Authenticate before reading parameters: the guard answers 401 to a rejected token and 503 when
// the session check could not reach Gauzy, so an outage never looks like an expired session
const guard = await authenticatedGuard(req, res);
if (!guard.user) return guard.deny();
const { access_token } = guard;

const searchParams = req.nextUrl.searchParams;

const params: Partial<ITimeLogRequestParams> = {
Expand Down Expand Up @@ -53,9 +62,9 @@ export async function GET(req: NextRequest) {
};
}

const response = await getTimeLogReportDailyRequest(params as ITimeLogRequestParams);
const { data } = await getTimeLogReportDailyRequest(params as ITimeLogRequestParams, access_token);

return new Response(JSON.stringify(response), {
return new Response(JSON.stringify(data), {
status: 200,
headers: {
'Content-Type': 'application/json'
Expand Down
27 changes: 25 additions & 2 deletions apps/web/core/services/server/guards/authenticated-guard-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,37 @@
const taskId = getActiveTaskIdCookie({ req, res });
const projectId = getActiveProjectIdCookie({ req, res });

// serverFetch rejects a non-2xx answer with Promise.reject(data), so Gauzy's error body sits inside
// that promise; a network failure rejects with a plain error that carries no status code.
let rejection: { statusCode?: number; message?: string } | undefined;
const r_res = await currentAuthenticatedUserRequest({
bearer_token: access_token?.toString() || ''
}).catch(console.error);
}).catch(async (error: unknown) => {
const reason = error instanceof Promise ? await error.catch((data) => data) : error;

Check warning on line 26 in apps/web/core/services/server/guards/authenticated-guard-app.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

The catch parameter `data` should be named `error_`.

See more on https://sonarcloud.io/project/issues?id=ever-co_ever-teams&issues=AaB2B9UpDk5q6SaKiDPG&open=AaB2B9UpDk5q6SaKiDPG&pullRequest=4464
rejection = reason && typeof reason === 'object' ? reason : undefined;
console.error(reason);
});

if (!r_res || (r_res.data as any).statusCode === 401) {
// Keep Gauzy's own status (401, 404, 429...); only a check that never got an answer is a 503, so
// an outage never looks like an expired session that the client should log out.
const upstream: { statusCode?: number; message?: string } | undefined = rejection ?? (r_res?.data as any);
const status =
typeof upstream?.statusCode === 'number' && upstream.statusCode >= 400 ? upstream.statusCode : 503;
return {
$res: (data: any) => NextResponse.json({ statusCode: 401, message: data }),
user: null
user: null,
status,
deny: () =>
NextResponse.json(
{
message:
status === 503
? 'Session check unavailable, retry later'
: upstream?.message || 'Unauthorized'
},
{ status }
)
};
}

Expand Down
Loading