From a07397269d46e357ad824e5c54e1b052c48d41c4 Mon Sep 17 00:00:00 2001 From: Anup Cowkur Date: Mon, 20 Nov 2023 15:48:36 +0530 Subject: [PATCH 1/2] feat(webapp): use supabase auth token to make API calls --- measure-web-app/app/[teamId]/layout.tsx | 14 +- .../app/[teamId]/overview/page.tsx | 20 +- .../app/components/metrics_overview.tsx | 15 +- measure-web-app/app/components/user_flow.tsx | 17 +- measure-web-app/app/utils/auth_utils.tsx | 36 +++ measure-web-app/utils/supabase/server.ts | 4 +- package-lock.json | 254 +++++++++++++++++- package.json | 3 + 8 files changed, 335 insertions(+), 28 deletions(-) create mode 100644 measure-web-app/app/utils/auth_utils.tsx diff --git a/measure-web-app/app/[teamId]/layout.tsx b/measure-web-app/app/[teamId]/layout.tsx index 749b38434..28e9d8914 100644 --- a/measure-web-app/app/[teamId]/layout.tsx +++ b/measure-web-app/app/[teamId]/layout.tsx @@ -5,13 +5,13 @@ import React, { useState, useEffect } from 'react'; import { usePathname } from 'next/navigation'; import { useRouter } from 'next/navigation'; import TeamSwitcher from "../components/team_switcher"; +import { getAccessTokenOrRedirectToAuth, logoutIfAuthError } from "../utils/auth_utils"; export default function DashboardLayout({ children, }: { children: React.ReactNode }) { - enum TeamsApiStatus { Loading, Success, @@ -44,17 +44,17 @@ export default function DashboardLayout({ ]; const [teamsApiStatus, setTeamsApiStatus] = useState(TeamsApiStatus.Loading); - const [authToken, setAuthToken] = useState("abcde123"); const [teams, setTeams] = useState(emptyTeams); const [selectedTeam, setSelectedTeam] = useState(teams[0].id) const pathName = usePathname(); const router = useRouter(); - const getTeams = async (authToken:string) => { + const getTeams = async () => { setTeamsApiStatus(TeamsApiStatus.Loading) - const origin = "https://frosty-fog-7165.fly.dev" + const authToken = await getAccessTokenOrRedirectToAuth(router) + const origin = process.env.NEXT_PUBLIC_API_BASE_URL const opts = { headers: { "Authorization": `Bearer ${authToken}` @@ -62,9 +62,9 @@ export default function DashboardLayout({ }; const res = await fetch(`${origin}/teams`, opts); - if(!res.ok) { setTeamsApiStatus(TeamsApiStatus.Error) + logoutIfAuthError(router, res) return } @@ -75,8 +75,8 @@ export default function DashboardLayout({ } useEffect(() => { - getTeams(authToken) - }, [authToken]); + getTeams() + }, []); const onTeamChanged = (item:string) => { const selectedTeamId = teams.find((e) => e.name === item)!.id diff --git a/measure-web-app/app/[teamId]/overview/page.tsx b/measure-web-app/app/[teamId]/overview/page.tsx index 41b99af5d..25636bad7 100644 --- a/measure-web-app/app/[teamId]/overview/page.tsx +++ b/measure-web-app/app/[teamId]/overview/page.tsx @@ -5,8 +5,12 @@ import Dropdown from "@/app/components/dropdown"; import FilterPill from "@/app/components/filter_pill"; import UserFlow from "@/app/components/user_flow"; import MetricsOverview from '@/app/components/metrics_overview'; +import { getAccessTokenOrRedirectToAuth, logoutIfAuthError } from '@/app/utils/auth_utils'; +import { useRouter } from 'next/navigation'; export default function Overview({ params }: { params: { teamId: string } }) { + const router = useRouter() + enum AppsApiStatus { Loading, Success, @@ -43,9 +47,10 @@ export default function Overview({ params }: { params: { teamId: string } }) { setFormattedEndDate(new Date(endDate).toLocaleDateString()); }, [startDate, endDate]); - const getApps = async (authToken:string, teamId:string, ) => { + const getApps = async (teamId:string, ) => { setAppsApiStatus(AppsApiStatus.Loading) + const authToken = await getAccessTokenOrRedirectToAuth(router) const origin = process.env.NEXT_PUBLIC_API_BASE_URL const opts = { headers: { @@ -56,6 +61,7 @@ export default function Overview({ params }: { params: { teamId: string } }) { const res = await fetch(`${origin}/teams/${teamId}/apps`, opts); if(!res.ok) { setAppsApiStatus(AppsApiStatus.Error) + logoutIfAuthError(router, res) return } const data = await res.json() @@ -66,12 +72,13 @@ export default function Overview({ params }: { params: { teamId: string } }) { } useEffect(() => { - getApps("abcde123", params.teamId) + getApps(params.teamId) }, []); - const getFilters = async (authToken:string, appId:string, ) => { + const getFilters = async (appId:string, ) => { setFiltersApiStatus(FiltersApiStatus.Loading) + const authToken = await getAccessTokenOrRedirectToAuth(router) const origin = process.env.NEXT_PUBLIC_API_BASE_URL const opts = { headers: { @@ -81,6 +88,7 @@ export default function Overview({ params }: { params: { teamId: string } }) { const res = await fetch(`${origin}/apps/${appId}/filters`, opts); if(!res.ok) { + logoutIfAuthError(router, res) setFiltersApiStatus(FiltersApiStatus.Error) return } @@ -92,7 +100,7 @@ export default function Overview({ params }: { params: { teamId: string } }) { } useEffect(() => { - getFilters("abcde123", selectedApp) + getFilters(selectedApp) }, [selectedApp]); return ( @@ -121,9 +129,9 @@ export default function Overview({ params }: { params: { teamId: string } }) {
{appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Error &&

Error fetching filters, please refresh page or select a different app to try again

} - {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Success && } + {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Success && }
- {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Success && } + {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Success && }
) } diff --git a/measure-web-app/app/components/metrics_overview.tsx b/measure-web-app/app/components/metrics_overview.tsx index b4ad4d402..c31e423c9 100644 --- a/measure-web-app/app/components/metrics_overview.tsx +++ b/measure-web-app/app/components/metrics_overview.tsx @@ -5,9 +5,10 @@ import InfoCircleAppAdoption from './info_circle_app_adoption'; import InfoCircleAppSize from './info_circle_app_size'; import InfoCircleExceptionRate from './info_circle_exception_rate'; import InfoCircleAppStartTime from './info_circle_app_start_time'; +import { getAccessTokenOrRedirectToAuth, logoutIfAuthError } from '@/app/utils/auth_utils'; +import { useRouter } from 'next/navigation'; interface MetricsOverviewProps { - authToken: string, appId:string, startDate:string, endDate:string, @@ -20,7 +21,7 @@ export enum MetricsApiStatus { Error } -const MetricsOverview: React.FC = ({ authToken, appId, startDate, endDate, appVersion }) => { +const MetricsOverview: React.FC = ({ appId, startDate, endDate, appVersion }) => { const emptyData = { "adoption": { @@ -73,9 +74,12 @@ const MetricsOverview: React.FC = ({ authToken, appId, sta const [data, setData] = useState(emptyData); const [metricsApiStatus, setMetricsApiStatus] = useState(MetricsApiStatus.Loading); - const getData = async (authToken:string, appId:string, startDate:string, endDate:string, appVersion:string) => { + const router = useRouter() + + const getData = async (appId:string, startDate:string, endDate:string, appVersion:string) => { setMetricsApiStatus(MetricsApiStatus.Loading) + const authToken = await getAccessTokenOrRedirectToAuth(router) const origin = process.env.NEXT_PUBLIC_API_BASE_URL const opts = { headers: { @@ -89,6 +93,7 @@ const MetricsOverview: React.FC = ({ authToken, appId, sta if(!res.ok) { setMetricsApiStatus(MetricsApiStatus.Error) + logoutIfAuthError(router, res) return } @@ -97,8 +102,8 @@ const MetricsOverview: React.FC = ({ authToken, appId, sta } useEffect(() => { - getData(authToken, appId, startDate, endDate, appVersion) - }, [authToken, appId, startDate, endDate, appVersion]); + getData(appId, startDate, endDate, appVersion) + }, [appId, startDate, endDate, appVersion]); return (
diff --git a/measure-web-app/app/components/user_flow.tsx b/measure-web-app/app/components/user_flow.tsx index 1de677fe3..7110e68f7 100644 --- a/measure-web-app/app/components/user_flow.tsx +++ b/measure-web-app/app/components/user_flow.tsx @@ -2,16 +2,17 @@ import React, { useState, useEffect } from 'react'; import { ResponsiveSankey } from '@nivo/sankey' +import { getAccessTokenOrRedirectToAuth, logoutIfAuthError } from '@/app/utils/auth_utils'; +import { useRouter } from 'next/navigation'; interface UserFlowProps { - authToken: string, appId:string, startDate:string, endDate:string, appVersion:string, } -const UserFlow: React.FC = ({ authToken, appId, startDate, endDate, appVersion }) => { +const UserFlow: React.FC = ({ appId, startDate, endDate, appVersion }) => { enum JourneyApiStatus { Loading, Success, @@ -38,9 +39,12 @@ const UserFlow: React.FC = ({ authToken, appId, startDate, endDat const [journeyApiStatus, setJourneyApiStatus] = useState(JourneyApiStatus.Loading); const [data, setData] = useState(emptyData); - const getData = async (authToken:string, appId:string, startDate:string, endDate:string, appVersion:string) => { + const router = useRouter() + + const getData = async (appId:string, startDate:string, endDate:string, appVersion:string) => { setJourneyApiStatus(JourneyApiStatus.Loading) + const authToken = await getAccessTokenOrRedirectToAuth(router) const origin = process.env.NEXT_PUBLIC_API_BASE_URL const opts = { headers: { @@ -51,9 +55,10 @@ const UserFlow: React.FC = ({ authToken, appId, startDate, endDat const serverFormattedStartDate = new Date(startDate).toISOString() const serverFormattedEndDate = new Date(endDate).toISOString() const res = await fetch(`${origin}/apps/${appId}/journey?version=${appVersion}&from=${serverFormattedStartDate}&to=${serverFormattedEndDate}`, opts); - + if(!res.ok) { setJourneyApiStatus(JourneyApiStatus.Error) + logoutIfAuthError(router, res) return } @@ -62,8 +67,8 @@ const UserFlow: React.FC = ({ authToken, appId, startDate, endDat } useEffect(() => { - getData(authToken, appId, startDate, endDate, appVersion) - }, [authToken, appId, startDate, endDate, appVersion]); + getData(appId, startDate, endDate, appVersion) + }, [appId, startDate, endDate, appVersion]); return (
diff --git a/measure-web-app/app/utils/auth_utils.tsx b/measure-web-app/app/utils/auth_utils.tsx new file mode 100644 index 000000000..3dce33521 --- /dev/null +++ b/measure-web-app/app/utils/auth_utils.tsx @@ -0,0 +1,36 @@ +import { createClient } from '@supabase/supabase-js' +import { AppRouterInstance } from 'next/dist/shared/lib/app-router-context'; + +// Utility function to try and access current access token. If session retrieval +// fails for any reason, logout will be called and the user will be redirected to auth +export async function getAccessTokenOrRedirectToAuth(router: AppRouterInstance) { + const supabase = createClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! + ) + + const { data: {session}, error } = await supabase.auth.getSession() + + if(error) { + await supabase.auth.signOut() + router.push('/auth/logout') + return null + } + + return session!.access_token; + } + + // Utility function to check if API reponse has an authentication error. + // If it does, logout will be called and the user will be redirected to auth + export async function logoutIfAuthError(router: AppRouterInstance, res: Response) { + const supabase = createClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! + ) + + if(res.status === 401) { + await supabase.auth.signOut() + router.push('/auth/logout') + return + } + } \ No newline at end of file diff --git a/measure-web-app/utils/supabase/server.ts b/measure-web-app/utils/supabase/server.ts index 2fbf5bfc7..39e1aea73 100644 --- a/measure-web-app/utils/supabase/server.ts +++ b/measure-web-app/utils/supabase/server.ts @@ -1,10 +1,10 @@ -import { createServerClient, type CookieOptions } from '@supabase/ssr' +import { createBrowserClient, type CookieOptions } from '@supabase/ssr' import { cookies } from 'next/headers' export const createClient = () => { const cookieStore = cookies() - return createServerClient( + return createBrowserClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { diff --git a/package-lock.json b/package-lock.json index b4e315927..459bff658 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,9 @@ "packages": { "": { "name": "measure.sh", + "dependencies": { + "@supabase/supabase-js": "^2.38.4" + }, "devDependencies": { "@commitlint/cli": "^17.7.1", "@commitlint/config-conventional": "^17.7.0", @@ -454,6 +457,73 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@supabase/functions-js": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.1.5.tgz", + "integrity": "sha512-BNzC5XhCzzCaggJ8s53DP+WeHHGT/NfTsx2wUSSGKR2/ikLFQTBCDzMvGz/PxYMqRko/LwncQtKXGOYp1PkPaw==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/gotrue-js": { + "version": "2.57.0", + "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.57.0.tgz", + "integrity": "sha512-/CcAW40aPKgp9/w9WgXVUQFg1AOdvFR687ONOMjASPBuC6FsNbKlcXp4pc+rwKNtxyxDkBbR+x7zj/8g00r/Og==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/node-fetch": { + "version": "2.6.15", + "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.8.6.tgz", + "integrity": "sha512-iiEgF6o/pBumdFe/A2HSG/xx3L6ap7OO3IpTB2hsamNiH/gWb8ru4Z8bdwZjN4sQQttxgsIgZVMsNLkTOCOQhw==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.8.4.tgz", + "integrity": "sha512-5C9slLTGikHnYmAnIBOaPogAgbcNY68vnIyE6GpqIKjHElVb6LIi4clwNcjHSj4z6szuvvzj8T/+ePEgGEGekw==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14", + "@types/phoenix": "^1.5.4", + "@types/websocket": "^1.0.3", + "websocket": "^1.0.34" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.5.4.tgz", + "integrity": "sha512-yspHD19I9uQUgfTh0J94+/r/g6hnhdQmw6Y7OWqr/EbnL6uvicGV1i1UDkkmeUHqfF9Mbt2sLtuxRycYyKv2ew==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.38.4", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.38.4.tgz", + "integrity": "sha512-bYwxm/GosvRqOMIv6YP7qUTZWi/trgHtDWUEZDEmyRHW24d0JYIb1GOt6RaO2hsWlecn88DAJIpjoNbprocgRA==", + "dependencies": { + "@supabase/functions-js": "^2.1.5", + "@supabase/gotrue-js": "^2.56.0", + "@supabase/node-fetch": "^2.6.14", + "@supabase/postgrest-js": "^1.8.5", + "@supabase/realtime-js": "^2.8.4", + "@supabase/storage-js": "^2.5.4" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -487,8 +557,7 @@ "node_modules/@types/node": { "version": "20.4.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.7.tgz", - "integrity": "sha512-bUBrPjEry2QUTsnuEjzjbS7voGWCc30W0qzgMf90GPeDGFRakvrz47ju+oqDAKCXLUCe39u57/ORMl/O/04/9g==", - "dev": true + "integrity": "sha512-bUBrPjEry2QUTsnuEjzjbS7voGWCc30W0qzgMf90GPeDGFRakvrz47ju+oqDAKCXLUCe39u57/ORMl/O/04/9g==" }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -496,6 +565,19 @@ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, + "node_modules/@types/phoenix": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.4.tgz", + "integrity": "sha512-B34A7uot1Cv0XtaHRYDATltAdKx0BvVKNgYNqE4WjtPUa4VQJM7kxeXcVKaH+KS+kCmZ+6w+QaUdcljiheiBJA==" + }, + "node_modules/@types/websocket": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.9.tgz", + "integrity": "sha512-xrMBdqdKdlE+7L9Wg2PQblIkZGSgiMlEoP6UAaYKMHbbxqCJ6PV/pTZ2RcMcSSERurU2TtGbmO4lqpFOJd01ww==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -584,6 +666,18 @@ "node": ">=0.10.0" } }, + "node_modules/bufferutil": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", + "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -780,6 +874,15 @@ "node": ">= 8" } }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "node_modules/dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", @@ -789,6 +892,14 @@ "node": ">=8" } }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -859,6 +970,39 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -900,6 +1044,19 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1180,6 +1337,11 @@ "node": ">=0.10.0" } }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1451,6 +1613,26 @@ "node": ">= 6" } }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node_modules/node-gyp-build": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.7.0.tgz", + "integrity": "sha512-PbZERfeFdrHQOOXiAKOY0VPbykZy90ndPKk0d+CFDegTKmWp1VgOTz2xACVbr1BjCWxrQp68CXtvNsveFhqDJg==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", @@ -2032,6 +2214,11 @@ "readable-stream": "3" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", @@ -2084,6 +2271,11 @@ } } }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, "node_modules/type-fest": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", @@ -2096,6 +2288,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, "node_modules/typescript": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", @@ -2127,6 +2327,18 @@ "punycode": "^2.1.0" } }, + "node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -2149,6 +2361,36 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/websocket": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", + "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", + "dependencies": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2190,6 +2432,14 @@ "node": ">=10" } }, + "node_modules/yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==", + "engines": { + "node": ">=0.10.32" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 3f6073599..b47f7d05f 100644 --- a/package.json +++ b/package.json @@ -8,5 +8,8 @@ }, "scripts": { "prepare": "husky install" + }, + "dependencies": { + "@supabase/supabase-js": "^2.38.4" } } From f8a65855921026604d30cd3ee16562a0dbf9e139 Mon Sep 17 00:00:00 2001 From: Anup Cowkur Date: Tue, 21 Nov 2023 13:18:45 +0530 Subject: [PATCH 2/2] fix(backend): change teamId to id to match client response expectation --- measure-backend/measure-go/users.go | 2 +- measure-web-app/app/auth/callback/github/route.ts | 4 ++-- measure-web-app/app/auth/callback/google/route.ts | 4 ++-- measure-web-app/app/auth/callback/route.ts | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/measure-backend/measure-go/users.go b/measure-backend/measure-go/users.go index e3a3be79a..083833fa7 100644 --- a/measure-backend/measure-go/users.go +++ b/measure-backend/measure-go/users.go @@ -29,7 +29,7 @@ func (u *User) getTeams() ([]map[string]string, error) { return nil, err } - team["teamId"] = teamId + team["id"] = teamId team["name"] = name team["role"] = role teams = append(teams, team) diff --git a/measure-web-app/app/auth/callback/github/route.ts b/measure-web-app/app/auth/callback/github/route.ts index b2817417c..b2fe10bcb 100644 --- a/measure-web-app/app/auth/callback/github/route.ts +++ b/measure-web-app/app/auth/callback/github/route.ts @@ -39,7 +39,7 @@ export async function GET(request: Request) { } type Team = { - teamId: string, + id: string, name: string, role: string, } @@ -51,5 +51,5 @@ export async function GET(request: Request) { return NextResponse.redirect(errRedirectUrl, { status: 302 }) } - return NextResponse.redirect(`${requestUrl.origin}/${ownTeam.teamId}/overview`, { status: 302 }) + return NextResponse.redirect(`${requestUrl.origin}/${ownTeam.id}/overview`, { status: 302 }) } \ No newline at end of file diff --git a/measure-web-app/app/auth/callback/google/route.ts b/measure-web-app/app/auth/callback/google/route.ts index 3e7999cc6..8fb604522 100644 --- a/measure-web-app/app/auth/callback/google/route.ts +++ b/measure-web-app/app/auth/callback/google/route.ts @@ -52,7 +52,7 @@ export async function POST(request: Request) { } type Team = { - teamId: string, + id: string, name: string, role: string, } @@ -64,5 +64,5 @@ export async function POST(request: Request) { return NextResponse.redirect(errRedirectUrl, { status: 302 }) } - return NextResponse.redirect(`${requestUrl.origin}/${ownTeam.teamId}/overview`, { status: 302 }) + return NextResponse.redirect(`${requestUrl.origin}/${ownTeam.id}/overview`, { status: 302 }) } \ No newline at end of file diff --git a/measure-web-app/app/auth/callback/route.ts b/measure-web-app/app/auth/callback/route.ts index b0fd5f21e..aaf470e27 100644 --- a/measure-web-app/app/auth/callback/route.ts +++ b/measure-web-app/app/auth/callback/route.ts @@ -43,7 +43,7 @@ export async function GET(request: Request) { } type Team = { - teamId: string, + id: string, name: string, role: string, } @@ -55,5 +55,5 @@ export async function GET(request: Request) { return NextResponse.redirect(errRedirectUrl, { status: 302 }) } - return NextResponse.redirect(`${requestUrl.origin}/${ownTeam.teamId}/overview`, { status: 302 }) + return NextResponse.redirect(`${requestUrl.origin}/${ownTeam.id}/overview`, { status: 302 }) } \ No newline at end of file