refactor: massive refactor of ssr and ssr api

This commit is contained in:
EETagent 2022-12-05 14:35:41 +01:00
parent 4f32b244cf
commit 245fd6de80
8 changed files with 145 additions and 144 deletions

View file

@ -1,13 +1,17 @@
import type { AdminLogin } from "$lib/stores/admin"; import type { AdminLogin } from '$lib/stores/admin';
import type { CandidateData, CandidatePreview, CreateCandidate, CreateCandidateLogin } from "$lib/stores/candidate"; import type {
import axios from "axios"; CandidateData,
import { API_URL, errorHandler, type Fetch } from "."; CandidatePreview,
CreateCandidate,
CreateCandidateLogin
} from '$lib/stores/candidate';
import axios from 'axios';
import { API_URL, errorHandler, type Fetch } from '.';
// Login as admin /admin/login // Login as admin /admin/login
export const apiLogin = async (data: AdminLogin): Promise<number> => { export const apiLogin = async (data: AdminLogin): Promise<number> => {
try { try {
const res = await axios.post(API_URL + '/admin/login', data, { withCredentials: true }); await axios.post(API_URL + '/admin/login', data, { withCredentials: true });
return data.adminId; return data.adminId;
} catch (e: any) { } catch (e: any) {
throw errorHandler(e, 'Login failed'); throw errorHandler(e, 'Login failed');
@ -17,97 +21,92 @@ export const apiLogin = async (data: AdminLogin): Promise<number> => {
// Create new candidate /admin/create // Create new candidate /admin/create
// return created candidate's applicationId, personalIdNumber and password // return created candidate's applicationId, personalIdNumber and password
export const apiCreateCandidate = async (data: CreateCandidate): Promise<CreateCandidateLogin> => { export const apiCreateCandidate = async (data: CreateCandidate): Promise<CreateCandidateLogin> => {
try { try {
const res = await axios.post(API_URL + '/admin/create', data, { withCredentials: true }); const res = await axios.post(API_URL + '/admin/create', data, { withCredentials: true });
return res.data; return res.data;
} catch (e: any) { } catch (e: any) {
throw errorHandler(e, 'Candidate creation failed'); throw errorHandler(e, 'Candidate creation failed');
} }
} };
// Reset candidate password /admin/candidate/{id}/reset_password // Reset candidate password /admin/candidate/{id}/reset_password
export const apiResetCandidatePassword = async (id: number): Promise<CreateCandidateLogin> => { export const apiResetCandidatePassword = async (id: number): Promise<CreateCandidateLogin> => {
try { try {
const res = await axios.post(API_URL + '/admin/candidate/' + id + '/reset_password', const res = await axios.post(
{}, API_URL + '/admin/candidate/' + id + '/reset_password',
{ withCredentials: true } {},
); { withCredentials: true }
return res.data; );
} catch (e: any) { return res.data;
throw errorHandler(e, 'Candidate creation failed'); } catch (e: any) {
} throw errorHandler(e, 'Candidate creation failed');
} }
};
export const apiGetCandidatePortfolio = async (id: number): Promise<Blob> => { export const apiGetCandidatePortfolio = async (id: number): Promise<Blob> => {
try { try {
const res = await fetch(API_URL + '/admin/candidate/' + id + '/portfolio', { const res = await fetch(API_URL + '/admin/candidate/' + id + '/portfolio', {
method: 'GET', method: 'GET',
credentials: 'include', credentials: 'include'
}); });
return await res.blob(); return await res.blob();
} catch (e: any) { } catch (e: any) {
throw errorHandler(e, 'Candidate portfolio failed'); throw errorHandler(e, 'Candidate portfolio failed');
} }
} };
// SSR compatible // SSR compatible
// Logout as admin /admin/logout // Logout as admin /admin/logout
export const apiLogout = async (fetchSsr?: Fetch) => { export const apiLogout = async (fetchSsr?: Fetch) => {
const apiFetch = fetchSsr || fetch;
try { try {
if (fetchSsr) { const res = await apiFetch(API_URL + '/admin/logout', {
const res = await fetchSsr(API_URL + '/admin/logout', { method: 'POST',
method: 'POST', credentials: 'include'
credentials: 'include' });
}); return await res.text();
return await res.text(); } catch (e) {
}
const res = await axios.post(API_URL + '/admin/logout', { withCredentials: true });
return res.data;
} catch (e: any) {
throw errorHandler(e, 'Logout failed'); throw errorHandler(e, 'Logout failed');
} }
}; };
// SSR compatible // SSR compatible
// List all candidates /admin/list/candidates // List all candidates /admin/list/candidates
export const apiListCandidates = async (fetchSsr?: Fetch, field?: string): Promise<[CandidatePreview]> => { export const apiListCandidates = async (
fetchSsr?: Fetch,
field?: string
): Promise<Array<CandidatePreview>> => {
const apiFetch = fetchSsr || fetch;
const params = new URLSearchParams(); const params = new URLSearchParams();
if (field) { if (field) {
params.append('field', field); params.append('field', field);
} }
try { try {
if (fetchSsr) { const res = await apiFetch(API_URL + '/admin/list/candidates?' + params.toString(), {
const res = await fetchSsr(API_URL + '/admin/list/candidates?' + params.toString(), { method: 'GET',
method: 'GET', credentials: 'include'
credentials: 'include'
});
return await res.json();
}
const res = await axios.get(API_URL + '/admin/list/candidates?' + params.toString(), {
withCredentials: true
}); });
return res.data; if (res.status != 200) {
} catch (e: any) { throw Error(await res.text());
throw errorHandler(e, 'Failed to fetch submission progress'); }
return await res.json();
} catch (e) {
throw errorHandler(e, 'List candidates failed');
} }
}; };
// SSR compatible // SSR compatible
// Get candidate data /admin/candidate/{id} // Get candidate data /admin/candidate/{id}
export const apiFetchCandidate = async (id: number, fetchSsr?: Fetch): Promise<CandidateData> => { export const apiFetchCandidate = async (id: number, fetchSsr?: Fetch): Promise<CandidateData> => {
try { const apiFetch = fetchSsr || fetch;
if (fetchSsr) { try {
const res = await fetchSsr(API_URL + '/admin/candidate/' + id, { const res = await apiFetch(API_URL + '/admin/candidate/' + id, {
method: 'GET', method: 'GET',
credentials: 'include' credentials: 'include'
});
return await res.json();
}
const res = await axios.get(API_URL + '/admin/candidate/' + id, {
withCredentials: true
}); });
return res.data; return await res.json();
} catch (e: any) { } catch (e) {
throw errorHandler(e, 'Failed to fetch candidate data'); throw errorHandler(e, 'Failed to fetch candidate data');
} }
} };

View file

@ -6,64 +6,66 @@ import DOMPurify from 'isomorphic-dompurify';
// SSR Compatible // SSR Compatible
export const apiLogout = async (fetchSsr?: Fetch) => { export const apiLogout = async (fetchSsr?: Fetch) => {
const apiFetch = fetchSsr || fetch;
try { try {
fetchSsr const res = await apiFetch(API_URL + '/candidate/logout', {
? await fetchSsr(API_URL + '/candidate/logout', { method: 'POST', credentials: 'include' }) method: 'POST',
: await axios.post(API_URL + '/candidate/logout', { withCredentials: true }); credentials: 'include'
} catch (e: any) { });
return await res.json();
} catch (e) {
throw errorHandler(e, 'Logout failed'); throw errorHandler(e, 'Logout failed');
} }
}; };
// SSR Compatible // SSR Compatible
export const apiFetchDetails = async (fetchSsr?: Fetch): Promise<CandidateData> => { export const apiFetchDetails = async (fetchSsr?: Fetch): Promise<CandidateData> => {
const apiFetch = fetchSsr || fetch;
try { try {
if (fetchSsr) { const res = await apiFetch(API_URL + '/candidate/details', {
const res = await fetchSsr(API_URL + '/candidate/details', { method: 'GET',
method: 'GET', credentials: 'include'
credentials: 'include' });
}); if (res.status != 200) {
if (res.status != 200) { throw new Error(await res.text());
throw new Error(await res.text());
}
return await res.json();
} }
const res = await axios.get(API_URL + '/candidate/details', { withCredentials: true }); return await res.json();
return res.data; } catch (e) {
} catch (e: any) { throw errorHandler(e, 'Fetch details failed');
console.log(e);
throw errorHandler(e, 'Failed to fill details');
} }
}; };
// SSR Compatible // SSR Compatible
export const apiFetchSubmissionProgress = async (fetchSsr?: Fetch): Promise<SubmissionProgress> => { export const apiFetchSubmissionProgress = async (fetchSsr?: Fetch): Promise<SubmissionProgress> => {
const apiFetch = fetchSsr || fetch;
try { try {
if (fetchSsr) { const res = await apiFetch(API_URL + '/candidate/portfolio/submission_progress', {
const res = await fetchSsr(API_URL + '/candidate/portfolio/submission_progress', { method: 'GET',
method: 'GET', credentials: 'include'
credentials: 'include'
});
if (res.status != 200) {
throw Error(await res.text());
}
return await res.json();
}
const res = await axios.get(API_URL + '/candidate/portfolio/submission_progress', {
withCredentials: true
}); });
return res.data; if (res.status != 200) {
} catch (e: any) { throw Error(await res.text());
}
return await res.json();
} catch (e) {
throw errorHandler(e, 'Failed to fetch submission progress'); throw errorHandler(e, 'Failed to fetch submission progress');
} }
}; };
export const apiWhoami = async (): Promise<string> => { export const apiWhoami = async (fetchSsr?: Fetch): Promise<string> => {
const apiFetch = fetchSsr || fetch;
try { try {
const res = await axios.get(`${API_URL}/whoami`); console.log(API_URL + '/candidate/whoami');
return res.data; const res = await apiFetch(API_URL + '/candidate/whoami', {
} catch (e: any) { method: 'GET',
throw errorHandler(e, 'Whoami failed'); credentials: 'include'
});
if (res.status != 200) {
throw Error(await res.text());
}
return await res.text();
} catch (e) {
throw errorHandler(e, 'Failed to fetch whoami');
} }
}; };
@ -77,10 +79,11 @@ export const apiLogin = async (data: CandidateLogin): Promise<number> => {
}; };
export const apiFillDetails = async (data: CandidateData): Promise<CandidateData> => { export const apiFillDetails = async (data: CandidateData): Promise<CandidateData> => {
Object.keys(data).forEach(key => { Object.keys(data).forEach((key) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
data[key] = DOMPurify.sanitize(data[key]); data[key] = DOMPurify.sanitize(data[key]);
}); });
try { try {
const res = await axios.post(API_URL + '/candidate/details', data, { withCredentials: true }); const res = await axios.post(API_URL + '/candidate/details', data, { withCredentials: true });
return res.data; return res.data;

View file

@ -5,10 +5,10 @@ export type Fetch = (input: RequestInfo, init?: RequestInit) => Promise<Response
export const API_URL = 'http://localhost:8000'; export const API_URL = 'http://localhost:8000';
export interface ApiError { export interface ApiError {
error: AxiosError; error: AxiosError | unknown;
msg: string; msg: string;
} }
export const errorHandler = (error: AxiosError, msg: string): ApiError => { export const errorHandler = (error: AxiosError | unknown, msg: string): ApiError => {
return { error, msg }; return { error, msg };
} }

View file

@ -4,13 +4,13 @@ import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ fetch }) => { export const load: PageServerLoad = async ({ fetch }) => {
let candidatePreview: Array<CandidatePreview> = [{}]; let candidatePreview: Array<CandidatePreview> = [{}];
try {
candidatePreview = await apiListCandidates(fetch); candidatePreview =
} catch (e) { (await apiListCandidates(fetch).catch((e) => {
console.error(e); console.error(e);
} })) || [];
return { return {
preview: candidatePreview, preview: candidatePreview
}; };
}; };

View file

@ -1,10 +1,16 @@
import type { LayoutServerLoad } from './$types'; import type { LayoutServerLoad } from './$types';
import { redirect } from '@sveltejs/kit'; import { redirect } from '@sveltejs/kit';
import { apiWhoami } from '$lib/@api/candidate';
export const load: LayoutServerLoad = ({ cookies }) => { export const load: LayoutServerLoad = async ({ cookies, fetch }) => {
const isAuthenticated = cookies.get('id'); const isAuthenticated = cookies.get('id');
if (!isAuthenticated) {
throw redirect(302, '/auth/login'); if (isAuthenticated) {
await apiWhoami(fetch).catch((e) => {
throw redirect(302, '/auth/logout');
});
} else {
throw redirect(302, '/auth/logout');
} }
}; };

View file

@ -1,31 +0,0 @@
import { apiFetchDetails, apiFetchSubmissionProgress } from '$lib/@api/candidate';
import type { CandidateData } from '$lib/stores/candidate';
import { redirect } from '@sveltejs/kit';
import type { LayoutServerLoad } from './$types';
export const load: LayoutServerLoad = async ({ fetch }) => {
let details: CandidateData;
try {
details = await apiFetchDetails(fetch);
} catch (e: any) {
if (e.code === 401) {
throw redirect(302, '/auth/login');
} else {
throw redirect(302, '/register');
}
}
let submissionProgress;
try {
submissionProgress = await apiFetchSubmissionProgress(fetch);
} catch (e) {
console.log(e);
}
return {
candidate: details,
submission: {
...submissionProgress
}
};
};

View file

@ -0,0 +1,22 @@
import { apiFetchDetails, apiFetchSubmissionProgress } from '$lib/@api/candidate';
import type { CandidateData } from '$lib/stores/candidate';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ fetch }) => {
const details: CandidateData = await apiFetchDetails(fetch).catch((e) => {
console.error(e);
throw redirect(302, '/register');
});
const submissionProgress = await apiFetchSubmissionProgress(fetch).catch((e) => {
console.log(e);
});
return {
candidate: details,
submission: {
...submissionProgress
}
};
};

View file

@ -4,7 +4,9 @@ import { redirect } from '@sveltejs/kit';
import { apiLogout } from '$lib/@api/candidate'; import { apiLogout } from '$lib/@api/candidate';
export const load: PageServerLoad = async ({ fetch, cookies }) => { export const load: PageServerLoad = async ({ fetch, cookies }) => {
await apiLogout(fetch); await apiLogout(fetch).catch(() => {
// TODO: Handle error
});
cookies.delete('id', { path: '/' }); cookies.delete('id', { path: '/' });
cookies.delete('key', { path: '/' }); cookies.delete('key', { path: '/' });