Skip to content

Commit

Permalink
feat(auth): enable auth flow (with some redirects to bl-login)
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrianAndersen committed Jul 3, 2024
1 parent ef151b2 commit 156505d
Show file tree
Hide file tree
Showing 24 changed files with 346 additions and 160 deletions.
43 changes: 36 additions & 7 deletions src/api/api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import axios, { AxiosError, AxiosResponse } from "axios";
import axios, { AxiosError, AxiosResponse, isAxiosError } from "axios";

import { apiPath, getHeaders } from "@/api/apiRequest";
import { fetchNewTokens } from "@/api/token";
import { BlError } from "@/utils/types";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const get = async <T = any>(
Expand Down Expand Up @@ -34,14 +35,42 @@ export const get = async <T = any>(
});
};

export const add = async (collection: string, data: unknown) => {
return await axios
.post(apiPath(collection), data, {
export const add = async (
collection: string,
data: unknown,
): Promise<AxiosResponse | BlError> => {
try {
return await axios.post(apiPath(collection), data, {
headers: getHeaders(),
})
.catch((error) => {
throw new Error(error?.response?.data?.msg ?? "Noe gikk galt!");
});
} catch (error: unknown) {
return (
(isAxiosError(error) && error.response?.data) ?? {
msg: "Noe gikk galt!",
httpCode: 500,
code: 800,
}
);
}
};

export const patch = async (
collection: string,
data: unknown,
): Promise<AxiosResponse | BlError> => {
try {
return await axios.patch(apiPath(collection), data, {
headers: getHeaders(),
});
} catch (error: unknown) {
return (
(isAxiosError(error) && error.response?.data) ?? {
msg: "Noe gikk galt!",
httpCode: 500,
code: 800,
}
);
}
};

export const put = async <T = unknown>(
Expand Down
11 changes: 0 additions & 11 deletions src/api/login.ts

This file was deleted.

5 changes: 2 additions & 3 deletions src/api/token.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axios from "axios";
import { decodeToken } from "react-jwt";

import { add, get, remove } from "@/api/storage";
import { add, get, removeAll } from "@/api/storage";
import BL_CONFIG from "@/utils/bl-config";
import { AccessToken } from "@/utils/types";

Expand Down Expand Up @@ -57,8 +57,7 @@ export const getRefreshToken = (): string => {
};

export const removeTokens = (): void => {
remove(accessTokenName);
remove(refreshTokenName);
removeAll();
};

export const getAccessTokenBody = (): AccessToken => {
Expand Down
38 changes: 38 additions & 0 deletions src/api/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { UserDetail } from "@boklisten/bl-model";

import { add, patch } from "@/api/api";
import { parseTokensFromResponseDataAndStore } from "@/api/token";
import BL_CONFIG from "@/utils/bl-config";
import { verifyBlError } from "@/utils/types";

export const login = async (username: string, password: string) => {
const apiResponse = await add(BL_CONFIG.login.local.url, {
username,
password,
});
if (!verifyBlError(apiResponse)) {
parseTokensFromResponseDataAndStore(apiResponse.data);
}
return apiResponse;
};

export const registerUser = async (username: string, password: string) => {
const apiResponse = await add(BL_CONFIG.register.local.url, {
username,
password,
});
if (!verifyBlError(apiResponse)) {
parseTokensFromResponseDataAndStore(apiResponse.data);
}
return apiResponse;
};

export const updateUserDetails = async (
userId: string,
userDetails: Partial<UserDetail>,
) => {
return await patch(
`${BL_CONFIG.collection.userDetail}/${userId}`,
userDetails,
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
import Image from "next/image";
import { useState } from "react";
import { SubmitHandler, useForm } from "react-hook-form";
import isEmail from "validator/lib/isEmail";

import { add } from "@/api/api";
import DynamicLink from "@/components/DynamicLink";
Expand Down Expand Up @@ -104,12 +103,7 @@ const ForgotPage = () => {
id="email"
label="Epost"
autoComplete="email"
error={!!errors.email}
{...register("email", {
required: "Du må fylle inn epost",
validate: (v) =>
isEmail(v) ? true : "Du må fylle inn en gyldig epost",
})}
{...register("email")}
/>
<Button
data-testid="forgot-submit"
Expand Down
File renamed without changes.
11 changes: 11 additions & 0 deletions src/app/auth/logout/page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use client";
import { redirect } from "next/navigation";

import { logout } from "@/api/auth";
import { attachTokensToHref } from "@/components/AuthLinker";
import BL_CONFIG from "@/utils/bl-config";

export default function LogoutPage() {
logout();
redirect(attachTokensToHref(BL_CONFIG.blWeb.basePath + "auth/logout"));
}
File renamed without changes.
15 changes: 15 additions & 0 deletions src/app/auth/token/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"use client";

import { useRouter } from "next/navigation";
import { useEffect } from "react";

export default function TokenRedirectPage() {
const router = useRouter();
useEffect(() => {
// Redirect after tokens have been captured
setTimeout(() => {
router.push("/");
}, 100);
}, [router]);
return null;
}
9 changes: 9 additions & 0 deletions src/app/items/page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use client";
import { redirect } from "next/navigation";

import { attachTokensToHref } from "@/components/AuthLinker";
import BL_CONFIG from "@/utils/bl-config";

export default function ItemsPage() {
redirect(attachTokensToHref(BL_CONFIG.blWeb.basePath + "u/items"));
}
3 changes: 1 addition & 2 deletions src/app/matches/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import React, { useEffect, useState } from "react";
import { isLoggedIn } from "@/api/auth";
import DynamicLink from "@/components/DynamicLink";
import { MatchesList } from "@/components/matches/matchesList/MatchesList";
import BL_CONFIG from "@/utils/bl-config";

const MatchesPage = () => {
const [hydrated, setHydrated] = useState(false);
Expand All @@ -28,7 +27,7 @@ const MatchesPage = () => {
<Alert severity="info">
Du må logge inn for å se overleveringene dine
</Alert>
<DynamicLink href={`${BL_CONFIG.blWeb.basePath}overleveringer`}>
<DynamicLink href={"/auth/login?redirect=matches"}>
<Button variant={"contained"} sx={{ mt: "1rem" }}>
Logg inn
</Button>
Expand Down
9 changes: 9 additions & 0 deletions src/app/order-history/page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use client";
import { redirect } from "next/navigation";

import { attachTokensToHref } from "@/components/AuthLinker";
import BL_CONFIG from "@/utils/bl-config";

export default function OrdersPage() {
redirect(attachTokensToHref(BL_CONFIG.blWeb.basePath + "u/order"));
}
9 changes: 9 additions & 0 deletions src/app/order/page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use client";
import { redirect } from "next/navigation";

import { attachTokensToHref } from "@/components/AuthLinker";
import BL_CONFIG from "@/utils/bl-config";

export default function OrderPage() {
redirect(attachTokensToHref(BL_CONFIG.blWeb.basePath + "fastbuy/regions"));
}
4 changes: 3 additions & 1 deletion src/app/page.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"use client";
import { redirect } from "next/navigation";

import { attachTokensToHref } from "@/components/AuthLinker";
import BL_CONFIG from "@/utils/bl-config";

export default function IndexPage() {
redirect(BL_CONFIG.blWeb.basePath);
redirect(attachTokensToHref(BL_CONFIG.blWeb.basePath));
}
File renamed without changes.
19 changes: 18 additions & 1 deletion src/components/AuthLinker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,24 @@
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useEffect } from "react";

import { addAccessToken, addRefreshToken } from "@/api/token";
import { isLoggedIn } from "@/api/auth";
import {
addAccessToken,
addRefreshToken,
getAccessToken,
getRefreshToken,
} from "@/api/token";
import BL_CONFIG from "@/utils/bl-config";

export function attachTokensToHref(href: string) {
if (String(href).includes(BL_CONFIG.blWeb.basePath) && isLoggedIn()) {
return (
href +
`?refresh_token=${getRefreshToken()}&access_token=${getAccessToken()}`
);
}
return href;
}

export default function AuthLinker() {
const pathname = usePathname();
Expand Down
19 changes: 2 additions & 17 deletions src/components/DynamicLink.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
"use client";
import { Link as MuiLink, LinkProps as MuiLinkProps } from "@mui/material";
import NextLink, { LinkProps as NextLinkProps } from "next/link";
import { ForwardedRef, forwardRef, useEffect, useState } from "react";

import { isLoggedIn } from "@/api/auth";
import { getAccessToken, getRefreshToken } from "@/api/token";
import BL_CONFIG from "@/utils/bl-config";
import { ForwardedRef, forwardRef } from "react";

type CustomNextLinkProps = Omit<NextLinkProps, "href"> & {
_href: NextLinkProps["href"];
Expand All @@ -26,23 +22,12 @@ type DynamicLinkProps = Omit<MuiLinkProps<typeof NextLink>, "href"> & {
href: NextLinkProps["href"];
testID?: string;
};

const DynamicLink = ({ href, testID, ...props }: DynamicLinkProps) => {
// Since we do not have token info while on the server side, we need to wait until we are on the client side to set the href
const [hydrated, setHydrated] = useState(false);
useEffect(() => {
setHydrated(true);
}, []);

if (String(href).includes(BL_CONFIG.blWeb.basePath) && isLoggedIn()) {
href += `?refresh_token=${getRefreshToken()}&access_token=${getAccessToken()}`;
}

return (
<MuiLink
{...props}
component={CustomNextLink}
_href={hydrated ? href : ""}
_href={href}
data-testid={testID}
variant={props.variant ?? "body2"}
underline={props.underline ?? "none"}
Expand Down
7 changes: 4 additions & 3 deletions src/components/LocalizationProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"use client";
import { LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterMoment as DateAdapter } from "@mui/x-date-pickers/AdapterMoment/AdapterMoment";
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
import { Moment } from "moment";
import { ReactNode } from "react";

class OverriddenAdapter extends DateAdapter {
class OverriddenAdapter extends AdapterMoment {
// Get years in descending order
override getYearRange = ([start, end]: [Moment, Moment]) => {
const startDate = this.moment(start).startOf("year");
Expand All @@ -20,13 +20,14 @@ class OverriddenAdapter extends DateAdapter {
return years.reverse();
};
}

export default function CustomLocalizationProvider({
children,
}: {
children: ReactNode;
}) {
return (
<LocalizationProvider dateAdapter={OverriddenAdapter}>
<LocalizationProvider dateAdapter={OverriddenAdapter} adapterLocale={"no"}>
{children}
</LocalizationProvider>
);
Expand Down
5 changes: 2 additions & 3 deletions src/components/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import React from "react";
import BranchSelect from "@/components/BranchSelect";
import DynamicLink from "@/components/DynamicLink";
import DropDownMenu from "@/components/SideMenuDrawer";
import BL_CONFIG from "@/utils/bl-config";

interface TabLinkProps {
title: string;
Expand Down Expand Up @@ -43,7 +42,7 @@ const TAB_LINKS: TabLinkProps[] = [
testID: "infoBtnNav",
},
{
href: BL_CONFIG.blWeb.basePath + "fastbuy/regions",
href: "/order",
title: "Bestill bøker",
testID: "",
},
Expand All @@ -54,7 +53,7 @@ export default function NavBar() {
<Box data-testid="nav-bar">
<AppBar position="fixed">
<Toolbar sx={{ paddingY: "10px" }}>
<DynamicLink href={BL_CONFIG.blWeb.basePath}>
<DynamicLink href={"/"}>
<Box
sx={{ display: "flex", alignItems: "center", cursor: "pointer" }}
color="secondary"
Expand Down
Loading

0 comments on commit 156505d

Please sign in to comment.