diff --git a/admin/src/api/auth.ts b/admin/src/api/auth.ts index 603caffe..c8262818 100644 --- a/admin/src/api/auth.ts +++ b/admin/src/api/auth.ts @@ -6,27 +6,15 @@ export type FigmaUser = { readonly email: string; }; -export type CheckAuthResponseBody = - | { - readonly type: '3LO'; - readonly authorized: true; - readonly grant: { - readonly authorizationEndpoint: string; - }; - readonly user: FigmaUser; - } - | { - readonly type: '3LO'; - readonly authorized: false; - readonly grant: { - readonly authorizationEndpoint: string; - }; - }; +export type MeResponseBody = { + readonly authorizationEndpoint: string; + readonly user?: FigmaUser; +}; -export async function checkAuth( +export async function getAuthMe( atlassianUserId: string, -): Promise> { - return await axiosRest.get('/admin/auth/checkAuth', { +): Promise> { + return await axiosRest.get('/admin/auth/me', { params: { userId: atlassianUserId }, }); } diff --git a/admin/src/app.tsx b/admin/src/app.tsx index 39c733a9..2a0ea7b8 100644 --- a/admin/src/app.tsx +++ b/admin/src/app.tsx @@ -1,7 +1,7 @@ import Spinner from '@atlaskit/spinner'; import { useQuery } from '@tanstack/react-query'; -import { checkAuth, getAtlassianAccountId } from './api'; +import { getAtlassianAccountId, getAuthMe } from './api'; import { Page } from './components'; import { AuthPage, TeamsPage } from './pages'; @@ -13,15 +13,15 @@ export function App() { const atlassianAccountId = atlassianAccountIdQuery.data; - const checkAuthQuery = useQuery({ - queryKey: ['checkAuth', atlassianAccountId], + const getAuthMeQuery = useQuery({ + queryKey: ['authMe', atlassianAccountId], queryFn: async () => { - return (await checkAuth(atlassianAccountId ?? '')).data; + return (await getAuthMe(atlassianAccountId ?? '')).data; }, enabled: atlassianAccountId != null, }); - if (atlassianAccountIdQuery.isPending || checkAuthQuery.isPending) { + if (atlassianAccountIdQuery.isPending || getAuthMeQuery.isPending) { return ( @@ -34,25 +34,21 @@ export function App() { return null; } - if (checkAuthQuery.isError) { + if (getAuthMeQuery.isError) { // TODO: render an error screen when our service is down or unavailable return null; } - const checkAuthResponse = checkAuthQuery.data; + const { authorizationEndpoint, user } = getAuthMeQuery.data; - if (!checkAuthResponse.authorized) { - return ( - - ); + if (!user) { + return ; } return ( ); } diff --git a/src/usecases/check-user-figma-auth-use-case.ts b/src/usecases/check-user-figma-auth-use-case.ts new file mode 100644 index 00000000..2e109541 --- /dev/null +++ b/src/usecases/check-user-figma-auth-use-case.ts @@ -0,0 +1,15 @@ +import type { ConnectInstallation } from '../domain/entities'; +import { figmaService } from '../infrastructure/figma'; +export const checkUserFigmaAuthUseCase = { + execute: async ( + atlassianUserId: string, + connectInstallation: ConnectInstallation, + ): Promise => { + const currentUser = await figmaService.fetchCurrentUser({ + atlassianUserId, + connectInstallationId: connectInstallation.id, + }); + + return currentUser != null; + }, +}; diff --git a/src/usecases/current-figma-user-use-case.ts b/src/usecases/get-current-figma-user-use-case.ts similarity index 89% rename from src/usecases/current-figma-user-use-case.ts rename to src/usecases/get-current-figma-user-use-case.ts index 49528f29..23b61a15 100644 --- a/src/usecases/current-figma-user-use-case.ts +++ b/src/usecases/get-current-figma-user-use-case.ts @@ -1,7 +1,7 @@ import type { ConnectInstallation, FigmaUser } from '../domain/entities'; import { figmaService } from '../infrastructure/figma'; -export const currentFigmaUserUseCase = { +export const getCurrentFigmaUserUseCase = { execute: async ( atlassianUserId: string, connectInstallation: ConnectInstallation, diff --git a/src/usecases/index.ts b/src/usecases/index.ts index 16266e81..d47cbe1d 100644 --- a/src/usecases/index.ts +++ b/src/usecases/index.ts @@ -1,9 +1,10 @@ -export * from './current-figma-user-use-case'; export * from './associate-entity-use-case'; +export * from './check-user-figma-auth-use-case'; export * from './connect-figma-team-use-case'; export * from './disassociate-entity-use-case'; export * from './disconnect-figma-team-use-case'; export * from './errors'; +export * from './get-current-figma-user-use-case'; export * from './handle-figma-authorization-response-use-case'; export * from './handle-figma-file-update-event-use-case'; export * from './installed-use-case'; diff --git a/src/web/routes/admin/auth/auth-router.ts b/src/web/routes/admin/auth/auth-router.ts index 091620aa..224c0e54 100644 --- a/src/web/routes/admin/auth/auth-router.ts +++ b/src/web/routes/admin/auth/auth-router.ts @@ -1,10 +1,10 @@ import type { NextFunction } from 'express'; import { Router } from 'express'; -import type { CheckAuthRequest, CheckAuthResponse } from './types'; +import type { MeRequest, MeResponse } from './types'; import { figmaAuthService } from '../../../../infrastructure/figma'; -import { currentFigmaUserUseCase } from '../../../../usecases'; +import { getCurrentFigmaUserUseCase } from '../../../../usecases'; export const authRouter = Router(); @@ -12,11 +12,11 @@ export const authRouter = Router(); * Checks whether the given Atlassian admin is authorized to call Figma API. */ authRouter.get( - ['/checkAuth'], - function (req: CheckAuthRequest, res: CheckAuthResponse, next: NextFunction) { + ['/me'], + function (req: MeRequest, res: MeResponse, next: NextFunction) { const { connectInstallation, atlassianUserId } = res.locals; - currentFigmaUserUseCase + getCurrentFigmaUserUseCase .execute(atlassianUserId, connectInstallation) .then((currentUser) => { const authorizationEndpoint = @@ -28,15 +28,13 @@ authRouter.get( if (currentUser) { return res.send({ - authorized: true, user: { email: currentUser.email }, - grant: { authorizationEndpoint }, + authorizationEndpoint, }); } return res.send({ - authorized: false, - grant: { authorizationEndpoint }, + authorizationEndpoint, }); }) .catch((error) => next(error)); diff --git a/src/web/routes/admin/auth/integration.test.ts b/src/web/routes/admin/auth/integration.test.ts index 5388c184..359f9b2c 100644 --- a/src/web/routes/admin/auth/integration.test.ts +++ b/src/web/routes/admin/auth/integration.test.ts @@ -29,10 +29,10 @@ const FIGMA_OAUTH_API_BASE_URL = getConfig().figma.oauth2.authorizationServerBaseUrl; const FIGMA_OAUTH_REFRESH_TOKEN_ENDPOINT = '/api/oauth/refresh'; -const CHECK_AUTH_ENDPOINT = '/admin/auth/checkAuth'; +const AUTH_ME_ENDPOINT = '/admin/auth/me'; describe('/admin/auth', () => { - describe('/checkAuth', () => { + describe('/me', () => { const REFRESH_TOKEN = uuidv4(); const REFRESH_TOKEN_QUERY_PARAMS = generateRefreshOAuth2TokenQueryParams({ client_id: getConfig().figma.oauth2.clientId, @@ -69,16 +69,13 @@ describe('/admin/auth', () => { mockFigmaMeEndpoint({ baseUrl: getConfig().figma.apiBaseUrl }); return request(app) - .get(CHECK_AUTH_ENDPOINT) + .get(AUTH_ME_ENDPOINT) .set('Authorization', `JWT ${jwt}`) .expect(HttpStatusCode.Ok) .then((response) => { expect(response.body).toStrictEqual({ - authorized: true, user: { email: expect.any(String) }, - grant: { - authorizationEndpoint: expect.any(String), - }, + authorizationEndpoint: expect.any(String), }); }); }); @@ -118,16 +115,13 @@ describe('/admin/auth', () => { mockFigmaMeEndpoint({ baseUrl: getConfig().figma.apiBaseUrl }); await request(app) - .get(CHECK_AUTH_ENDPOINT) + .get(AUTH_ME_ENDPOINT) .set('Authorization', `JWT ${jwt}`) .expect(HttpStatusCode.Ok) .then((response) => { expect(response.body).toStrictEqual({ - authorized: true, user: { email: expect.any(String) }, - grant: { - authorizationEndpoint: expect.any(String), - }, + authorizationEndpoint: expect.any(String), }); }); @@ -163,15 +157,12 @@ describe('/admin/auth', () => { }); return request(app) - .get(CHECK_AUTH_ENDPOINT) + .get(AUTH_ME_ENDPOINT) .set('Authorization', `JWT ${jwt}`) .expect(HttpStatusCode.Ok) .then((response) => { expect(response.body).toStrictEqual({ - authorized: false, - grant: { - authorizationEndpoint: expect.any(String), - }, + authorizationEndpoint: expect.any(String), }); }); }); @@ -209,15 +200,12 @@ describe('/admin/auth', () => { .reply(HttpStatusCode.InternalServerError); return request(app) - .get(CHECK_AUTH_ENDPOINT) + .get(AUTH_ME_ENDPOINT) .set('Authorization', `JWT ${jwt}`) .expect(HttpStatusCode.Ok) .then((response) => { expect(response.body).toStrictEqual({ - authorized: false, - grant: { - authorizationEndpoint: expect.any(String), - }, + authorizationEndpoint: expect.any(String), }); }); }); @@ -254,15 +242,12 @@ describe('/admin/auth', () => { }); return request(app) - .get(CHECK_AUTH_ENDPOINT) + .get(AUTH_ME_ENDPOINT) .set('Authorization', `JWT ${jwt}`) .expect(HttpStatusCode.Ok) .then((response) => { expect(response.body).toStrictEqual({ - authorized: false, - grant: { - authorizationEndpoint: expect.any(String), - }, + authorizationEndpoint: expect.any(String), }); }); }); @@ -289,7 +274,7 @@ describe('/admin/auth', () => { }); return request(app) - .get(CHECK_AUTH_ENDPOINT) + .get(AUTH_ME_ENDPOINT) .query({ userId: atlassianUserId, }) @@ -298,7 +283,7 @@ describe('/admin/auth', () => { .then((response) => { const authorizationEndpoint = new URL( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access - response.body.grant.authorizationEndpoint, + response.body.authorizationEndpoint, ); expect(authorizationEndpoint.origin).toBe( @@ -354,7 +339,7 @@ describe('/admin/auth', () => { mockFigmaMeEndpoint({ baseUrl: getConfig().figma.apiBaseUrl }); return request(app) - .get(CHECK_AUTH_ENDPOINT) + .get(AUTH_ME_ENDPOINT) .set('Authorization', `JWT ${jwt}`) .expect(HttpStatusCode.Unauthorized); }); diff --git a/src/web/routes/admin/auth/types.ts b/src/web/routes/admin/auth/types.ts index 48bb4af0..716bb361 100644 --- a/src/web/routes/admin/auth/types.ts +++ b/src/web/routes/admin/auth/types.ts @@ -2,32 +2,26 @@ import type { Request, Response } from 'express'; import type { ConnectInstallation } from '../../../../domain/entities'; -export type CheckAuthQueryParameters = { readonly userId: string }; +export type MeQueryParameters = { readonly userId: string }; -export type CheckAuthResponseBody = { - readonly authorized: boolean; - readonly grant: { - readonly authorizationEndpoint: string; - }; +export type MeResponseBody = { readonly user?: { readonly email: string; }; + readonly authorizationEndpoint: string; }; -type CheckAuthRequestLocals = { +type MeRequestLocals = { readonly connectInstallation: ConnectInstallation; readonly atlassianUserId: string; }; -export type CheckAuthRequest = Request< +export type MeRequest = Request< Record, - CheckAuthResponseBody, + MeResponseBody, never, - CheckAuthQueryParameters, - CheckAuthRequestLocals + MeQueryParameters, + MeRequestLocals >; -export type CheckAuthResponse = Response< - CheckAuthResponseBody, - CheckAuthRequestLocals ->; +export type MeResponse = Response; diff --git a/src/web/routes/auth/auth-router.ts b/src/web/routes/auth/auth-router.ts index 9a64a013..6defe9c0 100644 --- a/src/web/routes/auth/auth-router.ts +++ b/src/web/routes/auth/auth-router.ts @@ -5,7 +5,7 @@ import { CHECK_AUTH_REQUEST_SCHEMA } from './schemas'; import type { CheckAuthRequest, CheckAuthResponse } from './types'; import { figmaAuthService } from '../../../infrastructure/figma'; -import { currentFigmaUserUseCase } from '../../../usecases'; +import { checkUserFigmaAuthUseCase } from '../../../usecases'; import { requestSchemaValidationMiddleware } from '../../middleware'; import { jiraServerSymmetricJwtAuthMiddleware } from '../../middleware/jira'; @@ -23,10 +23,9 @@ authRouter.get( const { connectInstallation } = res.locals; const atlassianUserId = req.query.userId; - currentFigmaUserUseCase + checkUserFigmaAuthUseCase .execute(atlassianUserId, connectInstallation) - .then((currentUser) => { - const authorized = currentUser != null; + .then((authorized) => { if (authorized) { return res.send({ type: '3LO', authorized }); }