Merge pull request #690 from ONLYOFFICE/feature/session-lifetime

Feature/session lifetime
This commit is contained in:
Viktor Fomin 2022-06-07 13:44:57 +03:00 committed by GitHub
commit b60d59fc7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 281 additions and 4 deletions

View File

@ -101,6 +101,13 @@ export function setCookieSettings(lifeTime) {
});
}
export function getCookieSettings() {
return request({
method: "get",
url: "/settings/cookiesettings.json",
});
}
export function setLifetimeAuditSettings(data) {
return request({
method: "post",

View File

@ -32,6 +32,7 @@ class SettingsStore {
trustedDomainsType = 0;
ipRestrictionEnable = false;
ipRestrictions = [];
sessionLifetime = "1440";
timezone = "UTC";
timezones = [];
tenantAlias = "";
@ -509,6 +510,16 @@ class SettingsStore {
this.enableAdmMess = turnOn;
};
getSessionLifetime = async () => {
const res = await api.settings.getCookieSettings();
this.sessionLifetime = res;
};
setSessionLifetimeSettings = async (lifeTime) => {
const res = await api.settings.setCookieSettings(lifeTime);
this.sessionLifetime = lifeTime;
};
setIsBurgerLoading = (isBurgerLoading) => {
this.isBurgerLoading = isBurgerLoading;
};

View File

@ -80,6 +80,7 @@
"LanguageTimeSettingsTooltip": "<0>{{text}}</0> is a way to change the language of the whole portal for all portal users and to configure the time zone so that all the events of the ONLYOFFICE portal will be shown with the correct date and time.",
"LanguageTimeSettingsTooltipDescription": "To make the parameters you set take effect click the <1>{{save}}</1> button at the bottom of the section.<3>{{learnMore}}</3>",
"LocalFile": "Local file",
"Lifetime": "Lifetime (min)",
"LogoDark": "Logo for the About/Login page",
"LogoDocsEditor": "Logo for the editors header",
"LogoFavicon": "Favicon",
@ -130,6 +131,11 @@
"SendNotificationAboutRestoring": "Send notification about portal restoring to users",
"ServerSideEncryptionMethod": "Server Side Encryption Method",
"ServiceUrl": "Service Url",
"RecoveryFileNotSelected": "Recovery error. Recovery file not selected",
"SessionLifetime": "Session Lifetime",
"SessionLifetimeDescription": "Session Lifetime allows to set time (in minutes) before the portal users will need to enter the portal credentials again in order to access the portal.",
"SessionLifetimeHelper": "After save all the users will be logged out from portal.",
"SetDefaultTitle": "Set default title",
"SettingPasswordStrength": "Setting password strength",
"SettingPasswordStrengthDescription": "Password Strength Settings is a way to determine the effectiveness of a password in resisting guessing and brute-force attacks.",
"SettingPasswordStrengthHelper": "Use the Minimum Password Length bar to determine how long the password should be. Check the appropriate boxes below to determine the character set that must be used in the password.",

View File

@ -9,6 +9,7 @@ import PasswordStrengthSection from "./passwordStrength";
import TrustedMailSection from "./trustedMail";
import IpSecuritySection from "./ipSecurity";
import AdminMessageSection from "./adminMessage";
import SessionLifetimeSection from "./sessionLifetime";
import MobileView from "./mobileView";
import CategoryWrapper from "../sub-components/category-wrapper";
import { size } from "@appserver/components/utils/device";
@ -76,6 +77,14 @@ const AccessPortal = (props) => {
tooltipUrl={`https://helpcenter.onlyoffice.com/${lng}/administration/configuration.aspx#ChangingSecuritySettings_block`}
/>
<AdminMessageSection />
<hr />
<CategoryWrapper
t={t}
title={t("SessionLifetime")}
tooltipTitle={t("SessionLifetimeDescription")}
/>
<SessionLifetimeSection />
</MainContainer>
);
};

View File

@ -49,6 +49,12 @@ const MobileView = (props) => {
url="/settings/security/access-portal/admin-message"
onClickLink={onClickLink}
/>
<MobileCategoryWrapper
title={t("SessionLifetime")}
subtitle={t("SessionLifetimeDescription")}
url="/settings/security/access-portal/lifetime"
onClickLink={onClickLink}
/>
</MainContainer>
);
};

View File

@ -0,0 +1,223 @@
import React, { useState, useEffect } from "react";
import styled from "styled-components";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import RadioButtonGroup from "@appserver/components/radio-button-group";
import Text from "@appserver/components/text";
import TextInput from "@appserver/components/text-input";
import toastr from "@appserver/components/toast/toastr";
import { LearnMoreWrapper } from "../StyledSecurity";
import { size } from "@appserver/components/utils/device";
import { saveToSessionStorage, getFromSessionStorage } from "../../../utils";
import SaveCancelButtons from "@appserver/components/save-cancel-buttons";
import isEqual from "lodash/isEqual";
const MainContainer = styled.div`
width: 100%;
.lifetime {
margin-top: 16px;
margin-bottom: 8px;
}
.save-cancel-buttons {
margin-top: 24px;
}
`;
const SessionLifetime = (props) => {
const {
t,
history,
lifetime,
setSessionLifetimeSettings,
initSettings,
isInit,
} = props;
const [type, setType] = useState(false);
const [sessionLifetime, setSessionLifetime] = useState("0");
const [showReminder, setShowReminder] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(false);
const getSettings = () => {
const currentSettings = getFromSessionStorage(
"currentSessionLifetimeSettings"
);
const defaultData = {
lifetime: lifetime.toString(),
type: lifetime > 0 ? true : false,
};
saveToSessionStorage("defaultSessionLifetimeSettings", defaultData);
if (currentSettings) {
setSessionLifetime(currentSettings.lifetime);
setType(currentSettings.type);
} else {
setSessionLifetime(lifetime.toString());
setType(lifetime > 0 ? true : false);
}
if (currentSettings) {
setType(currentSettings.type);
setSessionLifetime(currentSettings.lifetime);
} else {
setType(lifetime > 0 ? true : false);
setSessionLifetime(lifetime.toString());
}
setIsLoading(true);
};
useEffect(() => {
checkWidth();
if (!isInit) initSettings().then(() => setIsLoading(true));
else setIsLoading(true);
window.addEventListener("resize", checkWidth);
return () => window.removeEventListener("resize", checkWidth);
}, []);
useEffect(() => {
if (!isInit) return;
getSettings();
}, [isLoading]);
useEffect(() => {
if (!isLoading) return;
const defaultSettings = getFromSessionStorage(
"defaultSessionLifetimeSettings"
);
const newSettings = {
lifetime: sessionLifetime,
type: type,
};
saveToSessionStorage("currentSessionLifetimeSettings", newSettings);
if (isEqual(defaultSettings, newSettings)) {
setShowReminder(false);
} else {
setShowReminder(true);
}
}, [type, sessionLifetime]);
const checkWidth = () => {
window.innerWidth > size.smallTablet &&
history.location.pathname.includes("lifetime") &&
history.push("/settings/security/access-portal");
};
const onSelectType = (e) => {
setType(e.target.value === "enable" ? true : false);
};
const onChangeInput = (e) => {
setSessionLifetime(e.target.value);
};
const onBlurInput = () => {
!sessionLifetime ? setError(true) : setError(false);
};
const onFocusInput = () => {
setError(false);
};
const onSaveClick = async () => {
if (error) return;
try {
setSessionLifetimeSettings(sessionLifetime);
toastr.success(t("SuccessfullySaveSettingsMessage"));
saveToSessionStorage("defaultSessionLifetimeSettings", {
lifetime: lifetime,
type: type,
});
setShowReminder(false);
} catch (error) {
toastr.error(error);
}
};
const onCancelClick = () => {
const defaultSettings = getFromSessionStorage(
"defaultSessionLifetimeSettings"
);
setType(defaultSettings.type);
setSessionLifetime(defaultSettings.lifetime);
setShowReminder(false);
};
return (
<MainContainer>
<LearnMoreWrapper>
<Text>{t("SessionLifetimeHelper")}</Text>
</LearnMoreWrapper>
<RadioButtonGroup
className="box"
fontSize="13px"
fontWeight="400"
name="group"
orientation="vertical"
spacing="8px"
options={[
{
label: t("Disabled"),
value: "disabled",
},
{
label: t("Common:Enable"),
value: "enable",
},
]}
selected={type ? "enable" : "disabled"}
onClick={onSelectType}
/>
{type && (
<>
<Text className="lifetime" fontSize="15px" fontWeight="600">
{t("Lifetime")}
</Text>
<TextInput
isAutoFocussed={true}
value={sessionLifetime}
onChange={onChangeInput}
onBlur={onBlurInput}
onFocus={onFocusInput}
hasError={error}
/>
</>
)}
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onSaveClick}
onCancelClick={onCancelClick}
showReminder={showReminder}
reminderTest={t("YouHaveUnsavedChanges")}
saveButtonLabel={t("Common:SaveButton")}
cancelButtonLabel={t("Common:CancelButton")}
displaySettings={true}
hasScroll={false}
/>
</MainContainer>
);
};
export default inject(({ auth, setup }) => {
const { sessionLifetime, setSessionLifetimeSettings } = auth.settingsStore;
const { initSettings, isInit } = setup;
return {
lifetime: sessionLifetime,
setSessionLifetimeSettings,
initSettings,
isInit,
};
})(
withTranslation(["Settings", "Common"])(withRouter(observer(SessionLifetime)))
);

View File

@ -20,6 +20,9 @@ const IpSecurityPage = lazy(() =>
const AdminMessagePage = lazy(() =>
import("./categories/security/access-portal/adminMessage")
);
const SessionLifetimePage = lazy(() =>
import("./categories/security/access-portal/sessionLifetime")
);
const CommonSettings = lazy(() => import("./categories/common/index.js"));
@ -106,6 +109,10 @@ const ADMIN_MESSAGE_PAGE_URL = combineUrl(
PROXY_BASE_URL,
"/security/access-portal/admin-message"
);
const SESSION_LIFETIME_PAGE_URL = combineUrl(
PROXY_BASE_URL,
"/security/access-portal/lifetime"
);
const ADMINS_URL = combineUrl(PROXY_BASE_URL, "/security/access-rights/admins");
const THIRD_PARTY_URL = combineUrl(
@ -166,6 +173,11 @@ const Settings = (props) => {
path={ADMIN_MESSAGE_PAGE_URL}
component={AdminMessagePage}
/>
<Route
exact
path={SESSION_LIFETIME_PAGE_URL}
component={SessionLifetimePage}
/>
<Route exact path={THIRD_PARTY_URL} component={ThirdPartyServices} />
<Route

View File

@ -89,6 +89,12 @@ export const settingsTree = [
link: "admin-message",
tKey: "AdminsMessage",
},
{
key: "1-0-5",
icon: "",
link: "lifetime",
tKey: "SessionLifetime",
},
],
},
{

View File

@ -55,6 +55,7 @@ class SettingsSetupStore {
await authStore.tfaStore.getTfaType();
await authStore.settingsStore.getIpRestrictionsEnable();
await authStore.settingsStore.getIpRestrictions();
await authStore.settingsStore.getSessionLifetime();
}
};
@ -218,10 +219,6 @@ class SettingsSetupStore {
const res = await api.settings.setMailDomainSettings(dnsName, enable);
};
setCookieSettings = async (lifeTime) => {
const res = await api.settings.setCookieSettings(lifeTime);
};
setLifetimeAuditSettings = async (data) => {
const res = await api.settings.setLifetimeAuditSettings(data);
};