diff --git a/frontend/apps/remark42/app/common/api.ts b/frontend/apps/remark42/app/common/api.ts index 2eb2f0ed5a..a276eb8612 100644 --- a/frontend/apps/remark42/app/common/api.ts +++ b/frontend/apps/remark42/app/common/api.ts @@ -9,9 +9,10 @@ import { Sorting, BlockTTL, Image, + StatusResponse, EmailSubVerificationStatus, } from './types'; -import { apiFetcher, adminFetcher } from './fetcher'; +import { apiFetcher, adminFetcher, authFetcher } from './fetcher'; /* API methods */ @@ -61,7 +62,14 @@ export const removeMyComment = (id: Comment['id']): Promise => export const getPreview = (text: string): Promise => apiFetcher.post('/preview', {}, { text }); export function getUser(): Promise { - return apiFetcher.get('/user').catch(() => null); + return authFetcher.get('/status') + .then((resp) => { + if (resp.user) { + // verify that user is logged in first as otherwise we get an error 401 for unlogged user + return apiFetcher.get('/user').catch(() => null); + } + return Promise.resolve(null); + }); } export const uploadImage = (image: File): Promise => { diff --git a/frontend/apps/remark42/app/common/types.ts b/frontend/apps/remark42/app/common/types.ts index 173cf17e92..c66bb174b6 100644 --- a/frontend/apps/remark42/app/common/types.ts +++ b/frontend/apps/remark42/app/common/types.ts @@ -10,6 +10,11 @@ export type User = { paid_sub?: boolean; }; +export interface StatusResponse { + status: string; + user?: string; +} + /** data which is used on user-info page */ export type Profile = Pick & { current?: '1' }; diff --git a/frontend/packages/api/clients/index.ts b/frontend/packages/api/clients/index.ts index 3b648e3168..0b9267bc32 100644 --- a/frontend/packages/api/clients/index.ts +++ b/frontend/packages/api/clients/index.ts @@ -16,6 +16,11 @@ export interface User { paid_sub?: boolean } +export interface StatusResponse { + status: string; + user?: string; +} + export type OAuthProvider = | 'apple' | 'facebook' diff --git a/frontend/packages/api/clients/public.ts b/frontend/packages/api/clients/public.ts index 005014129c..bf66a7fee2 100644 --- a/frontend/packages/api/clients/public.ts +++ b/frontend/packages/api/clients/public.ts @@ -1,4 +1,4 @@ -import type { ClientParams, Provider, User } from './index' +import type { ClientParams, Provider, User, StatusResponse } from './index' import { createFetcher } from '../lib/fetcher' import { API_BASE } from '../consts' @@ -82,6 +82,7 @@ export type Vote = -1 | 1 export function createPublicClient({ siteId: site, baseUrl }: ClientParams) { const fetcher = createFetcher(site, `${baseUrl}${API_BASE}`) + const authFetcher = createFetcher(site,`${baseUrl}/auth`) /** * Get server config @@ -94,7 +95,14 @@ export function createPublicClient({ siteId: site, baseUrl }: ClientParams) { * Get current authorized user */ async function getUser(): Promise { - return fetcher.get('/user').catch(() => null) + return authFetcher.get('/status') + .then((resp: StatusResponse) => { + if (resp.user) { + // verify that user is logged in first as otherwise we get an error 401 for unlogged user + return fetcher.get('/user').catch(() => null); + } + return Promise.resolve(null); + }); } /** diff --git a/frontend/packages/api/tests/clients/public.test.ts b/frontend/packages/api/tests/clients/public.test.ts index 70734dab37..69d95e7129 100644 --- a/frontend/packages/api/tests/clients/public.test.ts +++ b/frontend/packages/api/tests/clients/public.test.ts @@ -97,11 +97,32 @@ describe('Public Client', (publicClient) => { }) }) - const userCases = [null, { id: '1', username: 'user' }] - userCases.forEach((user) => { - publicClient('should return user', async ({ client }) => { - mockEndpoint('/remark42/api/v1/user', { body: user }) - await expect(client.getUser()).resolves.toEqual(user) - }) - }) + const userCases = [ + { status: 'not logged in', user: null }, + { status: 'logged in', user: { id: '1', username: 'user' } }, + ]; + + userCases.forEach((testCase) => { + publicClient(`should return user when status is ${testCase.status}`, async ({ client }) => { + if (!testCase.user) { + mockEndpoint('/remark42/auth/status', { body: { status: testCase.status } }); + } else { + mockEndpoint('/remark42/auth/status', { + body: { + status: testCase.status, + user: testCase.user.username + } + }); + } + const userMock = mockEndpoint('/remark42/api/v1/user', { body: testCase.user }); + + await expect(client.getUser()).resolves.toEqual(testCase.status === 'logged in' ? testCase.user : null); + + if (testCase.status === 'not logged in') { + expect(userMock.req).not.toHaveBeenCalled(); + } else { + expect(userMock.req).toBeDefined(); + } + }); + }); })