Skip to content
Merged

Login #1536

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 30 additions & 7 deletions src/components/User/withAuth.component.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,42 @@
import { useRouter } from 'next/router';
import { useEffect, ComponentType } from 'react';
import { hasCredentials } from '../../utils/auth';
import { useEffect, ComponentType, useState } from 'react';
import { useQuery } from '@apollo/client';
import { GET_CURRENT_USER } from '../../utils/gql/GQL_QUERIES';
import LoadingSpinner from '../LoadingSpinner/LoadingSpinner.component';

const withAuth = <P extends object>(WrappedComponent: ComponentType<P>) => {
const Wrapper = (props: P) => {
const router = useRouter();
const [isChecking, setIsChecking] = useState(true);

const { data, loading, error } = useQuery(GET_CURRENT_USER, {
errorPolicy: 'all',
fetchPolicy: 'cache-and-network',
});

useEffect(() => {
if (!hasCredentials()) {
router.push('/logg-inn');
if (!loading) {
setIsChecking(false);

// If there's an error or no customer data, user is not authenticated
if (error || !data?.customer) {
router.push('/logg-inn');
}
}
}, [router]);
}, [data, loading, error, router]);

if (!hasCredentials()) {
return null; // or a loading spinner
// Show loading while checking authentication
if (loading || isChecking) {
return (
<div className="flex justify-center items-center min-h-screen">
<LoadingSpinner />
</div>
);
}

// If no customer data, don't render the component
if (!data?.customer) {
return null;
}

return <WrappedComponent {...props} />;
Expand Down
10 changes: 3 additions & 7 deletions src/utils/apollo/ApolloClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
createHttpLink,
ApolloLink,
} from '@apollo/client';
import { getAuthToken } from '../auth';

const SEVEN_DAYS = 7 * 24 * 60 * 60 * 1000; // 7 days in milliseconds

Expand Down Expand Up @@ -39,12 +38,8 @@ export const middleware = new ApolloLink(async (operation, forward) => {
}
}

if (process.browser) {
const authToken = await getAuthToken();
if (authToken) {
headers.Authorization = `Bearer ${authToken}`;
}
}
// Cookie-based authentication - no JWT tokens needed
// Cookies are automatically included with credentials: 'include'

operation.setContext({
headers,
Expand Down Expand Up @@ -97,6 +92,7 @@ const client = new ApolloClient({
createHttpLink({
uri: process.env.NEXT_PUBLIC_GRAPHQL_URL,
fetch,
credentials: 'include', // Include cookies for authentication
}),
),
),
Expand Down
46 changes: 41 additions & 5 deletions src/utils/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,44 @@ export async function getAuthToken() {
return null;
}

function getErrorMessage(error: any): string {
// Check for GraphQL errors
if (error.graphQLErrors && error.graphQLErrors.length > 0) {
const graphQLError = error.graphQLErrors[0];
const message = graphQLError.message;

// Map GraphQL error messages to user-friendly messages
switch (message) {
case 'invalid_username':
return 'Ugyldig brukernavn eller e-postadresse. Vennligst sjekk og prøv igjen.';
case 'incorrect_password':
return 'Feil passord. Vennligst sjekk passordet ditt og prøv igjen.';
case 'invalid_email':
return 'Ugyldig e-postadresse. Vennligst skriv inn en gyldig e-postadresse.';
case 'empty_username':
return 'Vennligst skriv inn brukernavn eller e-postadresse.';
case 'empty_password':
return 'Vennligst skriv inn passord.';
case 'too_many_retries':
return 'For mange mislykkede forsøk. Vennligst vent litt før du prøver igjen.';
default:
return 'Innlogging mislyktes. Vennligst sjekk dine opplysninger og prøv igjen.';
}
}

// Check for network errors
if (error.networkError) {
return 'Nettverksfeil. Vennligst sjekk internetttilkoblingen din og prøv igjen.';
}

// Fallback for other errors
if (error.message) {
return 'Det oppstod en feil under innlogging. Vennligst prøv igjen.';
}

return 'En ukjent feil oppstod. Vennligst prøv igjen senere.';
}

export async function login(username: string, password: string) {
try {
const client = new ApolloClient({
Expand All @@ -33,16 +71,14 @@ export async function login(username: string, password: string) {
const loginResult = data.loginWithCookies;

if (loginResult.status !== 'SUCCESS') {
throw new Error('Login failed');
throw new Error('Innlogging mislyktes. Vennligst sjekk dine opplysninger og prøv igjen.');
}

// On successful login, cookies are automatically set by the server
return { success: true, status: loginResult.status };
} catch (error: unknown) {
if (error instanceof Error) {
throw new Error(error.message);
}
throw new Error('An unknown error occurred during login.');
const userFriendlyMessage = getErrorMessage(error);
throw new Error(userFriendlyMessage);
}
}

Expand Down
11 changes: 11 additions & 0 deletions src/utils/gql/GQL_QUERIES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,17 @@ export const GET_CART = gql`
}
`;

export const GET_CURRENT_USER = gql`
query GET_CURRENT_USER {
customer {
id
firstName
lastName
email
}
}
`;

export const GET_CUSTOMER_ORDERS = gql`
query GET_CUSTOMER_ORDERS {
customer {
Expand Down
Loading