fix api auth

This commit is contained in:
Sara
2023-11-02 16:03:10 +01:00
parent 0d9f66c097
commit e65efb841f
12 changed files with 118 additions and 99 deletions

View File

@@ -1,43 +1,17 @@
"use client"; "use client";
import React, { useState, useEffect } from "react"; import React, { useState } from "react";
import getApi from "../../lib/getApi";
import { import { GetTranscript } from "../../api";
PageGetTranscript,
GetTranscript,
GetTranscriptFromJSON,
} from "../../api";
import { Title } from "../../lib/textComponents"; import { Title } from "../../lib/textComponents";
import Pagination from "./pagination"; import Pagination from "./pagination";
import Link from "next/link"; import Link from "next/link";
import { useFiefIsAuthenticated } from "@fief/fief/nextjs/react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faGear } from "@fortawesome/free-solid-svg-icons"; import { faGear } from "@fortawesome/free-solid-svg-icons";
import useTranscriptList from "../transcripts/useTranscriptList";
export default function TranscriptBrowser() { export default function TranscriptBrowser() {
const api = getApi();
const [results, setResults] = useState<PageGetTranscript | null>(null);
const [page, setPage] = useState<number>(1); const [page, setPage] = useState<number>(1);
const [isLoading, setIsLoading] = useState<boolean>(false); const { loading, response } = useTranscriptList(page);
const isAuthenticated = useFiefIsAuthenticated();
useEffect(() => {
if (!isAuthenticated) return;
setIsLoading(true);
api
.v1TranscriptsList({ page })
.then((response) => {
// issue with API layer, conversion for items is not happening
response.items = response.items.map((item) =>
GetTranscriptFromJSON(item),
);
setResults(response);
setIsLoading(false);
})
.catch(() => {
setResults(null);
setIsLoading(false);
});
}, [page, isAuthenticated]);
return ( return (
<div> <div>
@@ -52,12 +26,12 @@ export default function TranscriptBrowser() {
<Pagination <Pagination
page={page} page={page}
setPage={setPage} setPage={setPage}
total={results?.total || 0} total={response?.total || 0}
size={results?.size || 0} size={response?.size || 0}
/> />
</div> </div>
{isLoading && ( {loading && (
<div className="full-screen flex flex-col items-center justify-center"> <div className="full-screen flex flex-col items-center justify-center">
<FontAwesomeIcon <FontAwesomeIcon
icon={faGear} icon={faGear}
@@ -65,7 +39,7 @@ export default function TranscriptBrowser() {
/> />
</div> </div>
)} )}
{!isLoading && !results ? ( {!loading && !response && (
<div className="text-gray-500"> <div className="text-gray-500">
No transcripts found, but you can&nbsp; No transcripts found, but you can&nbsp;
<Link href="/transcripts/new" className="underline"> <Link href="/transcripts/new" className="underline">
@@ -73,12 +47,10 @@ export default function TranscriptBrowser() {
</Link> </Link>
&nbsp;to get started. &nbsp;to get started.
</div> </div>
) : (
<></>
)} )}
<div /** center and max 900px wide */ className="mx-auto max-w-[900px]"> <div /** center and max 900px wide */ className="mx-auto max-w-[900px]">
<div className="grid grid-cols-1 gap-2 lg:gap-4 h-full"> <div className="grid grid-cols-1 gap-2 lg:gap-4 h-full">
{results?.items.map((item: GetTranscript) => ( {response?.items.map((item: GetTranscript) => (
<div <div
key={item.id} key={item.id}
className="flex flex-col bg-blue-400/20 rounded-lg md:rounded-xl p-2 md:px-4" className="flex flex-col bg-blue-400/20 rounded-lg md:rounded-xl p-2 md:px-4"

View File

@@ -1,20 +1,17 @@
"use client"; "use client";
import Modal from "../modal"; import Modal from "../modal";
import getApi from "../../../lib/getApi";
import useTranscript from "../useTranscript"; import useTranscript from "../useTranscript";
import useTopics from "../useTopics"; import useTopics from "../useTopics";
import useWaveform from "../useWaveform"; import useWaveform from "../useWaveform";
import { TopicList } from "../topicList"; import { TopicList } from "../topicList";
import Recorder from "../recorder"; import Recorder from "../recorder";
import { Topic } from "../webSocketTypes"; import { Topic } from "../webSocketTypes";
import React, { useEffect, useState } from "react"; import React, { useState } from "react";
import "../../../styles/button.css"; import "../../../styles/button.css";
import FinalSummary from "../finalSummary"; import FinalSummary from "../finalSummary";
import ShareLink from "../shareLink"; import ShareLink from "../shareLink";
import QRCode from "react-qr-code"; import QRCode from "react-qr-code";
import TranscriptTitle from "../transcriptTitle"; import TranscriptTitle from "../transcriptTitle";
import { useFiefIsAuthenticated } from "@fief/fief/nextjs/react";
import { featureEnabled } from "../../domainContext";
type TranscriptDetails = { type TranscriptDetails = {
params: { params: {
@@ -22,20 +19,15 @@ type TranscriptDetails = {
}; };
}; };
export default function TranscriptDetails(details: TranscriptDetails) { const protectedPath = true;
const isAuthenticated = useFiefIsAuthenticated();
const api = getApi();
const [transcriptId, setTranscriptId] = useState<string>("");
const transcript = useTranscript(api, transcriptId);
const topics = useTopics(api, transcriptId);
const waveform = useWaveform(api, transcriptId);
const useActiveTopic = useState<Topic | null>(null);
const requireLogin = featureEnabled("requireLogin");
useEffect(() => { export default function TranscriptDetails(details: TranscriptDetails) {
if (requireLogin && !isAuthenticated) return; const transcriptId = details.params.transcriptId;
setTranscriptId(details.params.transcriptId);
}, [api]); const transcript = useTranscript(protectedPath, transcriptId);
const topics = useTopics(protectedPath, transcriptId);
const waveform = useWaveform(protectedPath, transcriptId);
const useActiveTopic = useState<Topic | null>(null);
if (transcript?.error /** || topics?.error || waveform?.error **/) { if (transcript?.error /** || topics?.error || waveform?.error **/) {
return ( return (

View File

@@ -36,9 +36,8 @@ const TranscriptRecord = (details: TranscriptDetails) => {
} }
}, []); }, []);
const api = getApi(); const transcript = useTranscript(false, details.params.transcriptId);
const transcript = useTranscript(api, details.params.transcriptId); const webRTC = useWebRTC(stream, details.params.transcriptId, true);
const webRTC = useWebRTC(stream, details.params.transcriptId, api);
const webSockets = useWebSockets(details.params.transcriptId); const webSockets = useWebSockets(details.params.transcriptId);
const { audioDevices, getAudioStream } = useAudioDevice(); const { audioDevices, getAudioStream } = useAudioDevice();

View File

@@ -19,10 +19,10 @@ const useCreateTranscript = (): CreateTranscript => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [error, setErrorState] = useState<Error | null>(null); const [error, setErrorState] = useState<Error | null>(null);
const { setError } = useError(); const { setError } = useError();
const api = getApi(); const api = getApi(true);
const create = (params: V1TranscriptsCreateRequest["createTranscript"]) => { const create = (params: V1TranscriptsCreateRequest["createTranscript"]) => {
if (loading) return; if (loading || !api) return;
setLoading(true); setLoading(true);
const requestParameters: V1TranscriptsCreateRequest = { const requestParameters: V1TranscriptsCreateRequest = {

View File

@@ -15,6 +15,7 @@ import AudioInputsDropdown from "./audioInputsDropdown";
import { Option } from "react-dropdown"; import { Option } from "react-dropdown";
import { useError } from "../../(errors)/errorContext"; import { useError } from "../../(errors)/errorContext";
import { waveSurferStyles } from "../../styles/recorder"; import { waveSurferStyles } from "../../styles/recorder";
import useMp3 from "./useMp3";
type RecorderProps = { type RecorderProps = {
setStream?: React.Dispatch<React.SetStateAction<MediaStream | null>>; setStream?: React.Dispatch<React.SetStateAction<MediaStream | null>>;

View File

@@ -5,6 +5,7 @@ import {
} from "../../api/apis/DefaultApi"; } from "../../api/apis/DefaultApi";
import { useError } from "../../(errors)/errorContext"; import { useError } from "../../(errors)/errorContext";
import { Topic } from "./webSocketTypes"; import { Topic } from "./webSocketTypes";
import getApi from "../../lib/getApi";
type TranscriptTopics = { type TranscriptTopics = {
topics: Topic[] | null; topics: Topic[] | null;
@@ -12,14 +13,15 @@ type TranscriptTopics = {
error: Error | null; error: Error | null;
}; };
const useTopics = (api: DefaultApi, id: string): TranscriptTopics => { const useTopics = (protectedPath, id: string): TranscriptTopics => {
const [topics, setTopics] = useState<Topic[] | null>(null); const [topics, setTopics] = useState<Topic[] | null>(null);
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [error, setErrorState] = useState<Error | null>(null); const [error, setErrorState] = useState<Error | null>(null);
const { setError } = useError(); const { setError } = useError();
const api = getApi(protectedPath);
const getTopics = (id: string) => { useEffect(() => {
if (!id) return; if (!id || !api) return;
setLoading(true); setLoading(true);
const requestParameters: V1TranscriptGetTopicsRequest = { const requestParameters: V1TranscriptGetTopicsRequest = {
@@ -36,11 +38,7 @@ const useTopics = (api: DefaultApi, id: string): TranscriptTopics => {
setError(err); setError(err);
setErrorState(err); setErrorState(err);
}); });
}; }, [id, api]);
useEffect(() => {
getTopics(id);
}, [id]);
return { topics, loading, error }; return { topics, loading, error };
}; };

View File

@@ -1,7 +1,8 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { DefaultApi, V1TranscriptGetRequest } from "../../api/apis/DefaultApi"; import { V1TranscriptGetRequest } from "../../api/apis/DefaultApi";
import { GetTranscript } from "../../api"; import { GetTranscript } from "../../api";
import { useError } from "../../(errors)/errorContext"; import { useError } from "../../(errors)/errorContext";
import getApi from "../../lib/getApi";
type Transcript = { type Transcript = {
response: GetTranscript | null; response: GetTranscript | null;
@@ -9,14 +10,18 @@ type Transcript = {
error: Error | null; error: Error | null;
}; };
const useTranscript = (api: DefaultApi, id: string | null): Transcript => { const useTranscript = (
protectedPath: boolean,
id: string | null,
): Transcript => {
const [response, setResponse] = useState<GetTranscript | null>(null); const [response, setResponse] = useState<GetTranscript | null>(null);
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(true);
const [error, setErrorState] = useState<Error | null>(null); const [error, setErrorState] = useState<Error | null>(null);
const { setError } = useError(); const { setError } = useError();
const api = getApi(protectedPath);
const getTranscript = (id: string | null) => { useEffect(() => {
if (!id) return; if (!id || !api) return;
setLoading(true); setLoading(true);
const requestParameters: V1TranscriptGetRequest = { const requestParameters: V1TranscriptGetRequest = {
@@ -33,11 +38,7 @@ const useTranscript = (api: DefaultApi, id: string | null): Transcript => {
setError(err); setError(err);
setErrorState(err); setErrorState(err);
}); });
}; }, [id, !api]);
useEffect(() => {
getTranscript(id);
}, [id]);
return { response, loading, error }; return { response, loading, error };
}; };

View File

@@ -0,0 +1,44 @@
import { useEffect, useState } from "react";
import { GetTranscriptFromJSON, PageGetTranscript } from "../../api";
import { useError } from "../../(errors)/errorContext";
import getApi from "../../lib/getApi";
type TranscriptList = {
response: PageGetTranscript | null;
loading: boolean;
error: Error | null;
};
//always protected
const useTranscriptList = (page: number): TranscriptList => {
const [response, setResponse] = useState<PageGetTranscript | null>(null);
const [loading, setLoading] = useState<boolean>(true);
const [error, setErrorState] = useState<Error | null>(null);
const { setError } = useError();
const api = getApi(true);
useEffect(() => {
if (!api) return;
setLoading(true);
api
.v1TranscriptsList({ page })
.then((response) => {
// issue with API layer, conversion for items is not happening
response.items = response.items.map((item) =>
GetTranscriptFromJSON(item),
);
setResponse(response);
setLoading(false);
})
.catch((err) => {
setResponse(null);
setLoading(false);
setError(err);
setErrorState(err);
});
}, [!api, page]);
return { response, loading, error };
};
export default useTranscriptList;

View File

@@ -5,6 +5,7 @@ import {
} from "../../api/apis/DefaultApi"; } from "../../api/apis/DefaultApi";
import { AudioWaveform } from "../../api"; import { AudioWaveform } from "../../api";
import { useError } from "../../(errors)/errorContext"; import { useError } from "../../(errors)/errorContext";
import getApi from "../../lib/getApi";
type AudioWaveFormResponse = { type AudioWaveFormResponse = {
waveform: AudioWaveform | null; waveform: AudioWaveform | null;
@@ -12,14 +13,15 @@ type AudioWaveFormResponse = {
error: Error | null; error: Error | null;
}; };
const useWaveform = (api: DefaultApi, id: string): AudioWaveFormResponse => { const useWaveform = (protectedPath, id: string): AudioWaveFormResponse => {
const [waveform, setWaveform] = useState<AudioWaveform | null>(null); const [waveform, setWaveform] = useState<AudioWaveform | null>(null);
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(true);
const [error, setErrorState] = useState<Error | null>(null); const [error, setErrorState] = useState<Error | null>(null);
const { setError } = useError(); const { setError } = useError();
const api = getApi(protectedPath);
const getWaveform = (id: string) => { useEffect(() => {
if (!id) return; if (!id || !api) return;
setLoading(true); setLoading(true);
const requestParameters: V1TranscriptGetAudioWaveformRequest = { const requestParameters: V1TranscriptGetAudioWaveformRequest = {
@@ -36,11 +38,7 @@ const useWaveform = (api: DefaultApi, id: string): AudioWaveFormResponse => {
setError(err); setError(err);
setErrorState(err); setErrorState(err);
}); });
}; }, [id, api]);
useEffect(() => {
getWaveform(id);
}, [id]);
return { waveform, loading, error }; return { waveform, loading, error };
}; };

View File

@@ -5,14 +5,16 @@ import {
V1TranscriptRecordWebrtcRequest, V1TranscriptRecordWebrtcRequest,
} from "../../api/apis/DefaultApi"; } from "../../api/apis/DefaultApi";
import { useError } from "../../(errors)/errorContext"; import { useError } from "../../(errors)/errorContext";
import getApi from "../../lib/getApi";
const useWebRTC = ( const useWebRTC = (
stream: MediaStream | null, stream: MediaStream | null,
transcriptId: string | null, transcriptId: string | null,
api: DefaultApi, protectedPath,
): Peer => { ): Peer => {
const [peer, setPeer] = useState<Peer | null>(null); const [peer, setPeer] = useState<Peer | null>(null);
const { setError } = useError(); const { setError } = useError();
const api = getApi(protectedPath);
useEffect(() => { useEffect(() => {
if (!stream || !transcriptId) { if (!stream || !transcriptId) {
@@ -35,6 +37,7 @@ const useWebRTC = (
}); });
p.on("signal", (data: any) => { p.on("signal", (data: any) => {
if (!api) return;
if ("sdp" in data) { if ("sdp" in data) {
const requestParameters: V1TranscriptRecordWebrtcRequest = { const requestParameters: V1TranscriptRecordWebrtcRequest = {
transcriptId: transcriptId, transcriptId: transcriptId,

View File

@@ -3,7 +3,7 @@ import { isDevelopment } from "./utils";
const localConfig = { const localConfig = {
features: { features: {
requireLogin: true, requireLogin: false,
privacy: true, privacy: true,
browse: true, browse: true,
}, },

View File

@@ -2,21 +2,32 @@ import { Configuration } from "../api/runtime";
import { DefaultApi } from "../api/apis/DefaultApi"; import { DefaultApi } from "../api/apis/DefaultApi";
import { useFiefAccessTokenInfo } from "@fief/fief/nextjs/react"; import { useFiefAccessTokenInfo } from "@fief/fief/nextjs/react";
import { useContext } from "react"; import { useContext, useEffect, useState } from "react";
import { DomainContext } from "../[domain]/domainContext"; import { DomainContext, featureEnabled } from "../[domain]/domainContext";
export default function getApi(): DefaultApi { export default function getApi(protectedPath: boolean): DefaultApi | undefined {
const accessTokenInfo = useFiefAccessTokenInfo(); const accessTokenInfo = useFiefAccessTokenInfo();
const api_url = useContext(DomainContext).api_url; const api_url = useContext(DomainContext).api_url;
const requireLogin = featureEnabled("requireLogin");
const [api, setApi] = useState<DefaultApi>();
if (!api_url) throw new Error("no API URL"); if (!api_url) throw new Error("no API URL");
useEffect(() => {
// console.log('trying auth', protectedPath, requireLogin, accessTokenInfo)
if (protectedPath && requireLogin && !accessTokenInfo) {
// console.log('waiting auth')
return;
}
const apiConfiguration = new Configuration({ const apiConfiguration = new Configuration({
basePath: api_url, basePath: api_url,
accessToken: accessTokenInfo accessToken: accessTokenInfo
? "Bearer " + accessTokenInfo.access_token ? "Bearer " + accessTokenInfo.access_token
: undefined, : undefined,
}); });
const api = new DefaultApi(apiConfiguration); setApi(new DefaultApi(apiConfiguration));
}, [!accessTokenInfo]);
return api; return api;
} }