add token for secured resources
parent
89cf1fcd76
commit
bed8aec44f
|
@ -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();
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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 = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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";
|
||||||
|
|
||||||
|
|
|
@ -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 (
|
|
@ -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(
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
//export { useAuthorizationToken } from "./useAuthorizationToken";
|
import { useToast } from "../contexts/ToastContext";
|
||||||
|
import useResourceSecurity from "./useResourceSecurity";
|
||||||
|
|
||||||
|
export { useToast, useResourceSecurity };
|
||||||
|
|
|
@ -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;
|
|
@ -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(
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
Loading…
Reference in New Issue