mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-15 03:27:57 +01:00
JWT impl.
This commit is contained in:
parent
7a4b5212d9
commit
cbca2e6184
@ -39,7 +39,8 @@
|
||||
"react-query": "^3.39.1",
|
||||
"react-redux": "^7.2.2",
|
||||
"react-router-dom": "^6.4.3",
|
||||
"styled-components": "^5.3.6"
|
||||
"styled-components": "^5.3.6",
|
||||
"universal-cookie": "^7.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@formatjs/cli": "^6.0.4",
|
||||
|
@ -7,7 +7,8 @@
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="<%=PUBLIC_URL%>/favicon.ico" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;600&display=swap" rel="stylesheet" rel="preload"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;600&display=swap"
|
||||
rel="stylesheet" rel="preload" />
|
||||
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
@ -26,6 +27,20 @@
|
||||
<meta property="og:url" content="https://www.wisemapping.com" />
|
||||
<meta property="og:site_name" content="WiseMapping" />
|
||||
|
||||
<script>
|
||||
if ('<%=CLIENT_TYPE%>' === 'rest');
|
||||
{
|
||||
window.serverconfig = {
|
||||
apiBaseUrl: 'http://localhost:3000',
|
||||
analyticsAccount: 'G-RSDEJH16YM',
|
||||
clientType: 'rest',
|
||||
recaptcha2Enabled: true,
|
||||
recaptcha2SiteKey: '6Lcat08kAAAAAIP-HjhzIa-Yq21PHgGa_ADWc-Ro',
|
||||
googleOauth2Url: 'https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=https://app.wisemapping.com/c/registration-google&prompt=consent&response_type=code&client_id=625682766634-cocbbbbb403iuvps1evecdk6d7phvbkf.apps.googleusercontent.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&access_type=offline&state=wisemapping&include_granted_scopes=true'
|
||||
};
|
||||
}
|
||||
window.errorMvcView = '';
|
||||
</script>
|
||||
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
|
@ -1,5 +1,10 @@
|
||||
import { Locale, LocaleCode } from '../app-i18n';
|
||||
|
||||
export type JwtAuth = {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
export type NewUser = {
|
||||
email: string;
|
||||
firstname: string;
|
||||
@ -85,6 +90,8 @@ export type ForgotPasswordResult = {
|
||||
};
|
||||
|
||||
interface Client {
|
||||
login(auth: JwtAuth): Promise<void>;
|
||||
|
||||
deleteAccount(): Promise<void>;
|
||||
importMap(model: ImportMapInfo): Promise<number>;
|
||||
createMap(map: BasicMapInfo): Promise<number>;
|
||||
|
@ -26,8 +26,10 @@ import Client, {
|
||||
Permission,
|
||||
Oauth2CallbackResult,
|
||||
ForgotPasswordResult,
|
||||
JwtAuth,
|
||||
} from '..';
|
||||
import { LocaleCode, localeFromStr } from '../../app-i18n';
|
||||
import Cookies from 'universal-cookie';
|
||||
|
||||
const label1: Label = {
|
||||
id: 1,
|
||||
@ -127,6 +129,18 @@ class MockClient implements Client {
|
||||
this.labels = [label1, label2, label3];
|
||||
}
|
||||
|
||||
login(auth: JwtAuth): Promise<void> {
|
||||
const cookies = new Cookies();
|
||||
cookies.set('jwt-token-mock', auth.email, { path: '/' });
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
private _jwtToken(): string | undefined {
|
||||
// Set cookie on session ...
|
||||
const cookies = new Cookies();
|
||||
return cookies.get('jwt-token-mock');
|
||||
}
|
||||
|
||||
fetchStarred(id: number): Promise<boolean> {
|
||||
return Promise.resolve(Boolean(this.maps.find((m) => m.id == id)?.starred));
|
||||
}
|
||||
|
@ -11,9 +11,11 @@ import Client, {
|
||||
Permission,
|
||||
Oauth2CallbackResult,
|
||||
ForgotPasswordResult,
|
||||
JwtAuth,
|
||||
} from '..';
|
||||
import { getCsrfToken } from '../../../utils';
|
||||
import { LocaleCode, localeFromStr } from '../../app-i18n';
|
||||
import Cookies from 'universal-cookie';
|
||||
|
||||
export default class RestClient implements Client {
|
||||
private baseUrl: string;
|
||||
@ -32,18 +34,64 @@ export default class RestClient implements Client {
|
||||
constructor(baseUrl: string) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.axios = axios.create({ maxRedirects: 0 });
|
||||
const csrfToken = getCsrfToken();
|
||||
if (csrfToken) {
|
||||
this.axios.defaults.headers['X-CSRF-TOKEN'] = csrfToken;
|
||||
} else {
|
||||
console.warn('csrf token not found in html head');
|
||||
}
|
||||
|
||||
// Configure request interceptors ...
|
||||
this.axios.interceptors.request.use((config) => {
|
||||
if (config.headers) {
|
||||
// JWT Token ...
|
||||
const jwtToken = this._jwtToken();
|
||||
if (jwtToken) {
|
||||
config.headers['Authorization'] = jwtToken;
|
||||
}
|
||||
|
||||
// Add Csrf token ...
|
||||
const csrfToken = getCsrfToken();
|
||||
if (csrfToken) {
|
||||
config.headers['X-CSRF-TOKEN'] = csrfToken;
|
||||
} else {
|
||||
console.warn('csrf token not found in html head');
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
});
|
||||
|
||||
// Process response globally ...
|
||||
this.axios.interceptors.response.use(
|
||||
(r) => r,
|
||||
(r) => this.checkResponseForSessionExpired(r),
|
||||
(response) => response,
|
||||
(respoonse) => this.checkResponseForSessionExpired(respoonse),
|
||||
);
|
||||
}
|
||||
|
||||
login(model: JwtAuth): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.post(`${this.baseUrl}/api/restful/authenticate`, model, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
const token = response.data;
|
||||
// Set jwt token on cookie ...
|
||||
const cookies = new Cookies();
|
||||
cookies.set('jwt-auth-token', token, { path: '/', maxAge: 604800 });
|
||||
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
private _jwtToken(): string | null {
|
||||
// Set cookie on session ...
|
||||
const cookies = new Cookies();
|
||||
const token = cookies.get('jwt-auth-token');
|
||||
return token ? `Bearer ${token}` : null;
|
||||
}
|
||||
|
||||
private _onSessionExpired: () => void;
|
||||
onSessionExpired(callback?: () => void): () => void {
|
||||
if (callback) {
|
||||
@ -61,9 +109,12 @@ export default class RestClient implements Client {
|
||||
deleteMapPermission(id: number, email: string): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.delete(`${this.baseUrl}/c/restful/maps/${id}/collabs?email=${encodeURIComponent(email)}`, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.delete(
|
||||
`${this.baseUrl}/api/restful/maps/${id}/collabs?email=${encodeURIComponent(email)}`,
|
||||
{
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
},
|
||||
)
|
||||
.then(() => {
|
||||
success();
|
||||
})
|
||||
@ -78,7 +129,7 @@ export default class RestClient implements Client {
|
||||
fetchStarred(id: number): Promise<boolean> {
|
||||
const handler = (success: (starred: boolean) => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.get(`${this.baseUrl}/c/restful/maps/${id}/starred`, {
|
||||
.get(`${this.baseUrl}/api/restful/maps/${id}/starred`, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then((response) => {
|
||||
@ -98,7 +149,7 @@ export default class RestClient implements Client {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.put(
|
||||
`${this.baseUrl}/c/restful/maps/${id}/collabs/`,
|
||||
`${this.baseUrl}/api/restful/maps/${id}/collabs/`,
|
||||
{
|
||||
message: message,
|
||||
collaborations: permissions,
|
||||
@ -123,7 +174,7 @@ export default class RestClient implements Client {
|
||||
reject: (error: ErrorInfo) => void,
|
||||
) => {
|
||||
this.axios
|
||||
.get(`${this.baseUrl}/c/restful/maps/${id}/collabs`, {
|
||||
.get(`${this.baseUrl}/api/restful/maps/${id}/collabs`, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then((response) => {
|
||||
@ -150,7 +201,7 @@ export default class RestClient implements Client {
|
||||
deleteAccount(): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.delete(`${this.baseUrl}/c/restful/account`, {
|
||||
.delete(`${this.baseUrl}/api/restful/account`, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
@ -167,11 +218,11 @@ export default class RestClient implements Client {
|
||||
updateAccountInfo(firstname: string, lastname: string): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.put(`${this.baseUrl}/c/restful/account/firstname`, firstname, {
|
||||
.put(`${this.baseUrl}/api/restful/account/firstname`, firstname, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
return this.axios.put(`${this.baseUrl}/c/restful/account/lastname`, lastname, {
|
||||
return this.axios.put(`${this.baseUrl}/api/restful/account/lastname`, lastname, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
});
|
||||
})
|
||||
@ -190,7 +241,7 @@ export default class RestClient implements Client {
|
||||
updateAccountPassword(pasword: string): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.put(`${this.baseUrl}/c/restful/account/password`, pasword, {
|
||||
.put(`${this.baseUrl}/api/restful/account/password`, pasword, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
@ -207,7 +258,7 @@ export default class RestClient implements Client {
|
||||
updateAccountLanguage(locale: LocaleCode): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.put(`${this.baseUrl}/c/restful/account/locale`, locale, {
|
||||
.put(`${this.baseUrl}/api/restful/account/locale`, locale, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
@ -229,7 +280,7 @@ export default class RestClient implements Client {
|
||||
const handler = (success: (mapId: number) => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.post(
|
||||
`${this.baseUrl}/c/restful/maps?title=${encodeURIComponent(
|
||||
`${this.baseUrl}/api/restful/maps?title=${encodeURIComponent(
|
||||
model.title,
|
||||
)}&description=${encodeURIComponent(model.description ? model.description : '')}`,
|
||||
model.content,
|
||||
@ -253,7 +304,7 @@ export default class RestClient implements Client {
|
||||
reject: (error: ErrorInfo) => void,
|
||||
) => {
|
||||
this.axios
|
||||
.get(`${this.baseUrl}/c/restful/account`, {
|
||||
.get(`${this.baseUrl}/api/restful/account`, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
@ -278,7 +329,7 @@ export default class RestClient implements Client {
|
||||
deleteMaps(ids: number[]): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.delete(`${this.baseUrl}/c/restful/maps/batch?ids=${ids.join()}`, {
|
||||
.delete(`${this.baseUrl}/api/restful/maps/batch?ids=${ids.join()}`, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
@ -296,7 +347,7 @@ export default class RestClient implements Client {
|
||||
updateMapToPublic(id: number, isPublic: boolean): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.put(`${this.baseUrl}/c/restful/maps/${id}/publish`, isPublic.toString(), {
|
||||
.put(`${this.baseUrl}/api/restful/maps/${id}/publish`, isPublic.toString(), {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
@ -313,7 +364,7 @@ export default class RestClient implements Client {
|
||||
revertHistory(id: number, hid: number): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.post(`${this.baseUrl}/c/restful/maps/${id}/history/${hid}`, null, {
|
||||
.post(`${this.baseUrl}/api/restful/maps/${id}/history/${hid}`, null, {
|
||||
headers: { 'Content-Type': 'text/pain' },
|
||||
})
|
||||
.then(() => {
|
||||
@ -333,7 +384,7 @@ export default class RestClient implements Client {
|
||||
reject: (error: ErrorInfo) => void,
|
||||
) => {
|
||||
this.axios
|
||||
.get(`${this.baseUrl}/c/restful/maps/${id}/history/`, {
|
||||
.get(`${this.baseUrl}/api/restful/maps/${id}/history/`, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
@ -358,12 +409,12 @@ export default class RestClient implements Client {
|
||||
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.put(`${this.baseUrl}/c/restful/maps/${id}/title`, basicInfo.title, {
|
||||
.put(`${this.baseUrl}/api/restful/maps/${id}/title`, basicInfo.title, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
return this.axios.put(
|
||||
`${this.baseUrl}/c/restful/maps/${id}/description`,
|
||||
`${this.baseUrl}/api/restful/maps/${id}/description`,
|
||||
basicInfo.description || ' ',
|
||||
{ headers: { 'Content-Type': 'text/plain' } },
|
||||
);
|
||||
@ -385,10 +436,10 @@ export default class RestClient implements Client {
|
||||
const handler = (success: (mapId: number) => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.post(
|
||||
`${this.baseUrl}/c/restful/maps?title=${encodeURIComponent(
|
||||
`${this.baseUrl}/api/restful/maps?title=${encodeURIComponent(
|
||||
model.title,
|
||||
)}&description=${encodeURIComponent(model.description ? model.description : '')}`,
|
||||
null,
|
||||
undefined,
|
||||
{ headers: { 'Content-Type': 'application/json' } },
|
||||
)
|
||||
.then((response) => {
|
||||
@ -409,7 +460,7 @@ export default class RestClient implements Client {
|
||||
reject: (error: ErrorInfo) => void,
|
||||
) => {
|
||||
this.axios
|
||||
.get(`${this.baseUrl}/c/restful/maps/`, {
|
||||
.get(`${this.baseUrl}/api/restful/maps/`, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
@ -443,7 +494,7 @@ export default class RestClient implements Client {
|
||||
registerNewUser(user: NewUser): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.post(`${this.baseUrl}/service/users/`, JSON.stringify(user), {
|
||||
.post(`${this.baseUrl}/api/restful/users/`, JSON.stringify(user), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then(() => {
|
||||
@ -461,7 +512,7 @@ export default class RestClient implements Client {
|
||||
deleteMap(id: number): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.delete(`${this.baseUrl}/c/restful/maps/${id}`, {
|
||||
.delete(`${this.baseUrl}/api/restful/maps/${id}`, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then(() => {
|
||||
@ -482,7 +533,7 @@ export default class RestClient implements Client {
|
||||
) => {
|
||||
this.axios
|
||||
.put(
|
||||
`${this.baseUrl}/service/users/resetPassword?email=${encodeURIComponent(email)}`,
|
||||
`${this.baseUrl}/api/restful/users/resetPassword?email=${encodeURIComponent(email)}`,
|
||||
null,
|
||||
{
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
@ -504,7 +555,7 @@ export default class RestClient implements Client {
|
||||
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number> {
|
||||
const handler = (success: (mapId: number) => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.post(`${this.baseUrl}/c/restful/maps/${id}`, JSON.stringify(basicInfo), {
|
||||
.post(`${this.baseUrl}/api/restful/maps/${id}`, JSON.stringify(basicInfo), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
@ -523,7 +574,7 @@ export default class RestClient implements Client {
|
||||
updateStarred(id: number, starred: boolean): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.put(`${this.baseUrl}/c/restful/maps/${id}/starred`, starred.toString(), {
|
||||
.put(`${this.baseUrl}/api/restful/maps/${id}/starred`, starred.toString(), {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
@ -541,7 +592,7 @@ export default class RestClient implements Client {
|
||||
fetchLabels(): Promise<Label[]> {
|
||||
const handler = (success: (labels: Label[]) => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.get(`${this.baseUrl}/c/restful/labels/`, {
|
||||
.get(`${this.baseUrl}/api/restful/labels/`, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
@ -569,7 +620,7 @@ export default class RestClient implements Client {
|
||||
const handler = (success: (labelId: number) => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.post(
|
||||
`${this.baseUrl}/c/restful/labels`,
|
||||
`${this.baseUrl}/api/restful/labels`,
|
||||
JSON.stringify({ title, color, iconName: 'smile' }),
|
||||
{
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
@ -590,7 +641,7 @@ export default class RestClient implements Client {
|
||||
deleteLabel(id: number): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.delete(`${this.baseUrl}/c/restful/labels/${id}`)
|
||||
.delete(`${this.baseUrl}/api/restful/labels/${id}`)
|
||||
.then(() => {
|
||||
success();
|
||||
})
|
||||
@ -605,7 +656,7 @@ export default class RestClient implements Client {
|
||||
addLabelToMap(labelId: number, mapId: number): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.post(`${this.baseUrl}/c/restful/maps/${mapId}/labels`, JSON.stringify(labelId), {
|
||||
.post(`${this.baseUrl}/api/restful/maps/${mapId}/labels`, JSON.stringify(labelId), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then(() => {
|
||||
@ -622,7 +673,7 @@ export default class RestClient implements Client {
|
||||
deleteLabelFromMap(labelId: number, mapId: number): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.delete(`${this.baseUrl}/c/restful/maps/${mapId}/labels/${labelId}`)
|
||||
.delete(`${this.baseUrl}/api/restful/maps/${mapId}/labels/${labelId}`)
|
||||
.then(() => {
|
||||
success();
|
||||
})
|
||||
@ -640,7 +691,7 @@ export default class RestClient implements Client {
|
||||
reject: (error: ErrorInfo) => void,
|
||||
) => {
|
||||
this.axios
|
||||
.post(`${this.baseUrl}/service/oauth2/googlecallback?code=${code}`, {
|
||||
.post(`${this.baseUrl}/api/restful/oauth2/googlecallback?code=${code}`, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
@ -661,7 +712,7 @@ export default class RestClient implements Client {
|
||||
confirmAccountSync(email: string, code: string): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.put(`${this.baseUrl}/service/oauth2/confirmaccountsync?email=${email}&code=${code}`, {
|
||||
.put(`${this.baseUrl}/api/restful/oauth2/confirmaccountsync?email=${email}&code=${code}`, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then(() => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { Link as RouterLink, useNavigate } from 'react-router-dom';
|
||||
import Header from '../layout/header';
|
||||
import Footer from '../layout/footer';
|
||||
import SubmitButton from '../form/submit-button';
|
||||
@ -15,6 +15,17 @@ import Separator from '../common/separator';
|
||||
import GoogleButton from '../common/google-button';
|
||||
import AppConfig from '../../classes/app-config';
|
||||
import CSRFInput from '../common/csrf-input';
|
||||
import { useMutation } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Client, { ErrorInfo } from '../../classes/client';
|
||||
import { activeInstance } from '../../redux/clientSlice';
|
||||
|
||||
export type Model = {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
const defaultModel: Model = { email: '', password: '' };
|
||||
|
||||
const LoginError = () => {
|
||||
// @Todo: This must be reviewed to be based on navigation state.
|
||||
@ -44,6 +55,9 @@ const LoginError = () => {
|
||||
|
||||
const LoginPage = (): React.ReactElement => {
|
||||
const intl = useIntl();
|
||||
const [model, setModel] = useState<Model>(defaultModel);
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
document.title = intl.formatMessage({
|
||||
@ -53,6 +67,29 @@ const LoginPage = (): React.ReactElement => {
|
||||
ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: 'Login' });
|
||||
}, []);
|
||||
|
||||
const mutation = useMutation<void, ErrorInfo, Model>(
|
||||
(model: Model) => client.login({ ...model }),
|
||||
{
|
||||
onSuccess: () => navigate('/c/maps/'),
|
||||
onError: (error) => {
|
||||
console.log(error);
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
|
||||
mutation.mutate(model);
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
event.preventDefault();
|
||||
|
||||
const name = event.target.name;
|
||||
const value = event.target.value;
|
||||
setModel({ ...model, [name as keyof Model]: value });
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Header type="only-signup" />
|
||||
@ -69,10 +106,11 @@ const LoginPage = (): React.ReactElement => {
|
||||
<LoginError />
|
||||
|
||||
<FormControl>
|
||||
<form action="/c/perform-login" method="POST">
|
||||
<form onSubmit={handleOnSubmit}>
|
||||
<CSRFInput />
|
||||
<Input
|
||||
name="username"
|
||||
onChange={handleOnChange}
|
||||
name="email"
|
||||
type="email"
|
||||
label={intl.formatMessage({
|
||||
id: 'login.email',
|
||||
@ -82,6 +120,7 @@ const LoginPage = (): React.ReactElement => {
|
||||
autoComplete="email"
|
||||
/>
|
||||
<Input
|
||||
onChange={handleOnChange}
|
||||
name="password"
|
||||
type="password"
|
||||
label={intl.formatMessage({
|
||||
@ -91,12 +130,6 @@ const LoginPage = (): React.ReactElement => {
|
||||
required
|
||||
autoComplete="current-password"
|
||||
/>
|
||||
<div>
|
||||
<input name="remember-me" id="remember-me" type="checkbox" />
|
||||
<label htmlFor="remember-me">
|
||||
<FormattedMessage id="login.remberme" defaultMessage="Remember me" />
|
||||
</label>
|
||||
</div>
|
||||
<SubmitButton
|
||||
value={intl.formatMessage({
|
||||
id: 'login.signin',
|
||||
|
@ -41,9 +41,9 @@ const RegistrationForm = () => {
|
||||
const navigate = useNavigate();
|
||||
const intl = useIntl();
|
||||
|
||||
const Client: Client = useSelector(activeInstance);
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const mutation = useMutation<void, ErrorInfo, Model>(
|
||||
(model: Model) => Client.registerNewUser({ ...model }),
|
||||
(model: Model) => client.registerNewUser({ ...model }),
|
||||
{
|
||||
onSuccess: () => navigate('/c/registration-success'),
|
||||
onError: (error) => {
|
||||
|
@ -10,6 +10,18 @@ module.exports = merge(common, {
|
||||
devServer: {
|
||||
port: 3000,
|
||||
hot: true,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: {
|
||||
host: "0.0.0.0",
|
||||
protocol: 'http:',
|
||||
port: 8080
|
||||
},
|
||||
pathRewrite: {
|
||||
'^/api': ''
|
||||
}
|
||||
},
|
||||
},
|
||||
historyApiFallback: {
|
||||
rewrites: [{ from: /^\/c\//, to: '/index.html' }],
|
||||
},
|
||||
@ -19,6 +31,7 @@ module.exports = merge(common, {
|
||||
template: path.join(__dirname, 'public/index.html'),
|
||||
templateParameters: {
|
||||
PUBLIC_URL: process.env.PUBLIC_URL ? process.env.PUBLIC_URL : 'http://localhost:3000',
|
||||
CLIENT_TYPE: process.env.CLIENT_TYPE ? process.env.CLIENT_TYPE : 'mock'
|
||||
},
|
||||
base: process.env.PUBLIC_URL ? process.env.PUBLIC_URL : 'http://localhost:3000',
|
||||
}),
|
||||
|
Loading…
Reference in New Issue
Block a user