add token for secured resources

master
Tudor Stanciu 2022-12-12 02:32:47 +02:00
parent 89cf1fcd76
commit bed8aec44f
15 changed files with 44 additions and 22 deletions

View File

@ -1,5 +1,5 @@
import { useCallback, useMemo } from "react"; import { useCallback, useMemo } from "react";
import { useToast } from "../context/ToastContext"; import { useToast } from "../contexts/ToastContext";
const useHttpRequest = () => { const useHttpRequest = () => {
const { error } = useToast(); const { error } = useToast();

View File

@ -9,8 +9,8 @@ import Error from "../pages/error";
import Login from "../pages/login"; import Login from "../pages/login";
// context // context
import { useUserState } from "../context/UserContext"; import { useUserState } from "../contexts/UserContext";
import { useToast } from "../context/ToastContext"; import { useToast } from "../contexts/ToastContext";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
export default function App() { export default function App() {

View File

@ -32,8 +32,8 @@ import {
useLayoutState, useLayoutState,
useLayoutDispatch, useLayoutDispatch,
toggleSidebar toggleSidebar
} from "../../context/LayoutContext"; } from "../../contexts/LayoutContext";
import { useUserDispatch, signOut } from "../../context/UserContext"; import { useUserDispatch, signOut } from "../../contexts/UserContext";
const messages = [ const messages = [
{ {

View File

@ -17,7 +17,7 @@ import ContentFooter from "./ContentFooter";
import ResourcesContainer from "../../features/resources/components/ResourcesContainer"; import ResourcesContainer from "../../features/resources/components/ResourcesContainer";
// context // context
import { useLayoutState } from "../../context/LayoutContext"; import { useLayoutState } from "../../contexts/LayoutContext";
// styles // styles
import useStyles from "./styles"; import useStyles from "./styles";

View File

@ -16,7 +16,7 @@ import {
useLayoutState, useLayoutState,
useLayoutDispatch, useLayoutDispatch,
toggleSidebar toggleSidebar
} from "../../context/LayoutContext"; } from "../../contexts/LayoutContext";
import menu from "./menu"; import menu from "./menu";

View File

@ -7,7 +7,7 @@ var UserDispatchContext = React.createContext();
function userReducer(state, action) { function userReducer(state, action) {
switch (action.type) { switch (action.type) {
case "LOGIN_SUCCESS": case "LOGIN_SUCCESS":
return { ...state, authenticated: true }; return { ...state, ...action.payload, authenticated: true };
case "SIGN_OUT_SUCCESS": case "SIGN_OUT_SUCCESS":
return { ...state, authenticated: false }; return { ...state, authenticated: false };
case "LOGIN_FAILURE": case "LOGIN_FAILURE":
@ -23,8 +23,10 @@ function userReducer(state, action) {
} }
function UserProvider({ children }) { function UserProvider({ children }) {
const { valid, token } = validateToken();
var [state, dispatch] = React.useReducer(userReducer, { var [state, dispatch] = React.useReducer(userReducer, {
authenticated: validateToken() === true authenticated: valid === true,
token
}); });
return ( return (

View File

@ -13,7 +13,7 @@ import {
FileCopyOutlined, FileCopyOutlined,
OpenInNewOutlined OpenInNewOutlined
} from "@material-ui/icons"; } from "@material-ui/icons";
import { useToast } from "../../../context/ToastContext"; import { useToast, useResourceSecurity } from "../../../hooks";
const __ROWS_PER_PAGE_OPTIONS = [10, 20, 50, 100]; const __ROWS_PER_PAGE_OPTIONS = [10, 20, 50, 100];
const __RESOURCE_NAME_MAX_LENGTH = 35; const __RESOURCE_NAME_MAX_LENGTH = 35;
@ -32,6 +32,7 @@ const ResourcesContainer = () => {
const { info } = useToast(); const { info } = useToast();
const { getResources } = useResourcesApi(); const { getResources } = useResourcesApi();
const { getResourceCategories } = useDictionariesApi(); const { getResourceCategories } = useDictionariesApi();
const { secureUrl } = useResourceSecurity();
useEffect(() => { useEffect(() => {
getResourceCategories().then((r) => setResourceCategories(r)); getResourceCategories().then((r) => setResourceCategories(r));
@ -81,7 +82,8 @@ const ResourcesContainer = () => {
{ {
code: "copy-url", code: "copy-url",
effect: (_event, resource) => { effect: (_event, resource) => {
navigator.clipboard.writeText(resource.url); const url = resource.secured ? secureUrl(resource.url) : resource.url;
navigator.clipboard.writeText(url);
info(t("Resource.List.Actions.LinkCopiedToClipboard")); info(t("Resource.List.Actions.LinkCopiedToClipboard"));
}, },
icon: FileCopyOutlined, icon: FileCopyOutlined,
@ -91,7 +93,8 @@ const ResourcesContainer = () => {
{ {
code: "open-in-new-tab", code: "open-in-new-tab",
effect: (event, resource) => { effect: (event, resource) => {
window.open(resource.url, "_blank"); const url = resource.secured ? secureUrl(resource.url) : resource.url;
window.open(url, "_blank");
event.preventDefault(); event.preventDefault();
}, },
icon: OpenInNewOutlined, icon: OpenInNewOutlined,
@ -99,7 +102,7 @@ const ResourcesContainer = () => {
top: false top: false
} }
], ],
[t, info] [t, info, secureUrl]
); );
const columns = useMemo( const columns = useMemo(

View File

@ -1 +1,4 @@
//export { useAuthorizationToken } from "./useAuthorizationToken"; import { useToast } from "../contexts/ToastContext";
import useResourceSecurity from "./useResourceSecurity";
export { useToast, useResourceSecurity };

View File

@ -0,0 +1,13 @@
import { useUserState } from "../contexts/UserContext";
import { useCallback } from "react";
const useResourceSecurity = () => {
const { token } = useUserState();
const secureUrl = useCallback((url) => `${url}?token=${token.raw}`, [
token.raw
]);
return { secureUrl };
};
export default useResourceSecurity;

View File

@ -5,9 +5,9 @@ import { CssBaseline } from "@material-ui/core";
import Themes from "./themes"; import Themes from "./themes";
import App from "./components/App"; import App from "./components/App";
import * as serviceWorker from "./serviceWorker"; import * as serviceWorker from "./serviceWorker";
import { LayoutProvider } from "./context/LayoutContext"; import { LayoutProvider } from "./contexts/LayoutContext";
import { UserProvider } from "./context/UserContext"; import { UserProvider } from "./contexts/UserContext";
import { ToastProvider } from "./context/ToastContext"; import { ToastProvider } from "./contexts/ToastContext";
import "./utils/i18n"; import "./utils/i18n";
ReactDOM.render( ReactDOM.render(

View File

@ -20,7 +20,7 @@ import logo from "./logo.svg";
import google from "../../images/google.svg"; import google from "../../images/google.svg";
// context // context
import { useUserDispatch, loginUser } from "../../context/UserContext"; import { useUserDispatch, loginUser } from "../../contexts/UserContext";
function Login(props) { function Login(props) {
var classes = useStyles(); var classes = useStyles();

View File

@ -16,7 +16,7 @@ import Notification from "../../components/Notification";
import { Typography, Button } from "../../components/Wrappers/Wrappers"; import { Typography, Button } from "../../components/Wrappers/Wrappers";
// context // context
import { useToast, useToastState } from "../../context/ToastContext"; import { useToast, useToastState } from "../../contexts/ToastContext";
export default function NotificationsPage(props) { export default function NotificationsPage(props) {
const classes = useStyles(); const classes = useStyles();

View File

@ -33,17 +33,18 @@ const invalidate = () => {
}; };
const validateToken = () => { const validateToken = () => {
const token = getItem(storageKeys.TOKEN); let token = getItem(storageKeys.TOKEN);
if (!token) { if (!token) {
return false; return { valid: false };
} }
const valid = new Date(token.validUntil) >= new Date(); const valid = new Date(token.validUntil) >= new Date();
if (!valid) { if (!valid) {
invalidate(); invalidate();
token = null;
} }
return valid; return { valid, token };
}; };
export { storageKeys, authenticate, invalidate, validateToken }; export { storageKeys, authenticate, invalidate, validateToken };