diff --git a/client/src/App.tsx b/client/src/App.tsx
index 82fc9b7..23e38c3 100644
--- a/client/src/App.tsx
+++ b/client/src/App.tsx
@@ -1,22 +1,21 @@
import React, { useContext, useEffect } from 'react';
+import { createBrowserRouter, RouteObject, RouterProvider } from 'react-router-dom';
+import AuthContext from './context/AuthContext';
-// Styles
-import './styles/custom.scss';
-
-// Interfaces
-import { createBrowserRouter, RouterProvider } from 'react-router-dom';
-import Landing from './views/Landing';
+import BrowserRoutes from './routes';
import ProtectedRoute from './routes/ProtectedRoute';
import Layout from './layout/PrivateLayout';
-import browserRoutes from './routes';
-import NotFound from './views/NotFound';
-import AuthContext from './context/AuthContext';
+
+import Landing from './views/Landing';
import Login from './views/Login';
+import NotFound from './views/NotFound';
+
+import './styles/custom.scss';
const App: React.FC = () => {
const { signed, checkCurrentAuthUser } = useContext(AuthContext);
- const notSignedRouter = createBrowserRouter([
+ const notSignedRouter: RouteObject[] = [
{
path: '/',
element:
@@ -29,38 +28,42 @@ const App: React.FC = () => {
path: '*',
element:
}
- ]);
+ ];
- const signedRouter = createBrowserRouter([
+ const signedRouter: RouteObject[] = [
{
- path: '/',
+ path: '/', // ROUTES.ROOT='/'
element: ,
children: [
{
element: ,
- children: browserRoutes
+ children: BrowserRoutes
}
]
},
{
- path: '*',
+ path: '*', // ROUTES.ALL_ROUTES='*'
element:
}
- ]);
+ ];
- const getBrowserRoutes = () => {
+ const getBrowserRouter = () => {
if (signed) {
- return signedRouter;
+ console.log('app signed');
+ return createBrowserRouter(signedRouter);
}
- return notSignedRouter;
+ console.log('app not signed');
+ return createBrowserRouter(notSignedRouter);
};
+ const browserRouter = getBrowserRouter();
+
useEffect(() => {
checkCurrentAuthUser(window.location.pathname);
}, []);
return (
-
+
);
};
diff --git a/client/src/api-service/apiConfig.ts b/client/src/api-service/apiConfig.ts
index 5dcd540..e81b1b3 100644
--- a/client/src/api-service/apiConfig.ts
+++ b/client/src/api-service/apiConfig.ts
@@ -1,36 +1,74 @@
+import { API_TOKEN } from '../app-constants/app-constants';
import { env } from '../env';
-import { User } from '../types/User';
+import { SigninResponse } from '../types/SigninResponse';
const server = env.VITE_BACKEND_SERVER;
/**
*
*/
-function privateSessionFake(signed: boolean): Promise {
- return new Promise((resolve, reject) => {
- if (signed) {
- resolve({
- name: 'User',
- email: 'email@domain.com'
- });
+async function privateSessionState(signed: boolean): Promise {
+ const tokenState = localStorage.getItem(API_TOKEN);
+
+ if (signed && tokenState) {
+ const response = await fetch(ApiConfig.refreshTokenUrl, {
+ method: 'GET',
+ mode: 'cors',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${tokenState}`
+ }
+ });
+
+ if (response.ok) {
+ const data = await response.json();
+ localStorage.setItem(API_TOKEN, data.token);
+ return {
+ token: data.token
+ };
} else {
- reject();
+ console.error(response);
}
- });
+ }
+ return Promise.reject();
}
const ApiConfig = {
- login: `${server}/login`,
+ signinUrl: `${server}/auth/signin`,
- loginFake: async (): Promise => new Promise((resolve) => {
- resolve();
- }),
+ refreshTokenUrl: `${server}/rest/user-sessions/refresh`,
+
+ signin: async (email: string, password: string): Promise => {
+ try {
+ const response = await fetch(ApiConfig.signinUrl, {
+ method: 'POST',
+ mode: 'cors',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({ email, password })
+ });
+
+ if (response.ok) {
+ const data = await response.json();
+ localStorage.setItem(API_TOKEN, data.token);
+ return {
+ token: data.token
+ };
+ } else {
+ console.error('signin error', response);
+ }
+ }
+ catch (error) {
+ console.error(error);
+ }
+ },
logoutFake: async (): Promise => new Promise((resolve) => {
resolve();
}),
- currentSessionFake: privateSessionFake
+ currentSessionState: privateSessionState
};
export default ApiConfig;
diff --git a/client/src/app-constants/app-constants.ts b/client/src/app-constants/app-constants.ts
index 6175102..19fca9f 100644
--- a/client/src/app-constants/app-constants.ts
+++ b/client/src/app-constants/app-constants.ts
@@ -1 +1,3 @@
export const REDIRECT_PATH = 'TASKNOTE-REDIRECT';
+export const API_TOKEN = 'TASKNOTE-TOKEN';
+export const USER_DATA = 'TASKNOTE-USER';
diff --git a/client/src/context/AuthContext.ts b/client/src/context/AuthContext.ts
index 9bc9a09..ad0fc7a 100644
--- a/client/src/context/AuthContext.ts
+++ b/client/src/context/AuthContext.ts
@@ -5,7 +5,7 @@ export interface AuthContextData {
signed: boolean;
user: User | undefined;
checkCurrentAuthUser: (pathname: string) => Promise;
- signIn: () => void;
+ signIn: (email: string, password: string) => void;
signOut: () => void;
isAdmin: boolean;
}
diff --git a/client/src/context/AuthProvider.tsx b/client/src/context/AuthProvider.tsx
index 7ff7529..6d5d1e9 100644
--- a/client/src/context/AuthProvider.tsx
+++ b/client/src/context/AuthProvider.tsx
@@ -4,7 +4,8 @@ import { User } from '../types/User';
import { env } from '../env';
import ApiConfig from '../api-service/apiConfig';
import AuthContext, { AuthContextData } from './AuthContext';
-import { REDIRECT_PATH } from '../app-constants/app-constants';
+import { API_TOKEN, REDIRECT_PATH, USER_DATA } from '../app-constants/app-constants';
+import { SigninResponse } from '../types/SigninResponse';
interface Props {
children: React.ReactNode;
@@ -16,13 +17,13 @@ const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }: Pro
const [isAdmin, setIsAdmin] = useState(false);
const [intervalInstance, setIntervalInstance] = useState(null);
- const fetchCurrentSession = async (pathname: string): Promise => {
+ const fetchCurrentSession = async (pathname: string): Promise => {
try {
- const currentUser = await ApiConfig.currentSessionFake(signed);
- if (currentUser) {
+ const bearerToken: SigninResponse | undefined = await ApiConfig.currentSessionState(signed);
+ if (bearerToken && bearerToken.token) {
setSigned(true);
}
- return currentUser;
+ return bearerToken;
} catch (e) {
if (e instanceof Error) {
console.warn(e.message);
@@ -38,28 +39,35 @@ const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }: Pro
return undefined;
};
- const updateUserSession = (userPriv: User) => {
- localStorage.setItem('TaskNote-token', userPriv.email);
+ const updateUserSession = (userPriv: User | null, bearerToken: string) => {
+ if (userPriv) {
+ localStorage.setItem(USER_DATA, JSON.stringify(userPriv));
+ }
+ localStorage.setItem(API_TOKEN, bearerToken);
};
const checkCurrentAuthUser = async (pathname: string): Promise => {
- const currentUser = await fetchCurrentSession(pathname);
- if (currentUser) {
- updateUserSession(currentUser);
- setUser(currentUser);
+ console.log('checkCurrentAuthUser', pathname);
+ const bearerToken: SigninResponse | undefined = await fetchCurrentSession(pathname);
+ if (bearerToken && bearerToken.token) {
+ console.log('checkCurrentAuthUser token', bearerToken);
+ updateUserSession(null, bearerToken.token);
}
};
- const signIn = async (): Promise => {
- const appEnv = env.VITE_ENV || 'dev';
- await ApiConfig.loginFake();
- setSigned(true);
- const currentUser: User = {
- name: `Ricardo ${appEnv}`,
- email: 'ricardompcampos@gmail.com'
- };
+ const signIn = async (email: string, password: string): Promise => {
+ const bearerToken: SigninResponse | undefined = await ApiConfig.signin(email, password);
+ if (bearerToken && bearerToken.token) {
+ const currentUser: User = {
+ email
+ };
- setUser(currentUser);
+ setSigned(true);
+ setUser(currentUser);
+ updateUserSession(currentUser, bearerToken.token);
+ return Promise.resolve();
+ }
+ return Promise.reject();
};
const signOut = async (): Promise => {
@@ -74,11 +82,12 @@ const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }: Pro
localStorage.clear();
};
- const refreshTokenPvt = async () => {
- const currentUser = await fetchCurrentSession('/');
- if (currentUser) {
- updateUserSession(currentUser);
+ const refreshTokenPvt = async (): Promise => {
+ const bearerToken: SigninResponse | undefined = await fetchCurrentSession('/');
+ if (bearerToken) {
+ updateUserSession(null, bearerToken.token);
}
+ return Promise.resolve();
};
// 2 minutes
diff --git a/client/src/layout/PrivateLayout/index.tsx b/client/src/layout/PrivateLayout/index.tsx
index 9048d41..a89c4b2 100644
--- a/client/src/layout/PrivateLayout/index.tsx
+++ b/client/src/layout/PrivateLayout/index.tsx
@@ -8,6 +8,7 @@ import Footer from '../../components/Footer';
*
*/
function Layout() {
+ console.log('Layout');
return (
<>
diff --git a/client/src/routes/index.tsx b/client/src/routes/index.tsx
index 79eda30..25dfd5e 100644
--- a/client/src/routes/index.tsx
+++ b/client/src/routes/index.tsx
@@ -5,7 +5,7 @@ import Home from '../views/Home';
import About from '../views/About';
import NotFound from '../views/NotFound';
-const browserRoutes: RouteObject[] = [
+const BrowserRoutes: RouteObject[] = [
{
path: '/',
element: (
@@ -38,4 +38,4 @@ const browserRoutes: RouteObject[] = [
}
];
-export default browserRoutes;
+export default BrowserRoutes;
diff --git a/client/src/types/SigninResponse.ts b/client/src/types/SigninResponse.ts
new file mode 100644
index 0000000..ce51a2b
--- /dev/null
+++ b/client/src/types/SigninResponse.ts
@@ -0,0 +1,3 @@
+export type SigninResponse = {
+ token: string
+}
diff --git a/client/src/types/User.ts b/client/src/types/User.ts
index ed349b9..0696b4f 100644
--- a/client/src/types/User.ts
+++ b/client/src/types/User.ts
@@ -1,4 +1,3 @@
export type User = {
- name: string;
email: string;
}
diff --git a/client/src/views/Home/index.tsx b/client/src/views/Home/index.tsx
index 4b1f73e..15aeed1 100644
--- a/client/src/views/Home/index.tsx
+++ b/client/src/views/Home/index.tsx
@@ -4,6 +4,8 @@ import React from 'react';
*
*/
function Home() {
+ console.log('This is home!');
+
return (
This is home!
);
diff --git a/client/src/views/Landing/index.tsx b/client/src/views/Landing/index.tsx
index 1b04833..6cc17f2 100644
--- a/client/src/views/Landing/index.tsx
+++ b/client/src/views/Landing/index.tsx
@@ -1,20 +1,35 @@
-import React from 'react';
+import React, { useContext, useEffect } from 'react';
import { Button } from 'react-bootstrap';
import './styles.scss';
import { useNavigate } from 'react-router-dom';
+import AuthContext from '../../context/AuthContext';
/**
*
*/
function Landing() {
+ const { signed, checkCurrentAuthUser } = useContext(AuthContext);
const navigate = useNavigate();
+ const handleLogin = () => {
+ console.log('Landing signed', signed);
+ if (signed) {
+ navigate('/home');
+ } else {
+ navigate('/signin');
+ }
+ };
+
+ useEffect(() => {
+ checkCurrentAuthUser(window.location.pathname);
+ }, []);
+
return (
<>
This is landing page
diff --git a/client/src/views/Login/index.tsx b/client/src/views/Login/index.tsx
index 68e9473..fb91988 100644
--- a/client/src/views/Login/index.tsx
+++ b/client/src/views/Login/index.tsx
@@ -1,7 +1,7 @@
import React, { useContext, useEffect, useState } from 'react';
-import { Button, Form } from 'react-bootstrap';
-import { FeedbackType } from 'react-bootstrap/esm/Feedback';
+import { Alert, Button, Col, Form } from 'react-bootstrap';
import AuthContext from '../../context/AuthContext';
+import { redirect } from 'react-router-dom';
/**
* Created the Login component.
@@ -9,98 +9,63 @@ import AuthContext from '../../context/AuthContext';
function Login() {
const { signIn } = useContext(AuthContext);
const [validated, setValidated] = useState(true);
- const [email, setEmail] = useState('');
- const [password, setPassword] = useState('');
- const [emailValidType, setEmailValidType] = useState('valid');
- const [emailValidMsg, setEmailValidMsg] = useState('Looks good!');
- const [passwordValidType, setPasswordValidType] = useState('valid');
- const [passwordValidMsg, setPasswordValidMsg] = useState('Looks good!');
+ const [formInvalid, setFormInvalid] = useState(false);
- const handleSubmit = (event: React.FormEvent) => {
+ const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
event.stopPropagation();
setValidated(true);
const form = event.currentTarget;
if (form.checkValidity() === false) {
- if (email.length === 0) {
- setEmailValidType('invalid');
- setEmailValidMsg('Please type your email!');
- } else {
- setEmailValidType('valid');
- setEmailValidMsg('Looks good!');
- }
-
- if (password.length === 0) {
- setPasswordValidType('invalid');
- setPasswordValidMsg('Please type your password!');
- } else {
- setPasswordValidType('valid');
- setPasswordValidMsg('Looks good!');
- }
-
+ console.log('something is invalid!');
+ setFormInvalid(true);
return;
}
- setEmailValidType('valid');
- setEmailValidMsg('Looks good!');
-
- setPasswordValidType('valid');
- setPasswordValidMsg('Looks good!');
- signIn();
+ setFormInvalid(false);
+ console.log(`email=${form.email.value}, password=${form.password.value}`);
+ await signIn(form.email.value, form.password.value);
+ console.log('finished!? login component!?');
+ redirect("/home");
};
- const resetForm = () => {
- setValidated(false);
- setEmail('');
- setEmailValidType('valid');
- setPassword('');
- setPasswordValidType('valid');
- };
-
- useEffect(() => {}, [validated]);
+ useEffect(() => {}, [formInvalid]);
return (
<>
This is login page
+
Email address
setEmail(e.target.value)}
- isInvalid={emailValidType === 'invalid'}
/>
-
- {emailValidMsg}
-
-
+
Password
setPassword(e.target.value)}
- isInvalid={passwordValidType === 'invalid'}
/>
-
- {passwordValidMsg}
-
-
+
+ {formInvalid ? (
+
+ Something is wrong! Check your email and password!
+
+ ) : null}
>
);
}