Skip to content
Merged
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
16 changes: 12 additions & 4 deletions src/app/api/settings/disappearing-messages/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,23 @@ function getServiceRoleClient() {
return supabase;
}

function getBearerToken(authHeader) {
if (typeof authHeader !== 'string') return null;

const match = authHeader.match(/^Bearer\s+(.+)$/i);
const token = match?.[1]?.trim();

return token || null;
}

export async function GET(request) {
try {
const authHeader = request.headers.get('authorization');
if (!authHeader?.startsWith('Bearer ')) {
const token = getBearerToken(authHeader);
if (!token) {
return NextResponse.json({ error: 'Missing or invalid authorization header' }, { status: 401 });
}

const token = authHeader.split(' ')[1];
const client = getServiceRoleClient();

// Verify the JWT token and get user
Expand Down Expand Up @@ -54,11 +62,11 @@ export async function GET(request) {
export async function PUT(request) {
try {
const authHeader = request.headers.get('authorization');
if (!authHeader?.startsWith('Bearer ')) {
const token = getBearerToken(authHeader);
if (!token) {
return NextResponse.json({ error: 'Missing or invalid authorization header' }, { status: 401 });
}

const token = authHeader.split(' ')[1];
const client = getServiceRoleClient();

// Verify the JWT token and get user
Expand Down
43 changes: 41 additions & 2 deletions src/app/api/settings/disappearing-messages/route.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ vi.mock('@/lib/supabase/service-role.js', () => ({
createServiceRoleClient: mocks.createServiceRoleClient
}));

function request(method, body) {
function request(method, body, authorization = 'Bearer valid-token') {
return new Request('https://qrypt.chat/api/settings/disappearing-messages', {
method,
headers: {
authorization: 'Bearer valid-token',
authorization,
...(body ? { 'content-type': 'application/json' } : {})
},
body: body ? JSON.stringify(body) : undefined
Expand Down Expand Up @@ -76,6 +76,27 @@ describe('settings disappearing messages authentication', () => {
expect(mocks.profileEq).toHaveBeenCalledWith('auth_user_id', 'auth-user-id');
});

it('normalizes bearer scheme casing and extra spaces for GET requests', async () => {
const { GET } = await import('./route.js');

const response = await GET(request('GET', undefined, 'bearer valid-token '));

expect(response.status).toBe(200);
expect(mocks.authGetUser).toHaveBeenCalledWith('valid-token');
});

it('rejects an empty GET bearer header before creating the service client', async () => {
const { GET } = await import('./route.js');

const response = await GET(request('GET', undefined, 'Bearer '));
const body = await response.json();

expect(response.status).toBe(401);
expect(body.error).toBe('Missing or invalid authorization header');
expect(mocks.createServiceRoleClient).not.toHaveBeenCalled();
expect(mocks.authGetUser).not.toHaveBeenCalled();
});

it('initializes the service client before authenticating PUT requests', async () => {
mocks.from.mockImplementation((table) => {
if (table !== 'users') throw new Error(`Unexpected table: ${table}`);
Expand All @@ -91,4 +112,22 @@ describe('settings disappearing messages authentication', () => {
expect(mocks.authGetUser).toHaveBeenCalledWith('valid-token');
expect(mocks.updateEq).toHaveBeenCalledWith('auth_user_id', 'auth-user-id');
});

it('normalizes bearer scheme casing and extra spaces for PUT requests', async () => {
mocks.from.mockImplementation((table) => {
if (table !== 'users') throw new Error(`Unexpected table: ${table}`);
return updateQuery();
});
const { PUT } = await import('./route.js');

const response = await PUT(request(
'PUT',
{ default_message_retention_days: 3 },
'bearer valid-token '
));

expect(response.status).toBe(200);
expect(mocks.authGetUser).toHaveBeenCalledWith('valid-token');
expect(mocks.updateEq).toHaveBeenCalledWith('auth_user_id', 'auth-user-id');
});
});
Loading