Skip to content

Commit 20d4f63

Browse files
committed
fix: Password reset feature
1 parent c3a9634 commit 20d4f63

File tree

3 files changed

+16
-12
lines changed

3 files changed

+16
-12
lines changed

client/src/views/auth/LoginView.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const LoginView = () => {
3131
const Loader = useLoader();
3232
const { t } = useTranslation('login');
3333

34-
const { register, handleSubmit, formState: { isSubmitting }, control, setValue } = useForm<FormData>('user');
34+
const { register, handleSubmit, formState: { isSubmitting }, control, setValue, setFocus } = useForm<FormData>('user');
3535
const login = useWatch({ name: 'login', control });
3636

3737
/**
@@ -75,9 +75,10 @@ const LoginView = () => {
7575
return;
7676
}
7777
Loader.open();
78-
await UserRoutes.sendPasswordResetMail(login).catch(catchError(Alert));
78+
await UserRoutes.sendPasswordResetMail(login).then(() => {
79+
Alert.open('success', t('passwordResetMailSent'));
80+
}).catch(catchError(Alert));
7981
Loader.close();
80-
Alert.open('success', t('passwordResetMailSent'));
8182
}, [Alert, Loader, login, t]);
8283

8384
// Password reset form
@@ -118,23 +119,26 @@ const LoginView = () => {
118119
const code = url.searchParams.get('reset');
119120
const log = url.searchParams.get('login');
120121
if (code) {
122+
// Prefill login field
123+
setValue('login', log || '');
124+
setFocus('login');
125+
121126
const isValid = await UserRoutes.checkResetCodeValidity(log || '', code).catch(catchError(Alert));
122127
if (!isValid) {
123-
// Prefill login field
124-
setValue('login', log || '');
125-
126128
Alert.open('error', t('invalidResetCode'));
127129
// Remove code and login from URL
128130
url.searchParams.delete('reset');
129131
url.searchParams.delete('login');
130132
window.history.replaceState({}, '', url.href);
133+
134+
return;
131135
}
132136
// Open reset password dialog
133137
setResetDialogOpen(true);
134138
}
135139
};
136140
checkCode().catch(catchError(Alert));
137-
}, [Alert, setValue, t]);
141+
}, [Alert, setFocus, setValue, t]);
138142

139143
return (
140144
<Page

server/src/controllers/Users.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ const changePassword = (prisma: PrismaClient) => async (
127127
},
128128
});
129129

130-
res.status(200).send();
130+
res.send({ message: 'Password updated' });
131131
} catch (error) {
132132
sendError(res, error);
133133
}
@@ -165,7 +165,7 @@ const sendPasswordResetEmail = (prisma: PrismaClient) => async (
165165
throw new Error('Email not sent');
166166
}
167167

168-
res.send('ok');
168+
res.send({ message: 'Email sent' });
169169
} catch (error) {
170170
sendError(res, error);
171171
}
@@ -191,7 +191,7 @@ const checkResetCodeValidity = (prisma: PrismaClient) => async (
191191
const tokenIsValid = await bcrypt.compare(`${user.id}`, code);
192192

193193
if (tokenIsValid) {
194-
res.send();
194+
res.send({ message: 'Token valid' });
195195
} else {
196196
throw new Error('Invalid token');
197197
}
@@ -250,7 +250,7 @@ const resetPassword = (prisma: PrismaClient) => async (
250250
},
251251
});
252252

253-
res.send();
253+
res.send({ message: 'Password updated' });
254254
} catch (error) {
255255
sendError(res, error);
256256
}

server/src/utils/MailUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ style="@import url(https://fonts.googleapis.com/css?family=Rubik:300, 400, 500,
3030
</tr>
3131
<tr>
3232
<td style="text-align: center;">
33-
<img width="95%" max-width="670" style="-webkit-box-shadow: 0 6px 18px 0 rgba(0, 0, 0, 0.06); -moz-box-shadow: 0 6px 18px 0 rgba(0, 0, 0, 0.06); box-shadow: 0 6px 18px 0 rgba(0, 0, 0, 0.06);" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMi4wLjEsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMDAgMTAwMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCgkuc3Qwe2ZpbGw6dXJsKCNTVkdJRF8xXyk7fQ0KCS5zdDF7ZmlsbDp1cmwoI1NWR0lEXzJfKTt9DQoJLnN0MntmaWxsOnVybCgjU1ZHSURfM18pO30NCgkuc3Qze2ZpbGw6dXJsKCNTVkdJRF80Xyk7fQ0KPC9zdHlsZT4NCjxnPg0KCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMV8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMjM4LjgxNSIgeTE9IjU1OC4wNTUxIiB4Mj0iNTg3Ljk5NSIgeTI9IjU1OC4wNTUxIj4NCgkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzFCNzVCQyIvPg0KCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMkUzMTkyIi8+DQoJPC9saW5lYXJHcmFkaWVudD4NCgk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNTYxLjcsNjU0LjNjLTExLjksMC0yMi40LDcuOS0yNSwxOS4xSDI3My44bDI1NC44LTI1NC44aC05N2MtMi41LTUuNy04LjUtOS41LTE1LjEtOS41DQoJCWMtOS4yLDAtMTYuOCw3LjUtMTYuOCwxNi44YzAsOS4yLDcuNSwxNi44LDE2LjgsMTYuOGM2LjYsMCwxMi41LTMuOCwxNS4xLTkuNWg2MkwyMzguOCw2ODcuOWgyOTcuOGMyLjYsMTEuMiwxMy4yLDE5LjEsMjUsMTkuMQ0KCQljMTQuNSwwLDI2LjMtMTEuOSwyNi4zLTI2LjNDNTg4LDY2Ni4yLDU3Ni4xLDY1NC4zLDU2MS43LDY1NC4zeiBNNDE2LjUsNDM1LjFjLTUsMC05LjItNC4yLTkuMi05LjJjMC01LDQuMi05LjYsOS4yLTkuNg0KCQljNSwwLDkuNiw0LjYsOS42LDkuNkM0MjYuMiw0MzAuOSw0MjEuNiw0MzUuMSw0MTYuNSw0MzUuMXogTTU2MS43LDY5NS44Yy03LjksMC0xNS4xLTcuMy0xNS4xLTE1LjFjMC03LjksNy4yLTE0LjUsMTUuMS0xNC41DQoJCWM3LjksMCwxNC41LDYuNiwxNC41LDE0LjVDNTc2LjEsNjg4LjYsNTY5LjYsNjk1LjgsNTYxLjcsNjk1Ljh6Ii8+DQoJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8yXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIyNDkuMDA1IiB5MT0iNDYxLjUwNSIgeDI9Ijc2MS4xODUiIHkyPSI0NjEuNTA1Ij4NCgkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0Y3OTQxRCIvPg0KCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojRjE1QTI5Ii8+DQoJPC9saW5lYXJHcmFkaWVudD4NCgk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNNzM0LjksNTQzLjRjLTEyLjUsMC0yMyw5LjItMjUuNywyMWgtNzlMNTk2LDU5OEg0MzMuMmwyNDQuNS0yNDQuNUg0MTIuMmwtMzMuNS0zNC4yaC03OC4zDQoJCWMtMi0xMS44LTEyLjUtMjAuNC0yNS43LTIwLjRjLTE0LjUsMC0yNS43LDExLjgtMjUuNywyNi4zYzAsMTMuOCwxMS4yLDI1LjYsMjUuNywyNS42YzExLjksMCwyMS03LjIsMjUtMTcuMWg3M2wyMSwyMWgtMzYuOA0KCQljLTIuNy03LjgtOS4yLTEyLjQtMTcuMS0xMi40Yy0xMC41LDAtMTguNCw4LjYtMTguNCwxOC41YzAsMTAuNSw3LjksMTguNCwxOC40LDE4LjRjNy44LDAsMTQuNC01LjIsMTcuMS0xMi4zaDQ4LjlsMC41LDAuNWgyMzcuMQ0KCQlsLTY1LjgsNjUuOEw0NDMuOSw1NjYuOWwtNDUuNiw0NS42aDIwNC4zbDAuMy0wLjNINjcyYzIsNy4zLDkuMiwxMS45LDE3LjEsMTEuOWMxMC41LDAsMTguNC03LjksMTguNC0xOC40DQoJCWMwLTkuOS03LjktMTguNC0xOC40LTE4LjRjLTcuOSwwLTE1LjEsNS4zLTE3LjEsMTIuNWgtNTYuOWwyMS4xLTIxLjVoNzQuM2MzLjMsMTAuNSwxMy4yLDE3LjEsMjQuNCwxNy4xDQoJCWMxNC41LDAsMjYuMy0xMS4yLDI2LjMtMjUuN1M3NDkuMyw1NDMuNCw3MzQuOSw1NDMuNHogTTI3NC43LDMzOS43Yy03LjksMC0xNC41LTcuMi0xNC41LTE0LjVjMC04LjYsNi42LTE1LjEsMTQuNS0xNS4xDQoJCWM4LjUsMCwxNS4xLDYuNSwxNS4xLDE1LjFDMjg5LjgsMzMyLjUsMjgzLjIsMzM5LjcsMjc0LjcsMzM5Ljd6IE0zMzkuOCwzNzEuM2MtNS45LDAtMTAuNS00LjYtMTAuNS0xMC41YzAtNiw0LjYtMTAuNSwxMC41LTEwLjUNCgkJYzYsMCwxMC41LDQuNiwxMC41LDEwLjVDMzUwLjQsMzY2LjcsMzQ1LjgsMzcxLjMsMzM5LjgsMzcxLjN6IE02ODkuMSw1OTUuOGM1LjksMCwxMC41LDQuNiwxMC41LDkuOWMwLDUuOS00LjYsMTAuNS0xMC41LDEwLjUNCgkJYy01LjksMC0xMC41LTQuNi0xMC41LTEwLjVDNjc4LjYsNjAwLjQsNjgzLjIsNTk1LjgsNjg5LjEsNTk1Ljh6IE03MzQuOSw1ODQuMmMtNy45LDAtMTUuMS02LjYtMTUuMS0xNC41DQoJCWMwLTcuOSw3LjItMTQuNSwxNS4xLTE0LjVjNy45LDAsMTQuNSw2LjYsMTQuNSwxNC41Qzc0OS4zLDU3Ny42LDc0Mi43LDU4NC4yLDczNC45LDU4NC4yeiIvPg0KCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfM18iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iNDEyLjAxNSIgeTE9IjQ0MS45NDUiIHgyPSI3NjEuMTg1IiB5Mj0iNDQxLjk0NSI+DQoJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiMxQjc1QkMiLz4NCgkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzJFMzE5MiIvPg0KCTwvbGluZWFyR3JhZGllbnQ+DQoJPHBhdGggY2xhc3M9InN0MiIgZD0iTTc2MS4yLDMxMi4xSDQ2My4zYy0yLjYtMTEuMi0xMy4yLTE5LjEtMjUtMTkuMWMtMTQuNSwwLTI2LjMsMTEuOS0yNi4zLDI2LjNjMCwxNC41LDExLjgsMjYuMywyNi4zLDI2LjMNCgkJYzExLjgsMCwyMi40LTcuOSwyNS0xOS4xaDI2Mi45bC05Mi4xLDkyLjFsLTE0LjUsMTQuNUw0ODUuOSw1NjYuOWwtMTQuNSwxNC41aDk3YzIuNSw1LjcsOC41LDkuNSwxNS4xLDkuNQ0KCQljOS4yLDAsMTYuOC03LjUsMTYuOC0xNi44YzAtOS4yLTcuNS0xNi44LTE2LjgtMTYuOGMtNi42LDAtMTIuNSwzLjgtMTUuMSw5LjVoLTYyTDc2MS4yLDMxMi4xTDc2MS4yLDMxMi4xeiBNNDM4LjMsMzMzLjgNCgkJYy03LjksMC0xNC41LTYuNi0xNC41LTE0LjVjMC03LjksNi42LTE1LjEsMTQuNS0xNS4xYzcuOSwwLDE1LjEsNy4zLDE1LjEsMTUuMUM0NTMuNSwzMjcuMiw0NDYuMiwzMzMuOCw0MzguMywzMzMuOHogTTU4My41LDU2NC45DQoJCWM1LDAsOS4yLDQuMiw5LjIsOS4yYzAsNS00LjIsOS42LTkuMiw5LjZjLTUsMC05LjYtNC42LTkuNi05LjZDNTczLjgsNTY5LjEsNTc4LjQsNTY0LjksNTgzLjUsNTY0Ljl6Ii8+DQoJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF80XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIyMzguODI1IiB5MT0iNTM4LjQ5NSIgeDI9Ijc1MS4wMDUiIHkyPSI1MzguNDk1Ij4NCgkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0Y3OTQxRCIvPg0KCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojRjE1QTI5Ii8+DQoJPC9saW5lYXJHcmFkaWVudD4NCgk8cGF0aCBjbGFzcz0ic3QzIiBkPSJNNzI1LjMsNjQ5LjFjLTExLjksMC0yMSw3LjItMjUsMTcuMWgtNzNsLTIxLTIxaDM2LjhjMi43LDcuOCw5LjIsMTIuNCwxNy4xLDEyLjRjMTAuNSwwLDE4LjQtOC42LDE4LjQtMTguNQ0KCQljMC0xMC41LTcuOS0xOC40LTE4LjQtMTguNGMtNy45LDAtMTQuNCw1LjItMTcuMSwxMi4zaC00OC45bC0wLjUtMC41SDM1Ni42bDUxLjMtNTEuM2wxNC41LTE0LjVsMTc5LjMtMTc5LjRIMzk3LjRsLTAuMywwLjNIMzI4DQoJCWMtMi03LjMtOS4yLTExLjktMTcuMS0xMS45Yy0xMC41LDAtMTguNCw3LjktMTguNCwxOC40YzAsOS45LDcuOSwxOC40LDE4LjQsMTguNGM3LjksMCwxNS4xLTUuMywxNy4xLTEyLjVoNTYuOWwtMjEuMSwyMS41aC03NC4zDQoJCWMtMy4zLTEwLjUtMTMuMi0xNy4xLTI0LjQtMTcuMWMtMTQuNSwwLTI2LjMsMTEuMi0yNi4zLDI1LjdzMTEuOCwyNi4zLDI2LjMsMjYuM2MxMi41LDAsMjMtOS4yLDI1LjctMjFoNzlMNDA0LDQwMmgxNjIuOA0KCQlsLTE2LjcsMTYuN0wzMjIuMyw2NDYuNWgyNjUuNWwzMy41LDM0LjJoNzguM2MyLDExLjgsMTIuNSwyMC40LDI1LjcsMjAuNGMxNC41LDAsMjUuNy0xMS44LDI1LjctMjYuMw0KCQlDNzUxLDY2MC45LDczOS44LDY0OS4xLDcyNS4zLDY0OS4xeiBNNjYwLjIsNjI4LjdjNS45LDAsMTAuNSw0LjYsMTAuNSwxMC41YzAsNi00LjYsMTAuNS0xMC41LDEwLjVjLTYsMC0xMC41LTQuNi0xMC41LTEwLjUNCgkJQzY0OS43LDYzMy4zLDY1NC4yLDYyOC43LDY2MC4yLDYyOC43eiBNMzEwLjksNDA0LjJjLTUuOSwwLTEwLjUtNC42LTEwLjUtOS45YzAtNS45LDQuNi0xMC41LDEwLjUtMTAuNWM2LDAsMTAuNSw0LjYsMTAuNSwxMC41DQoJCUMzMjEuNCwzOTkuNiwzMTYuOCw0MDQuMiwzMTAuOSw0MDQuMnogTTI2NS4xLDQ0NC44Yy03LjksMC0xNC41LTYuNi0xNC41LTE0LjVjMC03LjksNi42LTE0LjUsMTQuNS0xNC41YzcuOSwwLDE1LjEsNi42LDE1LjEsMTQuNQ0KCQlDMjgwLjMsNDM4LjIsMjczLDQ0NC44LDI2NS4xLDQ0NC44eiBNNzI1LjMsNjg5LjljLTguNSwwLTE1LjEtNi42LTE1LjEtMTUuMWMwLTcuMiw2LjYtMTQuNSwxNS4xLTE0LjVjNy45LDAsMTQuNSw3LjIsMTQuNSwxNC41DQoJCUM3MzkuOCw2ODMuMyw3MzMuMiw2ODkuOSw3MjUuMyw2ODkuOXoiLz4NCjwvZz4NCjwvc3ZnPg0K" title="logo" alt="logo" />
33+
<img width="50%" max-width="300" style="-webkit-box-shadow: 0 6px 18px 0 rgba(0, 0, 0, 0.06); -moz-box-shadow: 0 6px 18px 0 rgba(0, 0, 0, 0.06); box-shadow: 0 6px 18px 0 rgba(0, 0, 0, 0.06);" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMi4wLjEsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMDAgMTAwMDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCgkuc3Qwe2ZpbGw6dXJsKCNTVkdJRF8xXyk7fQ0KCS5zdDF7ZmlsbDp1cmwoI1NWR0lEXzJfKTt9DQoJLnN0MntmaWxsOnVybCgjU1ZHSURfM18pO30NCgkuc3Qze2ZpbGw6dXJsKCNTVkdJRF80Xyk7fQ0KPC9zdHlsZT4NCjxnPg0KCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMV8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMjM4LjgxNSIgeTE9IjU1OC4wNTUxIiB4Mj0iNTg3Ljk5NSIgeTI9IjU1OC4wNTUxIj4NCgkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzFCNzVCQyIvPg0KCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMkUzMTkyIi8+DQoJPC9saW5lYXJHcmFkaWVudD4NCgk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNTYxLjcsNjU0LjNjLTExLjksMC0yMi40LDcuOS0yNSwxOS4xSDI3My44bDI1NC44LTI1NC44aC05N2MtMi41LTUuNy04LjUtOS41LTE1LjEtOS41DQoJCWMtOS4yLDAtMTYuOCw3LjUtMTYuOCwxNi44YzAsOS4yLDcuNSwxNi44LDE2LjgsMTYuOGM2LjYsMCwxMi41LTMuOCwxNS4xLTkuNWg2MkwyMzguOCw2ODcuOWgyOTcuOGMyLjYsMTEuMiwxMy4yLDE5LjEsMjUsMTkuMQ0KCQljMTQuNSwwLDI2LjMtMTEuOSwyNi4zLTI2LjNDNTg4LDY2Ni4yLDU3Ni4xLDY1NC4zLDU2MS43LDY1NC4zeiBNNDE2LjUsNDM1LjFjLTUsMC05LjItNC4yLTkuMi05LjJjMC01LDQuMi05LjYsOS4yLTkuNg0KCQljNSwwLDkuNiw0LjYsOS42LDkuNkM0MjYuMiw0MzAuOSw0MjEuNiw0MzUuMSw0MTYuNSw0MzUuMXogTTU2MS43LDY5NS44Yy03LjksMC0xNS4xLTcuMy0xNS4xLTE1LjFjMC03LjksNy4yLTE0LjUsMTUuMS0xNC41DQoJCWM3LjksMCwxNC41LDYuNiwxNC41LDE0LjVDNTc2LjEsNjg4LjYsNTY5LjYsNjk1LjgsNTYxLjcsNjk1Ljh6Ii8+DQoJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8yXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIyNDkuMDA1IiB5MT0iNDYxLjUwNSIgeDI9Ijc2MS4xODUiIHkyPSI0NjEuNTA1Ij4NCgkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0Y3OTQxRCIvPg0KCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojRjE1QTI5Ii8+DQoJPC9saW5lYXJHcmFkaWVudD4NCgk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNNzM0LjksNTQzLjRjLTEyLjUsMC0yMyw5LjItMjUuNywyMWgtNzlMNTk2LDU5OEg0MzMuMmwyNDQuNS0yNDQuNUg0MTIuMmwtMzMuNS0zNC4yaC03OC4zDQoJCWMtMi0xMS44LTEyLjUtMjAuNC0yNS43LTIwLjRjLTE0LjUsMC0yNS43LDExLjgtMjUuNywyNi4zYzAsMTMuOCwxMS4yLDI1LjYsMjUuNywyNS42YzExLjksMCwyMS03LjIsMjUtMTcuMWg3M2wyMSwyMWgtMzYuOA0KCQljLTIuNy03LjgtOS4yLTEyLjQtMTcuMS0xMi40Yy0xMC41LDAtMTguNCw4LjYtMTguNCwxOC41YzAsMTAuNSw3LjksMTguNCwxOC40LDE4LjRjNy44LDAsMTQuNC01LjIsMTcuMS0xMi4zaDQ4LjlsMC41LDAuNWgyMzcuMQ0KCQlsLTY1LjgsNjUuOEw0NDMuOSw1NjYuOWwtNDUuNiw0NS42aDIwNC4zbDAuMy0wLjNINjcyYzIsNy4zLDkuMiwxMS45LDE3LjEsMTEuOWMxMC41LDAsMTguNC03LjksMTguNC0xOC40DQoJCWMwLTkuOS03LjktMTguNC0xOC40LTE4LjRjLTcuOSwwLTE1LjEsNS4zLTE3LjEsMTIuNWgtNTYuOWwyMS4xLTIxLjVoNzQuM2MzLjMsMTAuNSwxMy4yLDE3LjEsMjQuNCwxNy4xDQoJCWMxNC41LDAsMjYuMy0xMS4yLDI2LjMtMjUuN1M3NDkuMyw1NDMuNCw3MzQuOSw1NDMuNHogTTI3NC43LDMzOS43Yy03LjksMC0xNC41LTcuMi0xNC41LTE0LjVjMC04LjYsNi42LTE1LjEsMTQuNS0xNS4xDQoJCWM4LjUsMCwxNS4xLDYuNSwxNS4xLDE1LjFDMjg5LjgsMzMyLjUsMjgzLjIsMzM5LjcsMjc0LjcsMzM5Ljd6IE0zMzkuOCwzNzEuM2MtNS45LDAtMTAuNS00LjYtMTAuNS0xMC41YzAtNiw0LjYtMTAuNSwxMC41LTEwLjUNCgkJYzYsMCwxMC41LDQuNiwxMC41LDEwLjVDMzUwLjQsMzY2LjcsMzQ1LjgsMzcxLjMsMzM5LjgsMzcxLjN6IE02ODkuMSw1OTUuOGM1LjksMCwxMC41LDQuNiwxMC41LDkuOWMwLDUuOS00LjYsMTAuNS0xMC41LDEwLjUNCgkJYy01LjksMC0xMC41LTQuNi0xMC41LTEwLjVDNjc4LjYsNjAwLjQsNjgzLjIsNTk1LjgsNjg5LjEsNTk1Ljh6IE03MzQuOSw1ODQuMmMtNy45LDAtMTUuMS02LjYtMTUuMS0xNC41DQoJCWMwLTcuOSw3LjItMTQuNSwxNS4xLTE0LjVjNy45LDAsMTQuNSw2LjYsMTQuNSwxNC41Qzc0OS4zLDU3Ny42LDc0Mi43LDU4NC4yLDczNC45LDU4NC4yeiIvPg0KCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfM18iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iNDEyLjAxNSIgeTE9IjQ0MS45NDUiIHgyPSI3NjEuMTg1IiB5Mj0iNDQxLjk0NSI+DQoJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiMxQjc1QkMiLz4NCgkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzJFMzE5MiIvPg0KCTwvbGluZWFyR3JhZGllbnQ+DQoJPHBhdGggY2xhc3M9InN0MiIgZD0iTTc2MS4yLDMxMi4xSDQ2My4zYy0yLjYtMTEuMi0xMy4yLTE5LjEtMjUtMTkuMWMtMTQuNSwwLTI2LjMsMTEuOS0yNi4zLDI2LjNjMCwxNC41LDExLjgsMjYuMywyNi4zLDI2LjMNCgkJYzExLjgsMCwyMi40LTcuOSwyNS0xOS4xaDI2Mi45bC05Mi4xLDkyLjFsLTE0LjUsMTQuNUw0ODUuOSw1NjYuOWwtMTQuNSwxNC41aDk3YzIuNSw1LjcsOC41LDkuNSwxNS4xLDkuNQ0KCQljOS4yLDAsMTYuOC03LjUsMTYuOC0xNi44YzAtOS4yLTcuNS0xNi44LTE2LjgtMTYuOGMtNi42LDAtMTIuNSwzLjgtMTUuMSw5LjVoLTYyTDc2MS4yLDMxMi4xTDc2MS4yLDMxMi4xeiBNNDM4LjMsMzMzLjgNCgkJYy03LjksMC0xNC41LTYuNi0xNC41LTE0LjVjMC03LjksNi42LTE1LjEsMTQuNS0xNS4xYzcuOSwwLDE1LjEsNy4zLDE1LjEsMTUuMUM0NTMuNSwzMjcuMiw0NDYuMiwzMzMuOCw0MzguMywzMzMuOHogTTU4My41LDU2NC45DQoJCWM1LDAsOS4yLDQuMiw5LjIsOS4yYzAsNS00LjIsOS42LTkuMiw5LjZjLTUsMC05LjYtNC42LTkuNi05LjZDNTczLjgsNTY5LjEsNTc4LjQsNTY0LjksNTgzLjUsNTY0Ljl6Ii8+DQoJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF80XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIyMzguODI1IiB5MT0iNTM4LjQ5NSIgeDI9Ijc1MS4wMDUiIHkyPSI1MzguNDk1Ij4NCgkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0Y3OTQxRCIvPg0KCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojRjE1QTI5Ii8+DQoJPC9saW5lYXJHcmFkaWVudD4NCgk8cGF0aCBjbGFzcz0ic3QzIiBkPSJNNzI1LjMsNjQ5LjFjLTExLjksMC0yMSw3LjItMjUsMTcuMWgtNzNsLTIxLTIxaDM2LjhjMi43LDcuOCw5LjIsMTIuNCwxNy4xLDEyLjRjMTAuNSwwLDE4LjQtOC42LDE4LjQtMTguNQ0KCQljMC0xMC41LTcuOS0xOC40LTE4LjQtMTguNGMtNy45LDAtMTQuNCw1LjItMTcuMSwxMi4zaC00OC45bC0wLjUtMC41SDM1Ni42bDUxLjMtNTEuM2wxNC41LTE0LjVsMTc5LjMtMTc5LjRIMzk3LjRsLTAuMywwLjNIMzI4DQoJCWMtMi03LjMtOS4yLTExLjktMTcuMS0xMS45Yy0xMC41LDAtMTguNCw3LjktMTguNCwxOC40YzAsOS45LDcuOSwxOC40LDE4LjQsMTguNGM3LjksMCwxNS4xLTUuMywxNy4xLTEyLjVoNTYuOWwtMjEuMSwyMS41aC03NC4zDQoJCWMtMy4zLTEwLjUtMTMuMi0xNy4xLTI0LjQtMTcuMWMtMTQuNSwwLTI2LjMsMTEuMi0yNi4zLDI1LjdzMTEuOCwyNi4zLDI2LjMsMjYuM2MxMi41LDAsMjMtOS4yLDI1LjctMjFoNzlMNDA0LDQwMmgxNjIuOA0KCQlsLTE2LjcsMTYuN0wzMjIuMyw2NDYuNWgyNjUuNWwzMy41LDM0LjJoNzguM2MyLDExLjgsMTIuNSwyMC40LDI1LjcsMjAuNGMxNC41LDAsMjUuNy0xMS44LDI1LjctMjYuMw0KCQlDNzUxLDY2MC45LDczOS44LDY0OS4xLDcyNS4zLDY0OS4xeiBNNjYwLjIsNjI4LjdjNS45LDAsMTAuNSw0LjYsMTAuNSwxMC41YzAsNi00LjYsMTAuNS0xMC41LDEwLjVjLTYsMC0xMC41LTQuNi0xMC41LTEwLjUNCgkJQzY0OS43LDYzMy4zLDY1NC4yLDYyOC43LDY2MC4yLDYyOC43eiBNMzEwLjksNDA0LjJjLTUuOSwwLTEwLjUtNC42LTEwLjUtOS45YzAtNS45LDQuNi0xMC41LDEwLjUtMTAuNWM2LDAsMTAuNSw0LjYsMTAuNSwxMC41DQoJCUMzMjEuNCwzOTkuNiwzMTYuOCw0MDQuMiwzMTAuOSw0MDQuMnogTTI2NS4xLDQ0NC44Yy03LjksMC0xNC41LTYuNi0xNC41LTE0LjVjMC03LjksNi42LTE0LjUsMTQuNS0xNC41YzcuOSwwLDE1LjEsNi42LDE1LjEsMTQuNQ0KCQlDMjgwLjMsNDM4LjIsMjczLDQ0NC44LDI2NS4xLDQ0NC44eiBNNzI1LjMsNjg5LjljLTguNSwwLTE1LjEtNi42LTE1LjEtMTUuMWMwLTcuMiw2LjYtMTQuNSwxNS4xLTE0LjVjNy45LDAsMTQuNSw3LjIsMTQuNSwxNC41DQoJCUM3MzkuOCw2ODMuMyw3MzMuMiw2ODkuOSw3MjUuMyw2ODkuOXoiLz4NCjwvZz4NCjwvc3ZnPg0K" title="logo" alt="logo" />
3434
</td>
3535
</tr>
3636
<tr>

0 commit comments

Comments
 (0)