Merge branch 'release/v1.1.0' of github.com:ONLYOFFICE/AppServer into release/v1.1.0
This commit is contained in:
commit
39f172bd22
@ -37,6 +37,13 @@ while [ "$1" != "" ]; do
|
||||
fi
|
||||
;;
|
||||
|
||||
-skiphc | --skiphardwarecheck )
|
||||
if [ "$2" != "" ]; then
|
||||
SKIP_HARDWARE_CHECK=$2
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
|
||||
-? | -h | --help )
|
||||
echo " Usage $0 [PARAMETER] [[PARAMETER], ...]"
|
||||
echo " Parameters:"
|
||||
@ -60,6 +67,10 @@ if [ -z "${LOCAL_SCRIPTS}" ]; then
|
||||
LOCAL_SCRIPTS="false";
|
||||
fi
|
||||
|
||||
if [ -z "${SKIP_HARDWARE_CHECK}" ]; then
|
||||
SKIP_HARDWARE_CHECK="false";
|
||||
fi
|
||||
|
||||
if [ $(dpkg-query -W -f='${Status}' curl 2>/dev/null | grep -c "ok installed") -eq 0 ]; then
|
||||
apt-get update;
|
||||
apt-get install -yq curl;
|
||||
|
@ -6,6 +6,37 @@ command_exists () {
|
||||
type "$1" &> /dev/null;
|
||||
}
|
||||
|
||||
check_hardware () {
|
||||
DISK_REQUIREMENTS=40960;
|
||||
MEMORY_REQUIREMENTS=5500;
|
||||
CORE_REQUIREMENTS=2;
|
||||
|
||||
AVAILABLE_DISK_SPACE=$(df -m / | tail -1 | awk '{ print $4 }');
|
||||
|
||||
if [ ${AVAILABLE_DISK_SPACE} -lt ${DISK_REQUIREMENTS} ]; then
|
||||
echo "Minimal requirements are not met: need at least $DISK_REQUIREMENTS MB of free HDD space"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
TOTAL_MEMORY=$(free -m | grep -oP '\d+' | head -n 1);
|
||||
|
||||
if [ ${TOTAL_MEMORY} -lt ${MEMORY_REQUIREMENTS} ]; then
|
||||
echo "Minimal requirements are not met: need at least $MEMORY_REQUIREMENTS MB of RAM"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
CPU_CORES_NUMBER=$(cat /proc/cpuinfo | grep processor | wc -l);
|
||||
|
||||
if [ ${CPU_CORES_NUMBER} -lt ${CORE_REQUIREMENTS} ]; then
|
||||
echo "The system does not meet the minimal hardware requirements. CPU with at least $CORE_REQUIREMENTS cores is required"
|
||||
exit 1;
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$SKIP_HARDWARE_CHECK" != "true" ]; then
|
||||
check_hardware
|
||||
fi
|
||||
|
||||
ARCH="$(dpkg --print-architecture)"
|
||||
if [ "$ARCH" != "amd64" ]; then
|
||||
echo "ONLYOFFICE ${product^^} doesn't support architecture '$ARCH'"
|
||||
|
@ -47,6 +47,13 @@ while [ "$1" != "" ]; do
|
||||
fi
|
||||
;;
|
||||
|
||||
-skiphc | --skiphardwarecheck )
|
||||
if [ "$2" != "" ]; then
|
||||
SKIP_HARDWARE_CHECK=$2
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
|
||||
-? | -h | --help )
|
||||
echo " Usage $0 [PARAMETER] [[PARAMETER], ...]"
|
||||
echo " Parameters:"
|
||||
@ -69,6 +76,10 @@ if [ -z "${LOCAL_SCRIPTS}" ]; then
|
||||
LOCAL_SCRIPTS="false";
|
||||
fi
|
||||
|
||||
if [ -z "${SKIP_HARDWARE_CHECK}" ]; then
|
||||
SKIP_HARDWARE_CHECK="false";
|
||||
fi
|
||||
|
||||
cat > /etc/yum.repos.d/onlyoffice.repo <<END
|
||||
[onlyoffice]
|
||||
name=onlyoffice repo
|
||||
@ -91,11 +102,13 @@ END
|
||||
DOWNLOAD_URL_PREFIX="https://raw.githubusercontent.com/ONLYOFFICE/${product}/${GIT_BRANCH}/build/install/OneClickInstall/install-RedHat"
|
||||
|
||||
if [ "$LOCAL_SCRIPTS" = "true" ]; then
|
||||
source install-RedHat/tools.sh
|
||||
source install-RedHat/bootstrap.sh
|
||||
source install-RedHat/check-ports.sh
|
||||
source install-RedHat/install-preq.sh
|
||||
source install-RedHat/install-app.sh
|
||||
else
|
||||
source <(curl ${DOWNLOAD_URL_PREFIX}/tools.sh)
|
||||
source <(curl ${DOWNLOAD_URL_PREFIX}/bootstrap.sh)
|
||||
source <(curl ${DOWNLOAD_URL_PREFIX}/check-ports.sh)
|
||||
source <(curl ${DOWNLOAD_URL_PREFIX}/install-preq.sh)
|
||||
|
34
build/install/OneClickInstall/install-RedHat/tools.sh
Normal file
34
build/install/OneClickInstall/install-RedHat/tools.sh
Normal file
@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
check_hardware () {
|
||||
DISK_REQUIREMENTS=40960;
|
||||
MEMORY_REQUIREMENTS=5500;
|
||||
CORE_REQUIREMENTS=2;
|
||||
|
||||
AVAILABLE_DISK_SPACE=$(df -m / | tail -1 | awk '{ print $4 }');
|
||||
|
||||
if [ ${AVAILABLE_DISK_SPACE} -lt ${DISK_REQUIREMENTS} ]; then
|
||||
echo "Minimal requirements are not met: need at least $DISK_REQUIREMENTS MB of free HDD space"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
TOTAL_MEMORY=$(free -m | grep -oP '\d+' | head -n 1);
|
||||
|
||||
if [ ${TOTAL_MEMORY} -lt ${MEMORY_REQUIREMENTS} ]; then
|
||||
echo "Minimal requirements are not met: need at least $MEMORY_REQUIREMENTS MB of RAM"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
CPU_CORES_NUMBER=$(cat /proc/cpuinfo | grep processor | wc -l);
|
||||
|
||||
if [ ${CPU_CORES_NUMBER} -lt ${CORE_REQUIREMENTS} ]; then
|
||||
echo "The system does not meet the minimal hardware requirements. CPU with at least $CORE_REQUIREMENTS cores is required"
|
||||
exit 1;
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$SKIP_HARDWARE_CHECK" != "true" ]; then
|
||||
check_hardware
|
||||
fi
|
@ -811,3 +811,26 @@ export function fileCopyAs(fileId, destTitle, destFolderId, enableExternalExt) {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function getEditHistory(fileId, doc) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: `files/file/${fileId}/edit/history?doc=${doc}`,
|
||||
});
|
||||
}
|
||||
|
||||
export function getEditDiff(fileId, version, doc) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: `files/file/${fileId}/edit/diff?version=${version}&doc=${doc}`,
|
||||
});
|
||||
}
|
||||
|
||||
export function restoreDocumentsVersion(fileId, version, doc) {
|
||||
const options = {
|
||||
method: "get",
|
||||
url: `files/file/${fileId}/restoreversion?version=${version}&doc=${doc}`,
|
||||
};
|
||||
|
||||
return request(options);
|
||||
}
|
||||
|
@ -25,7 +25,11 @@ export function regDesktop(
|
||||
userId: user.id,
|
||||
};
|
||||
|
||||
console.log("regDesktop", data);
|
||||
console.log(
|
||||
"regDesktop date=",
|
||||
data,
|
||||
`isEncryption=${isEncryption} keys=${keys} isEditor=${isEditor}`
|
||||
);
|
||||
|
||||
let extendedData;
|
||||
|
||||
@ -80,6 +84,8 @@ export function regDesktop(
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
console.log("Created window.cloudCryptoCommand", window.cloudCryptoCommand);
|
||||
}
|
||||
|
||||
window.onSystemMessage = (e) => {
|
||||
@ -104,6 +110,8 @@ export function regDesktop(
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
console.log("Created window.onSystemMessage", window.onSystemMessage);
|
||||
}
|
||||
|
||||
export function relogin() {
|
||||
|
@ -7,16 +7,12 @@ import FilesListBody from "./FilesListBody";
|
||||
import Button from "@appserver/components/button";
|
||||
import Text from "@appserver/components/text";
|
||||
import { isArrayEqual } from "@appserver/components/utils/array";
|
||||
import { FolderType } from "@appserver/common/constants";
|
||||
import { getFoldersTree } from "@appserver/common/api/files";
|
||||
const exceptSortedByTagsFolders = [
|
||||
FolderType.Recent,
|
||||
FolderType.TRASH,
|
||||
FolderType.Favorites,
|
||||
];
|
||||
import {
|
||||
exceptSortedByTagsFolders,
|
||||
exceptPrivacyTrashFolders,
|
||||
} from "../SelectFolderDialog/ExceptionFoldersConstants";
|
||||
|
||||
const exceptTrashFolder = [FolderType.TRASH];
|
||||
const exceptPrivacyTrashFolders = [FolderType.Privacy, FolderType.TRASH];
|
||||
class SelectFileDialogModalView extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -59,20 +55,6 @@ class SelectFileDialogModalView extends React.Component {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
this.loadersCompletes();
|
||||
break;
|
||||
case "exceptTrashFolder":
|
||||
try {
|
||||
const foldersTree = await getFoldersTree();
|
||||
[
|
||||
this.folderList,
|
||||
this.noTreeSwitcher,
|
||||
] = SelectFolderDialog.convertFolders(foldersTree, exceptTrashFolder);
|
||||
this.onSetSelectedFolder();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
this.loadersCompletes();
|
||||
break;
|
||||
case "exceptPrivacyTrashFolders":
|
||||
|
@ -349,7 +349,6 @@ SelectFileDialogBody.propTypes = {
|
||||
"common",
|
||||
"third-party",
|
||||
"exceptSortedByTags",
|
||||
"exceptTrashFolder",
|
||||
"exceptPrivacyTrashFolders",
|
||||
]),
|
||||
folderId: PropTypes.string,
|
||||
|
@ -0,0 +1,10 @@
|
||||
import { FolderType } from "@appserver/common/constants";
|
||||
|
||||
export const exceptSortedByTagsFolders = [
|
||||
FolderType.Recent,
|
||||
FolderType.TRASH,
|
||||
FolderType.Favorites,
|
||||
FolderType.Privacy,
|
||||
];
|
||||
|
||||
export const exceptPrivacyTrashFolders = [FolderType.Privacy, FolderType.TRASH];
|
@ -23,6 +23,10 @@ import { FolderType } from "@appserver/common/constants";
|
||||
import { isArrayEqual } from "@appserver/components/utils/array";
|
||||
import store from "studio/store";
|
||||
import toastr from "studio/toastr";
|
||||
import {
|
||||
exceptSortedByTagsFolders,
|
||||
exceptPrivacyTrashFolders,
|
||||
} from "./ExceptionFoldersConstants";
|
||||
|
||||
const { auth: authStore } = store;
|
||||
|
||||
@ -31,14 +35,6 @@ const { desktop } = utils.device;
|
||||
let pathName = "";
|
||||
let folderList;
|
||||
|
||||
const exceptSortedByTagsFolders = [
|
||||
FolderType.Recent,
|
||||
FolderType.TRASH,
|
||||
FolderType.Favorites,
|
||||
];
|
||||
|
||||
const exceptTrashFolder = [FolderType.TRASH];
|
||||
const exceptPrivacyTrashFolders = [FolderType.Privacy, FolderType.TRASH];
|
||||
class SelectFolderModalDialog extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -116,6 +112,7 @@ class SelectFolderModalDialog extends React.Component {
|
||||
case "exceptSortedByTags":
|
||||
try {
|
||||
const foldersTree = await getFoldersTree();
|
||||
|
||||
[folderList, this.noTreeSwitcher] = SelectFolderDialog.convertFolders(
|
||||
foldersTree,
|
||||
exceptSortedByTagsFolders
|
||||
@ -126,19 +123,6 @@ class SelectFolderModalDialog extends React.Component {
|
||||
this.loadersCompletes();
|
||||
}
|
||||
break;
|
||||
case "exceptTrashFolder":
|
||||
try {
|
||||
const foldersTree = await getFoldersTree();
|
||||
[folderList, this.noTreeSwitcher] = SelectFolderDialog.convertFolders(
|
||||
foldersTree,
|
||||
exceptTrashFolder
|
||||
);
|
||||
this.setBaseSettings();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.loadersCompletes();
|
||||
}
|
||||
break;
|
||||
case "exceptPrivacyTrashFolders":
|
||||
try {
|
||||
const foldersTree = await getFoldersTree();
|
||||
@ -146,13 +130,13 @@ class SelectFolderModalDialog extends React.Component {
|
||||
foldersTree,
|
||||
exceptPrivacyTrashFolders
|
||||
);
|
||||
console.log("folderList", folderList);
|
||||
this.setBaseSettings();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.loadersCompletes();
|
||||
}
|
||||
break;
|
||||
|
||||
case "common":
|
||||
try {
|
||||
folderList = await SelectFolderDialog.getCommonFolders();
|
||||
@ -550,7 +534,6 @@ SelectFolderModalDialog.propTypes = {
|
||||
"common",
|
||||
"third-party",
|
||||
"exceptSortedByTags",
|
||||
"exceptTrashFolder",
|
||||
"exceptPrivacyTrashFolders",
|
||||
]),
|
||||
displayType: PropTypes.oneOf(["aside", "modal"]),
|
||||
|
@ -97,7 +97,7 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
services.TryAdd<ILinkDao, LinkDao>();
|
||||
|
||||
// AddSharpBoxDaoSelectorService
|
||||
services.TryAdd<EditHistory>();
|
||||
}
|
||||
}
|
||||
}
|
@ -1202,14 +1202,12 @@ namespace ASC.Files.Core.Data
|
||||
.Select(r =>
|
||||
{
|
||||
var item = ServiceProvider.GetService<EditHistory>();
|
||||
var editHistoryAuthor = ServiceProvider.GetService<EditHistoryAuthor>();
|
||||
|
||||
editHistoryAuthor.Id = r.ModifiedBy;
|
||||
item.ID = r.Id;
|
||||
item.Version = r.Version;
|
||||
item.VersionGroup = r.VersionGroup;
|
||||
item.ModifiedOn = TenantUtil.DateTimeFromUtc(r.ModifiedOn);
|
||||
item.ModifiedBy = editHistoryAuthor;
|
||||
item.ModifiedBy = r.ModifiedBy;
|
||||
item.ChangesString = r.Changes;
|
||||
item.Key = documentServiceHelper.GetDocKey(item.ID, item.Version, TenantUtil.DateTimeFromUtc(r.CreateOn));
|
||||
|
||||
|
@ -1,221 +1,225 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2018
|
||||
*
|
||||
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
||||
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
|
||||
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
|
||||
*
|
||||
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
||||
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
||||
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
||||
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
||||
* in every copy of the program you distribute.
|
||||
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Core.Users;
|
||||
using ASC.Files.Core.Resources;
|
||||
using ASC.Web.Core.Users;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace ASC.Files.Core
|
||||
{
|
||||
[DebuggerDisplay("{ID} v{Version}")]
|
||||
public class EditHistory
|
||||
{
|
||||
public EditHistory(
|
||||
IOptionsMonitor<ILog> options,
|
||||
TenantUtil tenantUtil,
|
||||
UserManager userManager,
|
||||
DisplayUserSettingsHelper displayUserSettingsHelper)
|
||||
{
|
||||
Logger = options.CurrentValue;
|
||||
TenantUtil = tenantUtil;
|
||||
UserManager = userManager;
|
||||
DisplayUserSettingsHelper = displayUserSettingsHelper;
|
||||
}
|
||||
|
||||
public int ID { get; set; }
|
||||
public string Key { get; set; }
|
||||
public int Version { get; set; }
|
||||
public int VersionGroup { get; set; }
|
||||
|
||||
[JsonPropertyName("user")]
|
||||
public EditHistoryAuthor ModifiedBy { get; set; }
|
||||
|
||||
[JsonPropertyName("changeshistory")]
|
||||
public string ChangesString { get; set; }
|
||||
|
||||
public List<EditHistoryChanges> Changes
|
||||
{
|
||||
get
|
||||
{
|
||||
var changes = new List<EditHistoryChanges>();
|
||||
if (string.IsNullOrEmpty(ChangesString)) return changes;
|
||||
|
||||
try
|
||||
{
|
||||
var jObject = JObject.Parse(ChangesString);
|
||||
ServerVersion = jObject.Value<string>("serverVersion");
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System Limited 2010-2018
|
||||
*
|
||||
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
||||
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
|
||||
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
|
||||
*
|
||||
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
||||
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
||||
*
|
||||
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
||||
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
||||
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
||||
* in every copy of the program you distribute.
|
||||
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Core.Users;
|
||||
using ASC.Files.Core.Resources;
|
||||
using ASC.Web.Core.Users;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Core
|
||||
{
|
||||
[Transient]
|
||||
[DebuggerDisplay("{ID} v{Version}")]
|
||||
public class EditHistory
|
||||
{
|
||||
private ILog Logger { get; }
|
||||
private TenantUtil TenantUtil { get; }
|
||||
private UserManager UserManager { get; }
|
||||
private DisplayUserSettingsHelper DisplayUserSettingsHelper { get; }
|
||||
|
||||
public EditHistory(
|
||||
IOptionsMonitor<ILog> options,
|
||||
TenantUtil tenantUtil,
|
||||
UserManager userManager,
|
||||
DisplayUserSettingsHelper displayUserSettingsHelper)
|
||||
{
|
||||
Logger = options.CurrentValue;
|
||||
TenantUtil = tenantUtil;
|
||||
UserManager = userManager;
|
||||
DisplayUserSettingsHelper = displayUserSettingsHelper;
|
||||
}
|
||||
|
||||
public int ID { get; set; }
|
||||
public string Key { get; set; }
|
||||
public int Version { get; set; }
|
||||
public int VersionGroup { get; set; }
|
||||
|
||||
public DateTime ModifiedOn { get; set; }
|
||||
public Guid ModifiedBy { get; set; }
|
||||
public string ChangesString { get; set; }
|
||||
|
||||
public string ServerVersion { get; set; }
|
||||
|
||||
public List<EditHistoryChanges> Changes
|
||||
{
|
||||
get
|
||||
{
|
||||
var changes = new List<EditHistoryChanges>();
|
||||
if (string.IsNullOrEmpty(ChangesString)) return changes;
|
||||
|
||||
try
|
||||
{
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
AllowTrailingCommas = true,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
var jObject = JsonSerializer.Deserialize<ChangesDataList>(ChangesString, options);
|
||||
ServerVersion = jObject.ServerVersion;
|
||||
|
||||
if (string.IsNullOrEmpty(ServerVersion))
|
||||
return changes;
|
||||
|
||||
var jChanges = jObject.Value<JArray>("changes");
|
||||
|
||||
changes = jChanges.Children()
|
||||
.Select(jChange =>
|
||||
{
|
||||
var jUser = jChange.Value<JObject>("user");
|
||||
return new EditHistoryChanges(TenantUtil)
|
||||
{
|
||||
Date = jChange.Value<string>("created"),
|
||||
Author = new EditHistoryAuthor(UserManager, DisplayUserSettingsHelper)
|
||||
{
|
||||
Id = new Guid(jUser.Value<string>("id") ?? Guid.Empty.ToString()),
|
||||
Name = jUser.Value<string>("name"),
|
||||
},
|
||||
};
|
||||
})
|
||||
.ToList();
|
||||
return changes;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("DeSerialize old scheme exception", ex);
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
set { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public DateTime ModifiedOn;
|
||||
|
||||
[JsonPropertyName("created")]
|
||||
public string ModifiedOnString
|
||||
{
|
||||
get { return ModifiedOn.Equals(default) ? null : ModifiedOn.ToString("g"); }
|
||||
set { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public ILog Logger { get; }
|
||||
private TenantUtil TenantUtil { get; }
|
||||
private UserManager UserManager { get; }
|
||||
private DisplayUserSettingsHelper DisplayUserSettingsHelper { get; }
|
||||
|
||||
public string ServerVersion;
|
||||
}
|
||||
|
||||
[DebuggerDisplay("{Id} {Name}")]
|
||||
public class EditHistoryAuthor
|
||||
{
|
||||
public EditHistoryAuthor(
|
||||
UserManager userManager,
|
||||
DisplayUserSettingsHelper displayUserSettingsHelper)
|
||||
{
|
||||
UserManager = userManager;
|
||||
DisplayUserSettingsHelper = displayUserSettingsHelper;
|
||||
}
|
||||
|
||||
public Guid Id { get; set; }
|
||||
|
||||
private string _name;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
UserInfo user;
|
||||
return
|
||||
Id.Equals(Guid.Empty)
|
||||
|| Id.Equals(ASC.Core.Configuration.Constants.Guest.ID)
|
||||
|| (user = UserManager.GetUsers(Id)).Equals(Constants.LostUser)
|
||||
? string.IsNullOrEmpty(_name)
|
||||
? FilesCommonResource.Guest
|
||||
: _name
|
||||
: user.DisplayUserName(false, DisplayUserSettingsHelper);
|
||||
}
|
||||
set { _name = value; }
|
||||
}
|
||||
|
||||
private UserManager UserManager { get; }
|
||||
private DisplayUserSettingsHelper DisplayUserSettingsHelper { get; }
|
||||
}
|
||||
|
||||
[DebuggerDisplay("{Author.Name}")]
|
||||
public class EditHistoryChanges
|
||||
{
|
||||
public EditHistoryChanges(TenantUtil tenantUtil)
|
||||
{
|
||||
TenantUtil = tenantUtil;
|
||||
}
|
||||
|
||||
[JsonPropertyName("user")]
|
||||
public EditHistoryAuthor Author { get; set; }
|
||||
|
||||
private DateTime _date;
|
||||
|
||||
[JsonPropertyName("created")]
|
||||
public string Date
|
||||
{
|
||||
get { return _date.Equals(default) ? null : _date.ToString("g"); }
|
||||
set
|
||||
{
|
||||
if (DateTime.TryParse(value, out _date))
|
||||
{
|
||||
_date = TenantUtil.DateTimeFromUtc(_date);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TenantUtil TenantUtil { get; }
|
||||
}
|
||||
|
||||
[DebuggerDisplay("{Version}")]
|
||||
public class EditHistoryData
|
||||
{
|
||||
public string ChangesUrl { get; set; }
|
||||
|
||||
public string Key { get; set; }
|
||||
|
||||
public EditHistoryUrl Previous { get; set; }
|
||||
|
||||
public string Token { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
public int Version { get; set; }
|
||||
}
|
||||
|
||||
[DebuggerDisplay("{Key} - {Url}")]
|
||||
public class EditHistoryUrl
|
||||
{
|
||||
public string Key { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
}
|
||||
|
||||
changes = jObject.Changes.Select(r =>
|
||||
{
|
||||
var result = new EditHistoryChanges()
|
||||
{
|
||||
Author = new EditHistoryAuthor(UserManager, DisplayUserSettingsHelper)
|
||||
{
|
||||
Id = new Guid(r.User.Id ?? Guid.Empty.ToString()),
|
||||
Name = r.User.Name,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (DateTime.TryParse(r.Created, out var _date))
|
||||
{
|
||||
_date = TenantUtil.DateTimeFromUtc(_date);
|
||||
}
|
||||
result.Date = _date;
|
||||
|
||||
return result;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
return changes;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("DeSerialize old scheme exception", ex);
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
set { throw new NotImplementedException(); }
|
||||
}
|
||||
}
|
||||
|
||||
class ChangesDataList
|
||||
{
|
||||
public string ServerVersion { get; set; }
|
||||
public ChangesData[] Changes { get; set; }
|
||||
}
|
||||
|
||||
class ChangesData
|
||||
{
|
||||
public string Created { get; set; }
|
||||
public ChangesUserData User { get; set; }
|
||||
}
|
||||
|
||||
class ChangesUserData
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[Transient]
|
||||
[DebuggerDisplay("{Id} {Name}")]
|
||||
public class EditHistoryAuthor
|
||||
{
|
||||
public EditHistoryAuthor(
|
||||
UserManager userManager,
|
||||
DisplayUserSettingsHelper displayUserSettingsHelper)
|
||||
{
|
||||
UserManager = userManager;
|
||||
DisplayUserSettingsHelper = displayUserSettingsHelper;
|
||||
}
|
||||
|
||||
public Guid Id { get; set; }
|
||||
|
||||
private string _name;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
UserInfo user;
|
||||
return
|
||||
Id.Equals(Guid.Empty)
|
||||
|| Id.Equals(ASC.Core.Configuration.Constants.Guest.ID)
|
||||
|| (user = UserManager.GetUsers(Id)).Equals(Constants.LostUser)
|
||||
? string.IsNullOrEmpty(_name)
|
||||
? FilesCommonResource.Guest
|
||||
: _name
|
||||
: user.DisplayUserName(false, DisplayUserSettingsHelper);
|
||||
}
|
||||
set { _name = value; }
|
||||
}
|
||||
|
||||
private UserManager UserManager { get; }
|
||||
private DisplayUserSettingsHelper DisplayUserSettingsHelper { get; }
|
||||
}
|
||||
|
||||
[DebuggerDisplay("{Author.Name}")]
|
||||
public class EditHistoryChanges
|
||||
{
|
||||
public EditHistoryAuthor Author { get; set; }
|
||||
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
[DebuggerDisplay("{Version}")]
|
||||
public class EditHistoryData
|
||||
{
|
||||
public string ChangesUrl { get; set; }
|
||||
|
||||
public string Key { get; set; }
|
||||
|
||||
public EditHistoryUrl Previous { get; set; }
|
||||
|
||||
public string Token { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
public int Version { get; set; }
|
||||
|
||||
public string FileType { get; set; }
|
||||
}
|
||||
|
||||
[DebuggerDisplay("{Key} - {Url}")]
|
||||
public class EditHistoryUrl
|
||||
{
|
||||
public string Key { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
public string FileType { get; set; }
|
||||
}
|
||||
}
|
@ -1071,12 +1071,15 @@ namespace ASC.Web.Files.Services.WCFService
|
||||
Key = DocumentServiceHelper.GetDocKey(file),
|
||||
Url = DocumentServiceConnector.ReplaceCommunityAdress(PathProvider.GetFileStreamUrl(file, doc)),
|
||||
Version = version,
|
||||
FileType = GetFileExtensionWithoutDot(FileUtility.GetFileExtension(file.Title))
|
||||
};
|
||||
|
||||
if (fileDao.ContainChanges(file.ID, file.Version))
|
||||
{
|
||||
string previouseKey;
|
||||
string sourceFileUrl;
|
||||
string previousFileExt;
|
||||
|
||||
if (file.Version > 1)
|
||||
{
|
||||
var previousFileStable = fileDao.GetFileStable(file.ID, file.Version - 1);
|
||||
@ -1085,6 +1088,7 @@ namespace ASC.Web.Files.Services.WCFService
|
||||
sourceFileUrl = PathProvider.GetFileStreamUrl(previousFileStable, doc);
|
||||
|
||||
previouseKey = DocumentServiceHelper.GetDocKey(previousFileStable);
|
||||
previousFileExt = FileUtility.GetFileExtension(previousFileStable.Title);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1105,12 +1109,14 @@ namespace ASC.Web.Files.Services.WCFService
|
||||
sourceFileUrl = BaseCommonLinkUtility.GetFullAbsolutePath(sourceFileUrl);
|
||||
|
||||
previouseKey = DocumentServiceConnector.GenerateRevisionId(Guid.NewGuid().ToString());
|
||||
previousFileExt = fileExt;
|
||||
}
|
||||
|
||||
result.Previous = new EditHistoryUrl
|
||||
{
|
||||
Key = previouseKey,
|
||||
Url = DocumentServiceConnector.ReplaceCommunityAdress(sourceFileUrl),
|
||||
FileType = GetFileExtensionWithoutDot(previousFileExt)
|
||||
};
|
||||
result.ChangesUrl = PathProvider.GetFileChangesUrl(file, doc);
|
||||
}
|
||||
@ -1118,6 +1124,11 @@ namespace ASC.Web.Files.Services.WCFService
|
||||
result.Token = DocumentServiceHelper.GetSignature(result);
|
||||
|
||||
return result;
|
||||
|
||||
string GetFileExtensionWithoutDot(string ext)
|
||||
{
|
||||
return ext.Substring(ext.IndexOf('.') + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public List<EditHistory> RestoreVersion(T fileId, int version, string url = null, string doc = null)
|
||||
|
49
products/ASC.Files/Core/Model/EditHistoryWrapper.cs
Normal file
49
products/ASC.Files/Core/Model/EditHistoryWrapper.cs
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Api.Core;
|
||||
using ASC.Core;
|
||||
using ASC.Web.Core.Users;
|
||||
|
||||
namespace ASC.Files.Core.Model
|
||||
{
|
||||
public class EditHistoryWrapper
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public string Key { get; set; }
|
||||
public int Version { get; set; }
|
||||
public int VersionGroup { get; set; }
|
||||
public EditHistoryAuthor User { get; set; }
|
||||
public ApiDateTime Created { get; set; }
|
||||
public string ChangesHistory { get; set; }
|
||||
public List<EditHistoryChangesWrapper> Changes { get; set; }
|
||||
public string ServerVersion { get; set; }
|
||||
|
||||
public EditHistoryWrapper(EditHistory editHistory, ApiDateTimeHelper apiDateTimeHelper, UserManager userManager, DisplayUserSettingsHelper displayUserSettingsHelper)
|
||||
{
|
||||
ID = editHistory.ID;
|
||||
Key = editHistory.Key;
|
||||
Version = editHistory.Version;
|
||||
VersionGroup = editHistory.VersionGroup;
|
||||
Changes = editHistory.Changes.Select(r => new EditHistoryChangesWrapper(r, apiDateTimeHelper)).ToList();
|
||||
ChangesHistory = editHistory.ChangesString;
|
||||
Created = apiDateTimeHelper.Get(editHistory.ModifiedOn);
|
||||
User = new EditHistoryAuthor(userManager, displayUserSettingsHelper) { Id = editHistory.ModifiedBy };
|
||||
ServerVersion = editHistory.ServerVersion;
|
||||
}
|
||||
}
|
||||
|
||||
public class EditHistoryChangesWrapper
|
||||
{
|
||||
public EditHistoryAuthor User { get; set; }
|
||||
|
||||
public ApiDateTime Created { get; set; }
|
||||
|
||||
public EditHistoryChangesWrapper(EditHistoryChanges historyChanges, ApiDateTimeHelper apiDateTimeHelper)
|
||||
{
|
||||
User = historyChanges.Author;
|
||||
Created = apiDateTimeHelper.Get(historyChanges.Date);
|
||||
}
|
||||
}
|
||||
}
|
@ -1517,6 +1517,48 @@ namespace ASC.Api.Documents
|
||||
return FilesControllerHelperInt.LockFile(fileId, model.LockFile);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[Read("file/{fileId}/edit/history")]
|
||||
public List<EditHistoryWrapper> GetEditHistory(string fileId, string doc = null)
|
||||
{
|
||||
return FilesControllerHelperString.GetEditHistory(fileId, doc);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[Read("file/{fileId:int}/edit/history")]
|
||||
public List<EditHistoryWrapper> GetEditHistory(int fileId, string doc = null)
|
||||
{
|
||||
return FilesControllerHelperInt.GetEditHistory(fileId, doc);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[Read("file/{fileId}/edit/diff")]
|
||||
public EditHistoryData GetEditDiffUrl(string fileId, int version = 0, string doc = null)
|
||||
{
|
||||
return FilesControllerHelperString.GetEditDiffUrl(fileId, version, doc);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[Read("file/{fileId:int}/edit/diff")]
|
||||
public EditHistoryData GetEditDiffUrl(int fileId, int version = 0, string doc = null)
|
||||
{
|
||||
return FilesControllerHelperInt.GetEditDiffUrl(fileId, version, doc);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[Read("file/{fileId}/restoreversion")]
|
||||
public List<EditHistoryWrapper> RestoreVersion(string fileId, int version = 0, string url = null, string doc = null)
|
||||
{
|
||||
return FilesControllerHelperString.RestoreVersion(fileId, version, url, doc);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[Read("file/{fileId:int}/restoreversion")]
|
||||
public List<EditHistoryWrapper> RestoreVersion(int fileId, int version = 0, string url = null, string doc = null)
|
||||
{
|
||||
return FilesControllerHelperInt.RestoreVersion(fileId, version, url, doc);
|
||||
}
|
||||
|
||||
[Update("file/{fileId}/comment")]
|
||||
public object UpdateCommentFromBody(string fileId, [FromBody] UpdateCommentModel model)
|
||||
{
|
||||
|
@ -21,6 +21,7 @@ using ASC.Files.Core;
|
||||
using ASC.Files.Core.Model;
|
||||
using ASC.Files.Model;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Core.Users;
|
||||
using ASC.Web.Files.Classes;
|
||||
using ASC.Web.Files.Core.Entries;
|
||||
using ASC.Web.Files.Services.DocumentService;
|
||||
@ -66,6 +67,9 @@ namespace ASC.Files.Helpers
|
||||
private EncryptionKeyPairHelper EncryptionKeyPairHelper { get; }
|
||||
private IHttpContextAccessor HttpContextAccessor { get; }
|
||||
private FileConverter FileConverter { get; }
|
||||
private ApiDateTimeHelper ApiDateTimeHelper { get; }
|
||||
private UserManager UserManager { get; }
|
||||
private DisplayUserSettingsHelper DisplayUserSettingsHelper { get; }
|
||||
private ILog Logger { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -94,7 +98,10 @@ namespace ASC.Files.Helpers
|
||||
SettingsManager settingsManager,
|
||||
EncryptionKeyPairHelper encryptionKeyPairHelper,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
FileConverter fileConverter)
|
||||
FileConverter fileConverter,
|
||||
ApiDateTimeHelper apiDateTimeHelper,
|
||||
UserManager userManager,
|
||||
DisplayUserSettingsHelper displayUserSettingsHelper)
|
||||
{
|
||||
ApiContext = context;
|
||||
FileStorageService = fileStorageService;
|
||||
@ -115,6 +122,9 @@ namespace ASC.Files.Helpers
|
||||
DocumentServiceTracker = documentServiceTracker;
|
||||
SettingsManager = settingsManager;
|
||||
EncryptionKeyPairHelper = encryptionKeyPairHelper;
|
||||
ApiDateTimeHelper = apiDateTimeHelper;
|
||||
UserManager = userManager;
|
||||
DisplayUserSettingsHelper = displayUserSettingsHelper;
|
||||
HttpContextAccessor = httpContextAccessor;
|
||||
FileConverter = fileConverter;
|
||||
Logger = optionMonitor.Get("ASC.Files");
|
||||
@ -571,6 +581,23 @@ namespace ASC.Files.Helpers
|
||||
return FileStorageService.GetPresignedUri(fileId);
|
||||
}
|
||||
|
||||
public List<EditHistoryWrapper> GetEditHistory(T fileId, string doc = null)
|
||||
{
|
||||
var result = FileStorageService.GetEditHistory(fileId, doc);
|
||||
return result.Select(r => new EditHistoryWrapper(r, ApiDateTimeHelper, UserManager, DisplayUserSettingsHelper)).ToList();
|
||||
}
|
||||
|
||||
public EditHistoryData GetEditDiffUrl(T fileId, int version = 0, string doc = null)
|
||||
{
|
||||
return FileStorageService.GetEditDiffUrl(fileId, version, doc);
|
||||
}
|
||||
|
||||
public List<EditHistoryWrapper> RestoreVersion(T fileId, int version = 0, string url = null, string doc = null)
|
||||
{
|
||||
var result = FileStorageService.RestoreVersion(fileId, version, url, doc);
|
||||
return result.Select(r => new EditHistoryWrapper(r, ApiDateTimeHelper, UserManager, DisplayUserSettingsHelper)).ToList();
|
||||
}
|
||||
|
||||
public string UpdateComment(T fileId, int version, string comment)
|
||||
{
|
||||
return FileStorageService.UpdateComment(fileId, version, comment);
|
||||
|
@ -166,7 +166,9 @@ namespace ASC.Api.Settings
|
||||
private ILog Log { get; set; }
|
||||
private TelegramHelper TelegramHelper { get; }
|
||||
private PaymentManager PaymentManager { get; }
|
||||
public Constants Constants { get; }
|
||||
private Constants Constants { get; }
|
||||
private InstanceCrypto InstanceCrypto { get; }
|
||||
private Signature Signature { get; }
|
||||
|
||||
public SettingsController(
|
||||
IOptionsMonitor<ILog> option,
|
||||
@ -228,7 +230,9 @@ namespace ASC.Api.Settings
|
||||
EncryptionWorker encryptionWorker,
|
||||
PasswordHasher passwordHasher,
|
||||
PaymentManager paymentManager,
|
||||
Constants constants)
|
||||
Constants constants,
|
||||
InstanceCrypto instanceCrypto,
|
||||
Signature signature)
|
||||
{
|
||||
Log = option.Get("ASC.Api");
|
||||
WebHostEnvironment = webHostEnvironment;
|
||||
@ -290,6 +294,8 @@ namespace ASC.Api.Settings
|
||||
TelegramHelper = telegramHelper;
|
||||
PaymentManager = paymentManager;
|
||||
Constants = constants;
|
||||
InstanceCrypto = instanceCrypto;
|
||||
Signature = signature;
|
||||
}
|
||||
|
||||
[Read("", Check = false)]
|
||||
@ -1598,7 +1604,7 @@ namespace ASC.Api.Settings
|
||||
if (currentUser.IsVisitor(UserManager) || currentUser.IsOutsider(UserManager))
|
||||
throw new NotSupportedException("Not available.");
|
||||
|
||||
return SettingsManager.LoadForCurrentUser<TfaAppUserSettings>().CodesSetting.Select(r => new { r.IsUsed, r.Code }).ToList();
|
||||
return SettingsManager.LoadForCurrentUser<TfaAppUserSettings>().CodesSetting.Select(r => new { r.IsUsed, Code = r.GetEncryptedCode(InstanceCrypto, Signature) }).ToList();
|
||||
}
|
||||
|
||||
[Update("tfaappnewcodes")]
|
||||
@ -1612,7 +1618,7 @@ namespace ASC.Api.Settings
|
||||
if (currentUser.IsVisitor(UserManager) || currentUser.IsOutsider(UserManager))
|
||||
throw new NotSupportedException("Not available.");
|
||||
|
||||
var codes = TfaManager.GenerateBackupCodes().Select(r => new { r.IsUsed, r.Code }).ToList();
|
||||
var codes = TfaManager.GenerateBackupCodes().Select(r => new { r.IsUsed, Code = r.GetEncryptedCode(InstanceCrypto, Signature) }).ToList();
|
||||
MessageService.Send(MessageAction.UserConnectedTfaApp, MessageTarget.Create(currentUser.ID), currentUser.DisplayUserName(false, DisplayUserSettingsHelper));
|
||||
return codes;
|
||||
}
|
||||
|
@ -29,7 +29,9 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using ASC.Common.Utils;
|
||||
using ASC.Core.Common.Settings;
|
||||
using ASC.Security.Cryptography;
|
||||
|
||||
namespace ASC.Web.Studio.Core.TFA
|
||||
{
|
||||
@ -65,7 +67,7 @@ namespace ASC.Web.Studio.Core.TFA
|
||||
var from = new DateTime(2018, 07, 07, 0, 0, 0, DateTimeKind.Utc);
|
||||
settings.SaltSetting = salt = (long)(DateTime.UtcNow - from).TotalMilliseconds;
|
||||
|
||||
settingsManager.SaveForUser<TfaAppUserSettings>(settings, userId);
|
||||
settingsManager.SaveForUser(settings, userId);
|
||||
}
|
||||
return salt;
|
||||
}
|
||||
@ -75,10 +77,10 @@ namespace ASC.Web.Studio.Core.TFA
|
||||
return settingsManager.LoadForUser<TfaAppUserSettings>(userId).CodesSetting;
|
||||
}
|
||||
|
||||
public static void DisableCodeForUser(SettingsManager settingsManager, Guid userId, string code)
|
||||
public static void DisableCodeForUser(SettingsManager settingsManager, InstanceCrypto instanceCrypto, Signature signature, Guid userId, string code)
|
||||
{
|
||||
var settings = settingsManager.LoadForUser<TfaAppUserSettings>(userId);
|
||||
var query = settings.CodesSetting.Where(x => x.Code == code).ToList();
|
||||
var query = settings.CodesSetting.Where(x => x.GetEncryptedCode(instanceCrypto, signature) == code).ToList();
|
||||
|
||||
if (query.Any())
|
||||
query.First().IsUsed = true;
|
||||
|
@ -51,35 +51,26 @@ namespace ASC.Web.Studio.Core.TFA
|
||||
[Serializable]
|
||||
public class BackupCode
|
||||
{
|
||||
private string code;
|
||||
private InstanceCrypto InstanceCrypto { get; }
|
||||
private Signature Signature { get; }
|
||||
|
||||
public string Code
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return InstanceCrypto.Decrypt(code);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//support old scheme stored in the DB
|
||||
return Signature.Read<string>(code);
|
||||
}
|
||||
}
|
||||
set { code = InstanceCrypto.Encrypt(value); }
|
||||
}
|
||||
|
||||
public bool IsUsed { get; set; }
|
||||
|
||||
public BackupCode(InstanceCrypto instanceCrypto, Signature signature, string code)
|
||||
public string Code { get; set; }
|
||||
|
||||
public string GetEncryptedCode(InstanceCrypto InstanceCrypto, Signature Signature)
|
||||
{
|
||||
InstanceCrypto = instanceCrypto;
|
||||
Signature = signature;
|
||||
Code = code;
|
||||
IsUsed = false;
|
||||
try
|
||||
{
|
||||
return InstanceCrypto.Decrypt(Code);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//support old scheme stored in the DB
|
||||
return Signature.Read<string>(Code);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetEncryptedCode(InstanceCrypto InstanceCrypto, string code)
|
||||
{
|
||||
Code = InstanceCrypto.Encrypt(code);
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,9 +136,9 @@ namespace ASC.Web.Studio.Core.TFA
|
||||
|
||||
if (!Tfa.ValidateTwoFactorPIN(GenerateAccessToken(user), code))
|
||||
{
|
||||
if (checkBackup && TfaAppUserSettings.BackupCodesForUser(SettingsManager, user.ID).Any(x => x.Code == code && !x.IsUsed))
|
||||
if (checkBackup && TfaAppUserSettings.BackupCodesForUser(SettingsManager, user.ID).Any(x => x.GetEncryptedCode(InstanceCrypto, Signature) == code && !x.IsUsed))
|
||||
{
|
||||
TfaAppUserSettings.DisableCodeForUser(SettingsManager, user.ID, code);
|
||||
TfaAppUserSettings.DisableCodeForUser(SettingsManager, InstanceCrypto, Signature, user.ID, code);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -195,7 +186,9 @@ namespace ASC.Web.Studio.Core.TFA
|
||||
result.Append(alphabet[b % (alphabet.Length)]);
|
||||
}
|
||||
|
||||
list.Add(new BackupCode(InstanceCrypto, Signature, result.ToString()));
|
||||
var code = new BackupCode();
|
||||
code.SetEncryptedCode(InstanceCrypto, result.ToString());
|
||||
list.Add(code);
|
||||
}
|
||||
}
|
||||
var settings = SettingsManager.LoadForCurrentUser<TfaAppUserSettings>();
|
||||
|
@ -26,6 +26,9 @@ import {
|
||||
getPresignedUri,
|
||||
convertFile,
|
||||
checkFillFormDraft,
|
||||
getEditHistory,
|
||||
getEditDiff,
|
||||
restoreDocumentsVersion,
|
||||
} from "@appserver/common/api/files";
|
||||
import FilesFilter from "@appserver/common/api/files/filter";
|
||||
|
||||
@ -33,12 +36,12 @@ import throttle from "lodash/throttle";
|
||||
import { isIOS, deviceType } from "react-device-detect";
|
||||
import { homepage } from "../package.json";
|
||||
|
||||
import { AppServerConfig, FolderType } from "@appserver/common/constants";
|
||||
import { AppServerConfig } from "@appserver/common/constants";
|
||||
import SharingDialog from "files/SharingDialog";
|
||||
import { getDefaultFileName, SaveAs, canConvert } from "files/utils";
|
||||
import SelectFileDialog from "files/SelectFileDialog";
|
||||
import SelectFolderDialog from "files/SelectFolderDialog";
|
||||
import { StyledSelectFolder, StyledSelectFile } from "./StyledEditor";
|
||||
import { StyledSelectFolder } from "./StyledEditor";
|
||||
import i18n from "./i18n";
|
||||
import Text from "@appserver/components/text";
|
||||
import TextInput from "@appserver/components/text-input";
|
||||
@ -67,7 +70,9 @@ let isSharingAccess;
|
||||
let user = null;
|
||||
let personal;
|
||||
let url = window.location.href;
|
||||
let config;
|
||||
const filesUrl = url.substring(0, url.indexOf("/doceditor"));
|
||||
const doc = url.indexOf("doc=") !== -1 ? url.split("doc=")[1] : null;
|
||||
|
||||
toast.configure();
|
||||
|
||||
@ -142,7 +147,7 @@ const Editor = () => {
|
||||
docEditor.setFavorite(favorite);
|
||||
};
|
||||
|
||||
const initDesktop = (config) => {
|
||||
const initDesktop = () => {
|
||||
const isEncryption = config?.editorConfig["encryptionKeys"] !== undefined;
|
||||
|
||||
regDesktop(
|
||||
@ -237,7 +242,7 @@ const Editor = () => {
|
||||
setIsAuthenticated(successAuth);
|
||||
}
|
||||
|
||||
const config = await openEdit(fileId, version, doc, view);
|
||||
config = await openEdit(fileId, version, doc, view);
|
||||
|
||||
if (
|
||||
!view &&
|
||||
@ -269,7 +274,7 @@ const Editor = () => {
|
||||
|
||||
setIsLoading(false);
|
||||
|
||||
loadScript(docApiUrl, "scripDocServiceAddress", () => onLoad(config));
|
||||
loadScript(docApiUrl, "scripDocServiceAddress", () => onLoad());
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toastr.error(
|
||||
@ -332,7 +337,7 @@ const Editor = () => {
|
||||
document.title = title;
|
||||
};
|
||||
|
||||
const onLoad = (config) => {
|
||||
const onLoad = () => {
|
||||
try {
|
||||
if (!window.DocsAPI) throw new Error("DocsAPI is not defined");
|
||||
|
||||
@ -408,7 +413,8 @@ const Editor = () => {
|
||||
onRequestSaveAs,
|
||||
onRequestInsertImage,
|
||||
onRequestMailMergeRecipients,
|
||||
onRequestCompareFile;
|
||||
onRequestCompareFile,
|
||||
onRequestRestore;
|
||||
|
||||
if (isSharingAccess) {
|
||||
onRequestSharingSettings = onSDKRequestSharingSettings;
|
||||
@ -425,6 +431,9 @@ const Editor = () => {
|
||||
onRequestCompareFile = onSDKRequestCompareFile;
|
||||
}
|
||||
|
||||
if (!!config.document.permissions.changeHistory) {
|
||||
onRequestRestore = onSDKRequestRestore;
|
||||
}
|
||||
const events = {
|
||||
events: {
|
||||
onAppReady: onSDKAppReady,
|
||||
@ -442,6 +451,10 @@ const Editor = () => {
|
||||
onRequestMailMergeRecipients,
|
||||
onRequestCompareFile,
|
||||
onRequestEditRights: onSDKRequestEditRights,
|
||||
onRequestHistory: onSDKRequestHistory,
|
||||
onRequestHistoryClose: onSDKRequestHistoryClose,
|
||||
onRequestHistoryData: onSDKRequestHistoryData,
|
||||
onRequestRestore,
|
||||
},
|
||||
};
|
||||
|
||||
@ -454,6 +467,114 @@ const Editor = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const onSDKRequestHistoryData = async (event) => {
|
||||
const version = event.data;
|
||||
|
||||
try {
|
||||
const versionDifference = await getEditDiff(fileId, version, doc);
|
||||
const changesUrl = versionDifference.changesUrl;
|
||||
const previous = versionDifference.previous;
|
||||
const token = versionDifference.token;
|
||||
|
||||
docEditor.setHistoryData({
|
||||
...(changesUrl && { changesUrl }),
|
||||
key: versionDifference.key,
|
||||
fileType: versionDifference.fileType,
|
||||
...(previous && {
|
||||
previous: {
|
||||
fileType: previous.fileType,
|
||||
key: previous.key,
|
||||
url: previous.url,
|
||||
},
|
||||
}),
|
||||
...(token && { token }),
|
||||
url: versionDifference.url,
|
||||
version,
|
||||
});
|
||||
} catch (e) {
|
||||
docEditor.setHistoryData({
|
||||
error: `${e}`, //TODO: maybe need to display something else.
|
||||
version,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onSDKRequestHistoryClose = () => {
|
||||
document.location.reload();
|
||||
};
|
||||
|
||||
const getDocumentHistory = (fileHistory, historyLength) => {
|
||||
let result = [];
|
||||
|
||||
for (let i = 0; i < historyLength; i++) {
|
||||
const changes = fileHistory[i].changes;
|
||||
const serverVersion = fileHistory[i].serverVersion;
|
||||
const version = fileHistory[i].version;
|
||||
const versionGroup = fileHistory[i].versionGroup;
|
||||
|
||||
let obj = {
|
||||
...(changes.length !== 0 && { changes }),
|
||||
created: `${new Date(fileHistory[i].created).toLocaleString(
|
||||
config.editorConfig.lang
|
||||
)}`,
|
||||
...(serverVersion && { serverVersion }),
|
||||
key: fileHistory[i].key,
|
||||
user: {
|
||||
id: fileHistory[i].user.id,
|
||||
name: fileHistory[i].user.name,
|
||||
},
|
||||
version,
|
||||
versionGroup,
|
||||
};
|
||||
|
||||
result.push(obj);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const getCurrentDocumentVersion = (fileHistory, historyLength) => {
|
||||
return url.indexOf("&version=") !== -1
|
||||
? +url.split("&version=")[1]
|
||||
: fileHistory[historyLength - 1].version;
|
||||
};
|
||||
const onSDKRequestHistory = async () => {
|
||||
try {
|
||||
const fileHistory = await getEditHistory(fileId, doc);
|
||||
const historyLength = fileHistory.length;
|
||||
|
||||
docEditor.refreshHistory({
|
||||
currentVersion: getCurrentDocumentVersion(fileHistory, historyLength),
|
||||
history: getDocumentHistory(fileHistory, historyLength),
|
||||
});
|
||||
} catch (e) {
|
||||
docEditor.refreshHistory({
|
||||
error: `${e}`, //TODO: maybe need to display something else.
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onSDKRequestRestore = async (event) => {
|
||||
const restoreVersion = event.data.version;
|
||||
try {
|
||||
const updateVersions = await restoreDocumentsVersion(
|
||||
fileId,
|
||||
restoreVersion,
|
||||
doc
|
||||
);
|
||||
const historyLength = updateVersions.length;
|
||||
docEditor.refreshHistory({
|
||||
currentVersion: getCurrentDocumentVersion(
|
||||
updateVersions,
|
||||
historyLength
|
||||
),
|
||||
history: getDocumentHistory(updateVersions, historyLength),
|
||||
});
|
||||
} catch (e) {
|
||||
docEditor.refreshHistory({
|
||||
error: `${e}`, //TODO: maybe need to display something else.
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onSDKAppReady = () => {
|
||||
console.log("ONLYOFFICE Document Editor is ready");
|
||||
|
||||
@ -738,7 +859,7 @@ const Editor = () => {
|
||||
onSelectFile={onSelectFile}
|
||||
isPanelVisible={isFileDialogVisible}
|
||||
onClose={onCloseFileDialog}
|
||||
foldersType="exceptTrashFolder"
|
||||
foldersType="exceptPrivacyTrashFolders"
|
||||
{...fileTypeDetection()}
|
||||
titleFilesList={selectFilesListTitle()}
|
||||
headerName={i18n.t("SelectFileTitle")}
|
||||
|
Loading…
Reference in New Issue
Block a user