[#34] added ky and condition to reconnect user on refresh
This commit is contained in:
Generated
+677
-891
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -18,6 +18,7 @@
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"i18next": "^23.7.9",
|
||||
"ky": "^1.8.1",
|
||||
"openid-client": "^6.5.3",
|
||||
"react": "^19.1.0",
|
||||
"react-calendar": "^6.0.0",
|
||||
@@ -32,7 +33,7 @@
|
||||
"start": "PORT=5000 rsbuild dev",
|
||||
"build": "rsbuild build",
|
||||
"preview": "rsbuild preview",
|
||||
"test": "react-scripts test",
|
||||
"test": "jest test",
|
||||
"lint": "eslint src"
|
||||
},
|
||||
"eslintConfig": {
|
||||
|
||||
@@ -19,12 +19,18 @@ import {
|
||||
getCalendarRange,
|
||||
} from "../../utils/dateUtils";
|
||||
import { Calendars } from "../../features/Calendars/CalendarTypes";
|
||||
import { push } from "redux-first-history";
|
||||
|
||||
export default function CalendarApp() {
|
||||
const calendarRef = useRef<CalendarApi | null>(null);
|
||||
const [selectedDate, setSelectedDate] = useState(new Date());
|
||||
const tokens = useAppSelector((state) => state.user.tokens);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
if (!tokens) {
|
||||
dispatch(push("/"));
|
||||
}
|
||||
|
||||
const calendars = useAppSelector((state) => state.calendars.list);
|
||||
const pending = useAppSelector((state) => state.calendars.pending);
|
||||
const userId = useAppSelector((state) => state.user.userData.openpaasId);
|
||||
@@ -75,7 +81,6 @@ export default function CalendarApp() {
|
||||
if (!pending && rangeKey) {
|
||||
dispatch(
|
||||
getCalendarDetailAsync({
|
||||
access_token: tokens.access_token,
|
||||
calId: id,
|
||||
match: {
|
||||
start: formatDateToYYYYMMDDTHHMMSS(calendarRange.start),
|
||||
|
||||
@@ -1,37 +1,32 @@
|
||||
import { cp } from "node:fs";
|
||||
import { api } from "../../utils/apiUtils";
|
||||
|
||||
export async function getCalendars(userId: string, opaque_token: string) {
|
||||
const response = await fetch(
|
||||
`${(window as any).CALENDAR_BASE_URL}/dav/calendars/${userId}.json?personal=true&sharedDelegationStatus=accepted&sharedPublicSubscription=true&withRights=true`,
|
||||
{
|
||||
headers: {
|
||||
Accept: "application/calendar+json",
|
||||
Authorization: `Bearer ${opaque_token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
const calendars = await response.json();
|
||||
export async function getCalendars(userId: string) {
|
||||
const calendars = await api
|
||||
.get(
|
||||
`dav/calendars/${userId}.json?personal=true&sharedDelegationStatus=accepted&sharedPublicSubscription=true&withRights=true`,
|
||||
{
|
||||
headers: {
|
||||
Accept: "application/calendar+json",
|
||||
},
|
||||
}
|
||||
)
|
||||
.json();
|
||||
return calendars;
|
||||
}
|
||||
|
||||
export async function getCalendar(
|
||||
id: string,
|
||||
opaque_token: string,
|
||||
match: { start: string; end: string }
|
||||
) {
|
||||
const response = await fetch(
|
||||
`${(window as any).CALENDAR_BASE_URL}/dav/calendars/${id}.json`,
|
||||
{
|
||||
method: "REPORT",
|
||||
headers: {
|
||||
Accept: "application/json, text/plain, */*",
|
||||
Authorization: `Bearer ${opaque_token}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
match,
|
||||
}),
|
||||
}
|
||||
);
|
||||
const response = await api(`dav/calendars/${id}.json`, {
|
||||
method: "REPORT",
|
||||
headers: {
|
||||
Accept: "application/json, text/plain, */*",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
match,
|
||||
}),
|
||||
});
|
||||
const calendar = await response.json();
|
||||
return calendar;
|
||||
}
|
||||
|
||||
@@ -6,12 +6,11 @@ import getOpenPaasUserId from "../User/userAPI";
|
||||
import { parseCalendarEvent } from "../Events/eventUtils";
|
||||
|
||||
export const getCalendarsListAsync = createAsyncThunk<
|
||||
Record<string, Calendars>, // Return type
|
||||
string // Arg type (access_token)
|
||||
>("calendars/getCalendars", async (access_token: string) => {
|
||||
Record<string, Calendars> // Return type
|
||||
>("calendars/getCalendars", async () => {
|
||||
const importedCalendars: Record<string, Calendars> = {};
|
||||
const user = await getOpenPaasUserId(access_token);
|
||||
const calendars = await getCalendars(user.id, access_token);
|
||||
const user = (await getOpenPaasUserId()) as Record<string, string>;
|
||||
const calendars = (await getCalendars(user.id)) as Record<string, any>;
|
||||
const rawCalendars = calendars._embedded["dav:calendar"];
|
||||
|
||||
for (const cal of rawCalendars) {
|
||||
@@ -32,9 +31,9 @@ export const getCalendarsListAsync = createAsyncThunk<
|
||||
|
||||
export const getCalendarDetailAsync = createAsyncThunk<
|
||||
{ calId: string; events: CalendarEvent[] }, // Return type
|
||||
{ access_token: string; calId: string; match: { start: string; end: string } } // Arg type
|
||||
>("calendars/getCalendarDetails", async ({ access_token, calId, match }) => {
|
||||
const calendar = await getCalendar(calId, access_token, match);
|
||||
{ calId: string; match: { start: string; end: string } } // Arg type
|
||||
>("calendars/getCalendarDetails", async ({ calId, match }) => {
|
||||
const calendar = (await getCalendar(calId, match)) as Record<string, any>;
|
||||
const color = calendar["apple:color"];
|
||||
const events: CalendarEvent[] = calendar._embedded["dav:item"].flatMap(
|
||||
(eventdata: any) => {
|
||||
|
||||
@@ -9,8 +9,6 @@ import { getCalendarsListAsync } from "../Calendars/CalendarSlice";
|
||||
export function CallbackResume() {
|
||||
const dispatch = useAppDispatch();
|
||||
const hasRun = useRef(false);
|
||||
const calendars = useAppSelector((state) => state.calendars);
|
||||
const userId = useAppSelector((state) => state.user.userData?.openpaasId);
|
||||
const saved = sessionStorage.getItem("redirectState")
|
||||
? JSON.parse(sessionStorage.getItem("redirectState")!)
|
||||
: null;
|
||||
@@ -28,6 +26,7 @@ export function CallbackResume() {
|
||||
dispatch(getCalendarsListAsync(data?.tokenSet.access_token ?? ""));
|
||||
|
||||
sessionStorage.removeItem("redirectState");
|
||||
sessionStorage.setItem("tokenSet", JSON.stringify(data?.tokenSet));
|
||||
// Redirect to main page after successful callback
|
||||
dispatch(push("/"));
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
export default async function getOpenPaasUserId(opaque_token: string) {
|
||||
const response = await fetch(
|
||||
`${(window as any).CALENDAR_BASE_URL}/api/user`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${opaque_token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
const user = await response.json();
|
||||
import { api } from "../../utils/apiUtils";
|
||||
|
||||
export default async function getOpenPaasUserId() {
|
||||
const user = await api.get(`api/user`).json();
|
||||
return user;
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@ import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
|
||||
import { userData, userOrganiser } from "./userDataTypes";
|
||||
import getOpenPaasUserId from "./userAPI";
|
||||
|
||||
export const getOpenPaasUserIdAsync = createAsyncThunk<
|
||||
string, // Return type
|
||||
string // Arg type
|
||||
>("user/getOpenPaasUserId", async (access_token) => {
|
||||
const user = await getOpenPaasUserId(access_token);
|
||||
export const getOpenPaasUserIdAsync = createAsyncThunk<string>(
|
||||
"user/getOpenPaasUserId",
|
||||
async () => {
|
||||
const user = (await getOpenPaasUserId()) as Record<string, string>;
|
||||
|
||||
return user.id;
|
||||
});
|
||||
return user.id;
|
||||
}
|
||||
);
|
||||
|
||||
export const userSlice = createSlice({
|
||||
name: "user",
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import ky from "ky";
|
||||
import { Auth } from "../features/User/oidcAuth";
|
||||
|
||||
export const api = ky.extend({
|
||||
prefixUrl: (window as any).CALENDAR_BASE_URL,
|
||||
hooks: {
|
||||
beforeRequest: [
|
||||
async (request) => {
|
||||
const saved = sessionStorage.getItem("tokenSet")
|
||||
? JSON.parse(sessionStorage.getItem("tokenSet")!)
|
||||
: null;
|
||||
const access_token = saved?.access_token;
|
||||
|
||||
const modifiedRequest = new Request(request);
|
||||
modifiedRequest.headers.set("Authorization", `Bearer ${access_token}`);
|
||||
return modifiedRequest;
|
||||
},
|
||||
],
|
||||
afterResponse: [
|
||||
async (request, options, response) => {
|
||||
if (response.status === 401) {
|
||||
// Attempt token refresh on unauthorized response
|
||||
const loginurl = await Auth();
|
||||
|
||||
sessionStorage.setItem(
|
||||
"tokenSet",
|
||||
JSON.stringify({
|
||||
code_verifier: loginurl.code_verifier,
|
||||
state: loginurl.state,
|
||||
})
|
||||
);
|
||||
window.location.assign(loginurl.redirectTo);
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user