Skip to content

Commit

Permalink
Fix: Require Signature to login + Notifications (#497)
Browse files Browse the repository at this point in the history
Co-authored-by: Hugo Marques <[email protected]>
  • Loading branch information
hugomarquesdev and Hugo Marques authored Jul 26, 2023
1 parent 297964c commit 5538998
Show file tree
Hide file tree
Showing 21 changed files with 495 additions and 381 deletions.
13 changes: 10 additions & 3 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,24 @@ const baseQuery = retry(
const result = await fetchBaseQuery({
baseUrl: config.baseApiUrl,
prepareHeaders: (headers, { getState }) => {
const { token, signature, message } = (getState() as RootState)
.auth;
const {
token,
signature,
message,
eip712_signature,
eip712_message
} = (getState() as RootState).auth;

// If we have a token set in state, let's assume that we should be passing it.
if (token) {
headers.set('authorization', `Bearer ${token}`);
}

if (signature) {
if (signature || eip712_signature) {
headers.set('signature', signature);
headers.set('message', message);
headers.set('eip712_signature', eip712_signature);
headers.set('eip712_message', eip712_message);
}

return headers;
Expand Down
10 changes: 1 addition & 9 deletions src/api/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,6 @@ export const userApi = emptySplitApi.injectEndpoints({
}),
transformResponse: (response: { data: PreSigned }) => response.data
}),
// Get number of unread notifications
getUnreadNotifications: builder.mutation<UnreadNotifications, void>({
query: () => ({
method: 'GET',
url: 'users/notifications/unread'
})
}),
// Get profile
getUser: builder.mutation<User, void>({
query: () => ({
Expand Down Expand Up @@ -175,7 +168,7 @@ export const userApi = emptySplitApi.injectEndpoints({
query: ({ body }) => ({
body,
method: 'PUT',
url: 'users/notifications/read'
url: 'users/notifications'
})
}),
// Edit profile
Expand All @@ -198,7 +191,6 @@ export const {
useCreateUserMutation,
useDeleteUserMutation,
useGetNotificationsMutation,
useGetUnreadNotificationsMutation,
useGetUserMutation,
useGetUserByIdMutation,
useRecoverAccountMutation,
Expand Down
44 changes: 0 additions & 44 deletions src/components/Signature.tsx

This file was deleted.

21 changes: 18 additions & 3 deletions src/helpers/dateHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ export const dateHelpers = {
addSuffix: true
}),

agoISO: (date: number | string | Date) => {
const dateStr = date;
const dateObj = new Date(dateStr);

const distance = formatDistanceToNowStrict(dateObj, {
addSuffix: true
});

return distance;
},

compact: (date: string | Date) =>
date ? format(new Date(date), 'MMM d, y') : '',

Expand All @@ -44,11 +55,15 @@ export const dateHelpers = {

complete: (date: number) =>
date ? format(new Date(fromUnixTime(date)), `MMM d, y • H:m`) : '',

getDateAndTime: (timestamp: string) => {
const date = new Date(timestamp);
const dateString = dateFnsFormat(date, 'MMM d, y', { locale: getLocale() });
const timeString = dateFnsFormat(date, 'HH:mm', { locale: getLocale() });
const dateString = dateFnsFormat(date, 'MMM d, y', {
locale: getLocale()
});
const timeString = dateFnsFormat(date, 'HH:mm', {
locale: getLocale()
});

return [dateString, timeString];
},
Expand Down
26 changes: 20 additions & 6 deletions src/helpers/handleSignature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,29 @@ import { registerSignature } from '../helpers/registerSignature';
import { toast } from '@impact-market/ui';
import config from '../../config';

export const handleSignature = async (signMessage: any) => {
export const handleSignature = async (signMessage: any, signTypedData: any) => {
try {
const timestamp = new Date()?.getTime()?.toString();
const messageToSign = `${config.signatureMessage} ${timestamp}`;
const currentDate = new Date();
const futureDate = new Date(
currentDate.getTime() + 45 * 24 * 60 * 60 * 1000
);

const messageToSign = `${config.signatureMessage} ${currentDate
.getTime()
.toString()}`;

const options = {
expiry: Math.trunc(futureDate.getTime() / 1000)
};

toast.info('Please go to the wallet, sign the message');
await signMessage(messageToSign).then((signature: string) => {
registerSignature(signature, messageToSign);
});

const [signature, eip712_signature] = await Promise.all([
signMessage(messageToSign),
signTypedData(messageToSign, options)
]);

registerSignature(signature, eip712_signature, messageToSign);

return { success: true };
} catch (error) {
Expand Down
31 changes: 28 additions & 3 deletions src/helpers/registerSignature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,38 @@ import { setSignature } from '../state/slices/auth';
import { store } from '../state/store';
import config from '../../config';

export const registerSignature = (signature: string, message: string) => {
interface Signature {
message: object;
signature: string;
}

export const registerSignature = (
signature: string,
eip712_signature: Signature,
messageToSign: string
) => {
const expiryDate = new Date(
Date.now() + 86400 * 1000 * parseInt(config.signatureExpires, 10)
);

setCookie('SIGNATURE', signature, { expires: expiryDate, path: '/' });
setCookie('MESSAGE', message, { expires: expiryDate, path: '/' });
setCookie('MESSAGE', messageToSign, { expires: expiryDate, path: '/' });

setCookie('EIP712_SIGNATURE', eip712_signature?.signature, {
expires: expiryDate,
path: '/'
});
setCookie('EIP712_MESSAGE', JSON.stringify(eip712_signature?.message), {
expires: expiryDate,
path: '/'
});

store.dispatch(setSignature({ message, signature }));
store.dispatch(
setSignature({
eip712_message: JSON.stringify(eip712_signature?.message),
eip712_signature: eip712_signature?.signature,
message: messageToSign,
signature
})
);
};
4 changes: 4 additions & 0 deletions src/hooks/useCache.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ const useCache = () => {
deleteCookie('AUTH_TOKEN', { path: '/' });
deleteCookie('SIGNATURE', { path: '/' });
deleteCookie('MESSAGE', { path: '/' });
deleteCookie('EIP712_SIGNATURE', { path: '/' });
deleteCookie('EIP712_MESSAGE', { path: '/' });

dispatch(
setSignature({
eip712_message: null,
eip712_signature: null,
message: null,
signature: null
})
Expand Down
15 changes: 12 additions & 3 deletions src/hooks/useMicrocredit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import useSWR from 'swr';

export function useMicrocreditBorrowers(filters?: any[]) {
const auth = useSelector(selectCurrentUser);
const { signature, message } = useSelector(selectCurrentUser);
const { signature, message, eip712_message, eip712_signature } =
useSelector(selectCurrentUser);

const fetcher = (url: string) =>
fetch(config.baseApiUrl + url, {
headers: {
Authorization: `Bearer ${auth.token}`,
eip712signature: eip712_signature,
eip712value: eip712_message,
message,
signature
}
Expand All @@ -37,12 +40,15 @@ export function useMicrocreditBorrowers(filters?: any[]) {

export function useMicrocreditBorrower(filters?: any[]) {
const auth = useSelector(selectCurrentUser);
const { signature, message } = useSelector(selectCurrentUser);
const { signature, message, eip712_message, eip712_signature } =
useSelector(selectCurrentUser);

const fetcher = (url: string) =>
fetch(config.baseApiUrl + url, {
headers: {
Authorization: `Bearer ${auth.token}`,
eip712signature: eip712_signature,
eip712value: eip712_message,
message,
signature
}
Expand All @@ -68,12 +74,15 @@ export function useMicrocreditBorrower(filters?: any[]) {

export function useMicrocreditBorrowerRepaymentHistory(filters?: any[]) {
const auth = useSelector(selectCurrentUser);
const { signature, message } = useSelector(selectCurrentUser);
const { signature, message, eip712_message, eip712_signature } =
useSelector(selectCurrentUser);

const fetcher = (url: string) =>
fetch(config.baseApiUrl + url, {
headers: {
Authorization: `Bearer ${auth.token}`,
eip712signature: eip712_signature,
eip712value: eip712_message,
message,
signature
}
Expand Down
6 changes: 4 additions & 2 deletions src/hooks/useMicrocreditApplications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import useSWR from 'swr';

export default function useMicrocreditApplications(filters?: any[]) {
const auth = useSelector(selectCurrentUser);
const { signature, message } = useSelector(selectCurrentUser);
const { signature, message, eip712_message, eip712_signature } =
useSelector(selectCurrentUser);

const fetcher = (url: string) =>
fetch(config.baseApiUrl + url, {
headers: {
Authorization: `Bearer ${auth.token}`,
eip712signature: eip712_signature,
eip712value: eip712_message,
message,
signature
}
Expand All @@ -25,7 +28,6 @@ export default function useMicrocreditApplications(filters?: any[]) {
fetcher
);


const loadingApplications = !data && !error;

return {
Expand Down
38 changes: 38 additions & 0 deletions src/hooks/useNotifications.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { selectCurrentUser } from '../state/slices/auth';
import { useSelector } from 'react-redux';
import config from '../../config';
import useSWR from 'swr';

export function useNotifications(filters?: any[]) {
const auth = useSelector(selectCurrentUser);
const { signature, message, eip712_message, eip712_signature } =
useSelector(selectCurrentUser);

const fetcher = (url: string) =>
fetch(config.baseApiUrl + url, {
headers: {
Authorization: `Bearer ${auth.token}`,
eip712signature: eip712_signature,
eip712value: eip712_message,
message,
signature
}
}).then((res) => res.json());

const { data, mutate, error } = useSWR(
`/users/notifications/${
!!filters?.length
? filters?.map((filter: any) => filter).join('&')
: ''
}`,
fetcher
);

const loadingNotifications = !data && !error;

return {
loadingNotifications,
mutate,
notifications: data?.data
};
}
13 changes: 8 additions & 5 deletions src/modals/AddCommunity/ConfirmAdd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import useTranslations from '../../libs/Prismic/hooks/useTranslations';
const ConfirmAdd = () => {
const { data, handleClose, isSubmitting, language, onSubmit } = useModal();

const { signature } = useSelector(selectCurrentUser);
const { signMessage } = useSignatures();
const { signature, eip712_signature } = useSelector(selectCurrentUser);
const { signMessage, signTypedData } = useSignatures();
const auth = useSelector(selectCurrentUser);
const [updatedData, setUpdatedData] = useState(data) as any;
const [profilePicture, setProfilePicture] = useState(null);
Expand Down Expand Up @@ -74,8 +74,8 @@ const ConfirmAdd = () => {
const personalForm: SubmitHandler<any> = async (userData) => {
if (isValid) {
try {
if (!signature) {
await handleSignature(signMessage);
if (!signature || !eip712_signature) {
await handleSignature(signMessage, signTypedData);
}

if (profilePicture || auth?.user?.avatarMediaPath) {
Expand All @@ -86,7 +86,10 @@ const ConfirmAdd = () => {
error?.data?.error?.name === 'EXPIRED_SIGNATURE' ||
error?.data?.error?.name === 'INVALID_SINATURE'
) {
const { success } = await handleSignature(signMessage);
const { success } = await handleSignature(
signMessage,
signTypedData
);

if (success) personalForm(data);
} else {
Expand Down
Loading

0 comments on commit 5538998

Please sign in to comment.