Add fingerprint to user requests

pull/3813/head
Kamran Ahmed 2 years ago
parent 7dbb00a306
commit 0da417735e
  1. 1
      package.json
  2. 8
      pnpm-lock.yaml
  3. 47
      src/components/AuthenticationFlow/EmailSignupForm.tsx
  4. 20
      src/lib/http.ts

@ -23,6 +23,7 @@
"@astrojs/preact": "^2.1.0",
"@astrojs/sitemap": "^1.2.2",
"@astrojs/tailwind": "^3.1.1",
"@fingerprintjs/fingerprintjs": "^3.4.1",
"@nanostores/preact": "^0.3.1",
"astro": "^2.2.3",
"astro-compress": "^1.1.35",

@ -4,6 +4,7 @@ specifiers:
'@astrojs/preact': ^2.1.0
'@astrojs/sitemap': ^1.2.2
'@astrojs/tailwind': ^3.1.1
'@fingerprintjs/fingerprintjs': ^3.4.1
'@nanostores/preact': ^0.3.1
'@playwright/test': ^1.32.3
'@tailwindcss/typography': ^0.5.9
@ -31,6 +32,7 @@ dependencies:
'@astrojs/preact': 2.1.0_preact@10.13.2
'@astrojs/sitemap': 1.2.2
'@astrojs/tailwind': 3.1.1_ooi4vwztktmr2nba6g3hokplre
'@fingerprintjs/fingerprintjs': 3.4.1
'@nanostores/preact': 0.3.1_ntvucyavaortwycasiweu74jd4
astro: 2.2.3
astro-compress: 1.1.35
@ -634,6 +636,12 @@ packages:
dev: false
optional: true
/@fingerprintjs/fingerprintjs/3.4.1:
resolution: {integrity: sha512-i3TqlaIdF+4qDHP6OStMtLXCnvnoo2C156rNPm9/kIglUtnLAF45+sGkZZmVQB+58dDF0mNpaiqvKHNSR8J1Hg==}
dependencies:
tslib: 2.5.0
dev: false
/@gar/promisify/1.1.3:
resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
dev: false

@ -1,5 +1,6 @@
import type { FunctionComponent } from 'preact';
import { useState } from 'preact/hooks';
import { httpPost } from '../../lib/http';
const EmailSignupForm: FunctionComponent = () => {
const [email, setEmail] = useState('');
@ -9,12 +10,26 @@ const EmailSignupForm: FunctionComponent = () => {
const [error, setError] = useState('');
const [isLoading, setIsLoading] = useState(false);
const handleRegisterResponse = async (res: Response) => {
const json = await res.json();
const onSubmit = async (e: Event) => {
e.preventDefault();
if (!res.ok) {
setError(json.message || 'Something went wrong. Please try again later.');
setIsLoading(true);
setError('');
const { response, error } = await httpPost<{ status: 'ok' }>(
`${import.meta.env.PUBLIC_API_URL}/v1-register`,
{
email,
password,
name,
}
);
if (error || response?.status !== 'ok') {
setIsLoading(false);
setError(
error?.message || 'Something went wrong. Please try again later.'
);
return;
}
@ -24,30 +39,6 @@ const EmailSignupForm: FunctionComponent = () => {
)}`;
};
const onSubmit = (e: Event) => {
e.preventDefault();
setIsLoading(true);
setError('');
fetch(`${import.meta.env.PUBLIC_API_URL}/v1-register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email,
password,
name,
}),
})
.then(handleRegisterResponse)
.catch((err) => {
setIsLoading(false);
setError('Something went wrong. Please try again later.');
});
};
return (
<form className="flex w-full flex-col gap-2" onSubmit={onSubmit}>
<label htmlFor="name" className="sr-only">

@ -1,12 +1,14 @@
import Cookies from 'js-cookie';
import fp from '@fingerprintjs/fingerprintjs';
import { TOKEN_COOKIE_NAME } from './jwt';
type HttpOptionsType = RequestInit | { headers: Record<string, any> };
type AppResponse = Record<string, any>;
type FetchError = {
status: number;
message: string;
};
type AppError = {
status: number;
message: string;
@ -29,9 +31,12 @@ export async function httpCall<
ErrorType = AppError
>(
url: string,
options?: RequestInit
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
try {
const fingerprintPromise = await fp.load({ monitoring: false });
const fingerprint = await fingerprintPromise.get();
const response = await fetch(url, {
credentials: 'include',
...options,
@ -39,6 +44,7 @@ export async function httpCall<
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${Cookies.get(TOKEN_COOKIE_NAME)}`,
'x-fp': fingerprint.visitorId,
...(options?.headers ?? {}),
}),
});
@ -82,7 +88,7 @@ export async function httpPost<
>(
url: string,
body: Record<string, any>,
options?: RequestInit
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
return httpCall<ResponseType, ErrorType>(url, {
...options,
@ -94,7 +100,7 @@ export async function httpPost<
export async function httpGet<ResponseType = AppResponse, ErrorType = AppError>(
url: string,
queryParams?: Record<string, any>,
options?: RequestInit
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
const searchParams = new URLSearchParams(queryParams).toString();
const queryUrl = searchParams ? `${url}?${searchParams}` : url;
@ -112,7 +118,7 @@ export async function httpPatch<
>(
url: string,
body: Record<string, any>,
options?: RequestInit
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
return httpCall<ResponseType, ErrorType>(url, {
...options,
@ -124,7 +130,7 @@ export async function httpPatch<
export async function httpPut<ResponseType = AppResponse, ErrorType = AppError>(
url: string,
body: Record<string, any>,
options?: RequestInit
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
return httpCall<ResponseType, ErrorType>(url, {
...options,
@ -138,7 +144,7 @@ export async function httpDelete<
ErrorType = AppError
>(
url: string,
options?: RequestInit
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
return httpCall<ResponseType, ErrorType>(url, {
...options,

Loading…
Cancel
Save