Merge branch 'release/v1.0.0' of https://github.com/ONLYOFFICE/DocSpace into release/v1.0.0
This commit is contained in:
commit
fc2810ca97
@ -1,157 +0,0 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using ValidationResult = ASC.Security.Cryptography.EmailValidationKeyProvider.ValidationResult;
|
||||
|
||||
namespace ASC.Api.Core.Security;
|
||||
|
||||
[Scope]
|
||||
public class DocSpaceLinkHelper
|
||||
{
|
||||
private readonly IDbContextFactory<MessagesContext> _dbContextFactory;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly MessageService _messageService;
|
||||
private readonly MessageTarget _messageTarget;
|
||||
private readonly Signature _signature;
|
||||
private readonly EmailValidationKeyProvider _emailValidationKeyProvider;
|
||||
private readonly UserManager _userManager;
|
||||
private readonly AuthManager _authManager;
|
||||
|
||||
public TimeSpan ExpirationInterval => _emailValidationKeyProvider.ValidEmailKeyInterval;
|
||||
public TimeSpan ExpirationVisitInterval => _emailValidationKeyProvider.ValidVisitLinkInterval;
|
||||
|
||||
public DocSpaceLinkHelper(
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
MessageTarget messageTarget,
|
||||
MessageService messageService,
|
||||
Signature signature,
|
||||
IDbContextFactory<MessagesContext> dbContextFactory,
|
||||
EmailValidationKeyProvider emailValidationKeyProvider,
|
||||
UserManager userManager,
|
||||
AuthManager authManager)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_messageTarget = messageTarget;
|
||||
_messageService = messageService;
|
||||
_dbContextFactory = dbContextFactory;
|
||||
_signature = signature;
|
||||
_emailValidationKeyProvider = emailValidationKeyProvider;
|
||||
_userManager = userManager;
|
||||
_authManager = authManager;
|
||||
}
|
||||
|
||||
public string MakeKey(Guid linkId)
|
||||
{
|
||||
return _signature.Create(linkId);
|
||||
}
|
||||
|
||||
public string MakeKey(string email, EmployeeType employeeType)
|
||||
{
|
||||
return email + ConfirmType.LinkInvite.ToStringFast() + employeeType.ToStringFast();
|
||||
}
|
||||
|
||||
public Guid Parse(string key)
|
||||
{
|
||||
return _signature.Read<Guid>(key);
|
||||
}
|
||||
|
||||
public ValidationResult Validate(string key, string email, EmployeeType employeeType)
|
||||
{
|
||||
return string.IsNullOrEmpty(email) ? ValidateRoomExternalLink(key) : ValidateEmailLink(email, key, employeeType);
|
||||
}
|
||||
|
||||
public ValidationResult ValidateEmailLink(string email, string key, EmployeeType employeeType)
|
||||
{
|
||||
var result = _emailValidationKeyProvider.ValidateEmailKey(MakeKey(email, employeeType), key, ExpirationInterval);
|
||||
|
||||
if (result == ValidationResult.Ok)
|
||||
{
|
||||
var user = _userManager.GetUserByEmail(email);
|
||||
|
||||
if (user == ASC.Core.Users.Constants.LostUser || _authManager.GetUserPasswordStamp(user.Id) != DateTime.MinValue)
|
||||
{
|
||||
return ValidationResult.Invalid;
|
||||
}
|
||||
|
||||
if (!CanUsed(email, key, ExpirationVisitInterval))
|
||||
{
|
||||
return ValidationResult.Expired;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ValidationResult ValidateRoomExternalLink(string key)
|
||||
{
|
||||
var payload = Parse(key);
|
||||
|
||||
return payload == default ? ValidationResult.Invalid : ValidationResult.Ok;
|
||||
}
|
||||
|
||||
public ValidationResult ValidateExtarnalLink(string key, EmployeeType employeeType)
|
||||
{
|
||||
return _emailValidationKeyProvider.ValidateEmailKey(ConfirmType.LinkInvite.ToStringFast() + (int)employeeType, key);
|
||||
}
|
||||
|
||||
private bool CanUsed(string email, string key, TimeSpan interval)
|
||||
{
|
||||
var message = GetLinkInfo(email, key);
|
||||
|
||||
if (message == null)
|
||||
{
|
||||
SaveVisitLinkInfo(email, key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return message.Date + interval > DateTime.UtcNow;
|
||||
}
|
||||
|
||||
private AuditEvent GetLinkInfo(string email, string key)
|
||||
{
|
||||
using var context = _dbContextFactory.CreateDbContext();
|
||||
var target = _messageTarget.Create(email);
|
||||
var description = JsonConvert.SerializeObject(new[] { key },
|
||||
new JsonSerializerSettings
|
||||
{
|
||||
DateTimeZoneHandling = DateTimeZoneHandling.Utc
|
||||
});
|
||||
|
||||
var message = context.AuditEvents.Where(a => a.Target == target.ToString() &&
|
||||
a.DescriptionRaw == description).FirstOrDefault();
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private void SaveVisitLinkInfo(string email, string key)
|
||||
{
|
||||
var headers = _httpContextAccessor?.HttpContext?.Request?.Headers;
|
||||
var target = _messageTarget.Create(email);
|
||||
|
||||
_messageService.Send(headers, MessageAction.RoomInviteLinkUsed, target, key);
|
||||
}
|
||||
}
|
@ -38,7 +38,7 @@ public class EmailValidationKeyModelHelper
|
||||
private readonly AuthContext _authContext;
|
||||
private readonly UserManager _userManager;
|
||||
private readonly AuthManager _authentication;
|
||||
private readonly DocSpaceLinkHelper _docSpaceLinkHelper;
|
||||
private readonly InvitationLinkHelper _invitationLinkHelper;
|
||||
private readonly AuditEventsRepository _auditEventsRepository;
|
||||
private readonly TenantUtil _tenantUtil;
|
||||
private readonly MessageTarget _messageTarget;
|
||||
@ -49,7 +49,7 @@ public class EmailValidationKeyModelHelper
|
||||
AuthContext authContext,
|
||||
UserManager userManager,
|
||||
AuthManager authentication,
|
||||
DocSpaceLinkHelper docSpaceLinkHelper,
|
||||
InvitationLinkHelper invitationLinkHelper,
|
||||
AuditEventsRepository auditEventsRepository,
|
||||
TenantUtil tenantUtil,
|
||||
MessageTarget messageTarget)
|
||||
@ -59,7 +59,7 @@ public class EmailValidationKeyModelHelper
|
||||
_authContext = authContext;
|
||||
_userManager = userManager;
|
||||
_authentication = authentication;
|
||||
_docSpaceLinkHelper = docSpaceLinkHelper;
|
||||
_invitationLinkHelper = invitationLinkHelper;
|
||||
_auditEventsRepository = auditEventsRepository;
|
||||
_tenantUtil = tenantUtil;
|
||||
_messageTarget = messageTarget;
|
||||
@ -110,13 +110,7 @@ public class EmailValidationKeyModelHelper
|
||||
break;
|
||||
|
||||
case ConfirmType.LinkInvite:
|
||||
checkKeyResult = string.IsNullOrEmpty(email) ? _docSpaceLinkHelper.ValidateRoomExternalLink(key)
|
||||
: _docSpaceLinkHelper.ValidateEmailLink(email, key, emplType ?? default);
|
||||
|
||||
if (checkKeyResult == ValidationResult.Invalid)
|
||||
{
|
||||
checkKeyResult = _provider.ValidateEmailKey(type.ToString() + (int)(emplType ?? default), key, _provider.ValidEmailKeyInterval);
|
||||
}
|
||||
checkKeyResult = _invitationLinkHelper.Validate(key, email, emplType ?? default).Result;
|
||||
break;
|
||||
|
||||
case ConfirmType.PortalOwnerChange:
|
||||
|
186
common/ASC.Api.Core/Security/InvitationLinkHelper.cs
Normal file
186
common/ASC.Api.Core/Security/InvitationLinkHelper.cs
Normal file
@ -0,0 +1,186 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using Constants = ASC.Core.Users.Constants;
|
||||
using ValidationResult = ASC.Security.Cryptography.EmailValidationKeyProvider.ValidationResult;
|
||||
|
||||
namespace ASC.Api.Core.Security;
|
||||
|
||||
[Scope]
|
||||
public class InvitationLinkHelper
|
||||
{
|
||||
private readonly IDbContextFactory<MessagesContext> _dbContextFactory;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly MessageService _messageService;
|
||||
private readonly MessageTarget _messageTarget;
|
||||
private readonly Signature _signature;
|
||||
private readonly EmailValidationKeyProvider _emailValidationKeyProvider;
|
||||
private readonly UserManager _userManager;
|
||||
private readonly AuthManager _authManager;
|
||||
|
||||
public TimeSpan IndividualLinkExpirationInterval => _emailValidationKeyProvider.ValidEmailKeyInterval;
|
||||
|
||||
public InvitationLinkHelper(
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
MessageTarget messageTarget,
|
||||
MessageService messageService,
|
||||
Signature signature,
|
||||
IDbContextFactory<MessagesContext> dbContextFactory,
|
||||
EmailValidationKeyProvider emailValidationKeyProvider,
|
||||
UserManager userManager,
|
||||
AuthManager authManager)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_messageTarget = messageTarget;
|
||||
_messageService = messageService;
|
||||
_dbContextFactory = dbContextFactory;
|
||||
_signature = signature;
|
||||
_emailValidationKeyProvider = emailValidationKeyProvider;
|
||||
_userManager = userManager;
|
||||
_authManager = authManager;
|
||||
}
|
||||
|
||||
public string MakeIndividualLinkKey(Guid linkId)
|
||||
{
|
||||
return _signature.Create(linkId);
|
||||
}
|
||||
|
||||
public async Task<LinkValidationResult> ValidateAsync(string key, string email, EmployeeType employeeType)
|
||||
{
|
||||
var validationResult = new LinkValidationResult { Result = ValidationResult.Invalid };
|
||||
|
||||
var (commonWithRoomLinkResult, linkId) = ValidateCommonWithRoomLink(key);
|
||||
|
||||
if (commonWithRoomLinkResult != ValidationResult.Invalid)
|
||||
{
|
||||
validationResult.Result = commonWithRoomLinkResult;
|
||||
validationResult.LinkType = InvitationLinkType.CommonWithRoom;
|
||||
validationResult.LinkId = linkId;
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
var commonLinkResult = _emailValidationKeyProvider.ValidateEmailKey(ConfirmType.LinkInvite.ToStringFast() + (int)employeeType,
|
||||
key, _emailValidationKeyProvider.ValidEmailKeyInterval);
|
||||
|
||||
if (commonLinkResult != ValidationResult.Invalid)
|
||||
{
|
||||
validationResult.Result = commonLinkResult;
|
||||
validationResult.LinkType = InvitationLinkType.Common;
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(email))
|
||||
{
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
var individualLinkResult = await ValidateIndividualLink(email, key, employeeType);
|
||||
|
||||
validationResult.Result = individualLinkResult;
|
||||
validationResult.LinkType = InvitationLinkType.Individual;
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
public LinkValidationResult Validate(string key, string email, EmployeeType employeeType)
|
||||
{
|
||||
return ValidateAsync(key, email, employeeType).Result;
|
||||
}
|
||||
|
||||
private async Task<ValidationResult> ValidateIndividualLink(string email, string key, EmployeeType employeeType)
|
||||
{
|
||||
var result = _emailValidationKeyProvider.ValidateEmailKey(email + ConfirmType.LinkInvite.ToStringFast() + employeeType.ToStringFast(),
|
||||
key, IndividualLinkExpirationInterval);
|
||||
|
||||
if (result != ValidationResult.Ok)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var user = _userManager.GetUserByEmail(email);
|
||||
|
||||
if (user.Equals(Constants.LostUser) || _authManager.GetUserPasswordStamp(user.Id) != DateTime.MinValue)
|
||||
{
|
||||
return ValidationResult.Invalid;
|
||||
}
|
||||
|
||||
var visitMessage = await GetLinkVisitMessageAsync(email, key);
|
||||
|
||||
if (visitMessage == null)
|
||||
{
|
||||
SaveLinkVisitMessage(email, key);
|
||||
}
|
||||
else if (visitMessage.Date + _emailValidationKeyProvider.ValidVisitLinkInterval < DateTime.UtcNow)
|
||||
{
|
||||
return ValidationResult.Expired;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private (ValidationResult, Guid) ValidateCommonWithRoomLink(string key)
|
||||
{
|
||||
var linkId = _signature.Read<Guid>(key);
|
||||
|
||||
return linkId == default ? (ValidationResult.Invalid, default) : (ValidationResult.Ok, linkId);
|
||||
}
|
||||
|
||||
private async Task<AuditEvent> GetLinkVisitMessageAsync(string email, string key)
|
||||
{
|
||||
using var context = _dbContextFactory.CreateDbContext();
|
||||
|
||||
var target = _messageTarget.Create(email);
|
||||
var description = JsonConvert.SerializeObject(new[] { key });
|
||||
|
||||
var message = await context.AuditEvents.FirstOrDefaultAsync(a => a.Target == target.ToString() && a.DescriptionRaw == description);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private void SaveLinkVisitMessage(string email, string key)
|
||||
{
|
||||
var headers = _httpContextAccessor?.HttpContext?.Request.Headers;
|
||||
var target = _messageTarget.Create(email);
|
||||
|
||||
_messageService.Send(headers, MessageAction.RoomInviteLinkUsed, target, key);
|
||||
}
|
||||
}
|
||||
|
||||
public enum InvitationLinkType
|
||||
{
|
||||
Common,
|
||||
CommonWithRoom,
|
||||
Individual
|
||||
}
|
||||
|
||||
public class LinkValidationResult
|
||||
{
|
||||
public ValidationResult Result { get; set; }
|
||||
public InvitationLinkType LinkType { get; set; }
|
||||
public Guid LinkId { get; set; }
|
||||
}
|
@ -329,6 +329,11 @@ public class PermissionContext
|
||||
return CheckPermissions(securityObject, null, actions);
|
||||
}
|
||||
|
||||
public bool CheckPermissions(IAccount account, ISecurityObject securityObject, params IAction[] actions)
|
||||
{
|
||||
return PermissionResolver.Check(account, securityObject, null, actions);
|
||||
}
|
||||
|
||||
public bool CheckPermissions(ISecurityObjectId objectId, ISecurityObjectProvider securityObjProvider, params IAction[] actions)
|
||||
{
|
||||
return PermissionResolver.Check(AuthContext.CurrentAccount, objectId, securityObjProvider, actions);
|
||||
|
@ -66,7 +66,7 @@
|
||||
},
|
||||
"files": {
|
||||
"thirdparty": {
|
||||
"enable": [ "box", "dropboxv2", "docusign", "google", "onedrive", "sharepoint", "nextcloud", "owncloud", "webdav", "kdrive", "yandex" ]
|
||||
"enable": [ "box", "dropboxv2", "docusign", "google", "onedrive", "sharepoint", "nextcloud", "owncloud", "webdav", "kdrive" ]
|
||||
},
|
||||
"docservice": {
|
||||
"coauthor-docs": [ ".pptx", ".ppsx", ".xlsx", ".csv", ".docx", ".docxf", ".oform", ".txt" ],
|
||||
|
@ -3,5 +3,6 @@
|
||||
"HideInput": "Hide",
|
||||
"Ready": "Done",
|
||||
"UploadAndConvert": "Upload and convert files",
|
||||
"Uploads": "Uploads"
|
||||
"Uploads": "Uploads",
|
||||
"CancelUpload": "The upload has been interrupted. Some files have not been uploaded."
|
||||
}
|
||||
|
@ -3,5 +3,6 @@
|
||||
"HideInput": "Скрыть ввод",
|
||||
"Ready": "Готово",
|
||||
"UploadAndConvert": "Загрузки и конвертация",
|
||||
"Uploads": "Загрузки"
|
||||
"Uploads": "Загрузки",
|
||||
"CancelUpload": "Загрузка была прервана. Не удалось загрузить часть файлов."
|
||||
}
|
||||
|
@ -61,10 +61,10 @@ const ChangeUserTypeEvent = ({
|
||||
const onChangeUserType = () => {
|
||||
onClosePanel();
|
||||
updateUserType(toType, userIDs, peopleFilter, fromType)
|
||||
.then(() => {
|
||||
.then((users) => {
|
||||
toastr.success(t("SuccessChangeUserType"));
|
||||
|
||||
successCallback && successCallback();
|
||||
successCallback && successCallback(users);
|
||||
})
|
||||
.catch((err) => {
|
||||
toastr.error(
|
||||
|
@ -67,6 +67,10 @@ class UploadPanelComponent extends React.Component {
|
||||
this.onClose();
|
||||
};
|
||||
|
||||
onCancelUpload = () => {
|
||||
this.props.cancelUpload(this.props.t);
|
||||
};
|
||||
|
||||
render() {
|
||||
//console.log("UploadPanel render");
|
||||
const {
|
||||
@ -75,7 +79,6 @@ class UploadPanelComponent extends React.Component {
|
||||
/* sharingPanelVisible, */ uploaded,
|
||||
converted,
|
||||
uploadDataFiles,
|
||||
cancelUpload,
|
||||
cancelConversion,
|
||||
isUploading,
|
||||
isUploadingAndConversion,
|
||||
@ -126,7 +129,9 @@ class UploadPanelComponent extends React.Component {
|
||||
iconName={ButtonCancelReactSvgUrl}
|
||||
// color={theme.filesPanels.upload.color}
|
||||
isClickable
|
||||
onClick={uploaded ? cancelConversion : cancelUpload}
|
||||
onClick={
|
||||
uploaded ? cancelConversion : this.onCancelUpload
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
@ -18,6 +18,8 @@ const Accounts = ({
|
||||
isAdmin,
|
||||
changeUserType,
|
||||
canChangeUserType,
|
||||
setSelection,
|
||||
getPeopleListItem,
|
||||
}) => {
|
||||
const [statusLabel, setStatusLabel] = React.useState("");
|
||||
const [isLoading, setIsLoading] = React.useState(false);
|
||||
@ -104,7 +106,16 @@ const Accounts = ({
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
const onSuccess = () => {
|
||||
const onSuccess = (users) => {
|
||||
if (users) {
|
||||
const items = [];
|
||||
users.map((u) => items.push(getPeopleListItem(u)));
|
||||
if (items.length === 1) {
|
||||
setSelection(getPeopleListItem(items[0]));
|
||||
} else {
|
||||
setSelection(items);
|
||||
}
|
||||
}
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
@ -219,6 +230,8 @@ export default inject(({ auth, peopleStore, accessRightsStore }) => {
|
||||
const { changeType: changeUserType, usersStore } = peopleStore;
|
||||
const { canChangeUserType } = accessRightsStore;
|
||||
|
||||
const { setSelection } = auth.infoPanelStore;
|
||||
|
||||
return {
|
||||
isOwner,
|
||||
isAdmin,
|
||||
@ -226,6 +239,8 @@ export default inject(({ auth, peopleStore, accessRightsStore }) => {
|
||||
selfId,
|
||||
canChangeUserType,
|
||||
loading: usersStore.operationRunning,
|
||||
getPeopleListItem: usersStore.getPeopleListItem,
|
||||
setSelection,
|
||||
};
|
||||
})(
|
||||
withTranslation([
|
||||
|
@ -216,6 +216,7 @@ export const StyledInfo = styled.div`
|
||||
padding-left: 0;
|
||||
font-size: 12px !important;
|
||||
line-height: 16px !important;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,7 +288,7 @@ class FilesStore {
|
||||
|
||||
if (this.selectedFolderStore.id !== file.folderId) {
|
||||
const movedToIndex = this.getFolderIndex(file.folderId);
|
||||
if (movedToIndex) this.folders[movedToIndex].filesCount++;
|
||||
if (movedToIndex > -1) this.folders[movedToIndex].filesCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -327,7 +327,7 @@ class FilesStore {
|
||||
|
||||
if (this.selectedFolderStore.id !== folder.parentId) {
|
||||
const movedToIndex = this.getFolderIndex(folder.parentId);
|
||||
if (movedToIndex) this.folders[movedToIndex].foldersCount++;
|
||||
if (movedToIndex > -1) this.folders[movedToIndex].foldersCount++;
|
||||
}
|
||||
|
||||
if (
|
||||
|
@ -164,7 +164,7 @@ class UploadDataStore {
|
||||
return this.files.filter((f) => f.uniqueId === id);
|
||||
};
|
||||
|
||||
cancelUpload = () => {
|
||||
cancelUpload = (t) => {
|
||||
let newFiles = [];
|
||||
|
||||
for (let i = 0; i < this.files.length; i++) {
|
||||
@ -190,6 +190,8 @@ class UploadDataStore {
|
||||
if (newUploadData.files.length === 0) this.setUploadPanelVisible(false);
|
||||
this.setUploadData(newUploadData);
|
||||
this.uploadedFilesHistory = newHistory;
|
||||
|
||||
toastr.info(t("CancelUpload"));
|
||||
};
|
||||
|
||||
cancelConversion = () => {
|
||||
|
@ -122,13 +122,17 @@ class UsersStore {
|
||||
toType = EmployeeType.User;
|
||||
}
|
||||
|
||||
let users = null;
|
||||
|
||||
try {
|
||||
await api.people.updateUserType(toType, userIds);
|
||||
users = await api.people.updateUserType(toType, userIds);
|
||||
} catch (e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
|
||||
await this.getUsersList(filter);
|
||||
|
||||
return users;
|
||||
};
|
||||
|
||||
updateProfileInUsers = async (updatedProfile) => {
|
||||
|
@ -83,8 +83,8 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
private readonly FileShareParamsHelper _fileShareParamsHelper;
|
||||
private readonly EncryptionLoginProvider _encryptionLoginProvider;
|
||||
private readonly CountRoomChecker _countRoomChecker;
|
||||
private readonly RoomLinkService _roomLinkService;
|
||||
private readonly DocSpaceLinkHelper _docSpaceLinkHelper;
|
||||
private readonly InvitationLinkService _invitationLinkService;
|
||||
private readonly InvitationLinkHelper _invitationLinkHelper;
|
||||
private readonly StudioNotifyService _studioNotifyService;
|
||||
public FileStorageService(
|
||||
Global global,
|
||||
@ -138,8 +138,8 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
FileShareParamsHelper fileShareParamsHelper,
|
||||
EncryptionLoginProvider encryptionLoginProvider,
|
||||
CountRoomChecker countRoomChecker,
|
||||
RoomLinkService roomLinkService,
|
||||
DocSpaceLinkHelper docSpaceLinkHelper,
|
||||
InvitationLinkService invitationLinkService,
|
||||
InvitationLinkHelper invitationLinkHelper,
|
||||
StudioNotifyService studioNotifyService)
|
||||
{
|
||||
_global = global;
|
||||
@ -193,8 +193,8 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
_fileShareParamsHelper = fileShareParamsHelper;
|
||||
_encryptionLoginProvider = encryptionLoginProvider;
|
||||
_countRoomChecker = countRoomChecker;
|
||||
_roomLinkService = roomLinkService;
|
||||
_docSpaceLinkHelper = docSpaceLinkHelper;
|
||||
_invitationLinkService = invitationLinkService;
|
||||
_invitationLinkHelper = invitationLinkHelper;
|
||||
_studioNotifyService = studioNotifyService;
|
||||
}
|
||||
|
||||
@ -2677,7 +2677,7 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
|
||||
var aces = new List<AceWrapper>
|
||||
{
|
||||
new AceWrapper
|
||||
new()
|
||||
{
|
||||
Access = share,
|
||||
Id = linkId,
|
||||
@ -2685,7 +2685,7 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
FileShareOptions = new FileShareOptions
|
||||
{
|
||||
Title = title,
|
||||
ExpirationDate = DateTime.UtcNow.Add(_docSpaceLinkHelper.ExpirationInterval)
|
||||
ExpirationDate = DateTime.UtcNow.Add(_invitationLinkHelper.IndividualLinkExpirationInterval)
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -3316,7 +3316,7 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
continue;
|
||||
}
|
||||
|
||||
var link = _roomLinkService.GetInvitationLink(user.Email, share.Access, _authContext.CurrentAccount.ID);
|
||||
var link = _invitationLinkService.GetInvitationLink(user.Email, share.Access, _authContext.CurrentAccount.ID);
|
||||
_studioNotifyService.SendEmailRoomInvite(user.Email, room.Title, link);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,198 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using ASC.Core.Billing;
|
||||
|
||||
namespace ASC.Files.Core.VirtualRooms;
|
||||
|
||||
[Scope]
|
||||
public class InvitationLinkService
|
||||
{
|
||||
private readonly CommonLinkUtility _commonLinkUtility;
|
||||
private readonly IDaoFactory _daoFactory;
|
||||
private readonly InvitationLinkHelper _invitationLinkHelper;
|
||||
private readonly ITariffService _tariffService;
|
||||
private readonly TenantManager _tenantManager;
|
||||
private readonly AuthManager _authManager;
|
||||
private readonly PermissionContext _permissionContext;
|
||||
private readonly CountPaidUserChecker _countPaidUserChecker;
|
||||
|
||||
public InvitationLinkService(
|
||||
CommonLinkUtility commonLinkUtility,
|
||||
IDaoFactory daoFactory,
|
||||
InvitationLinkHelper invitationLinkHelper,
|
||||
ITariffService tariffService,
|
||||
TenantManager tenantManager,
|
||||
AuthManager authManager,
|
||||
PermissionContext permissionContext,
|
||||
CountPaidUserChecker countPaidUserChecker)
|
||||
{
|
||||
_commonLinkUtility = commonLinkUtility;
|
||||
_daoFactory = daoFactory;
|
||||
_invitationLinkHelper = invitationLinkHelper;
|
||||
_tariffService = tariffService;
|
||||
_tenantManager = tenantManager;
|
||||
_authManager = authManager;
|
||||
_permissionContext = permissionContext;
|
||||
_countPaidUserChecker = countPaidUserChecker;
|
||||
}
|
||||
|
||||
public string GetInvitationLink(Guid linkId, Guid createdBy)
|
||||
{
|
||||
var key = _invitationLinkHelper.MakeIndividualLinkKey(linkId);
|
||||
|
||||
return _commonLinkUtility.GetConfirmationUrl(key, ConfirmType.LinkInvite, createdBy) + "&toRoom=true";
|
||||
}
|
||||
|
||||
public string GetInvitationLink(string email, FileShare share, Guid createdBy)
|
||||
{
|
||||
var type = FileSecurity.GetTypeByShare(share);
|
||||
|
||||
var link = _commonLinkUtility.GetConfirmationEmailUrl(email, ConfirmType.LinkInvite, type, createdBy)
|
||||
+ $"&emplType={type:d}&toRoom=true";
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
public string GetInvitationLink(string email, EmployeeType employeeType, Guid createdBy)
|
||||
{
|
||||
var link = _commonLinkUtility.GetConfirmationEmailUrl(email, ConfirmType.LinkInvite, employeeType, createdBy)
|
||||
+ $"&emplType={employeeType:d}";
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
public async Task<InvitationLinkData> GetProcessedLinkDataAsync(string key, string email)
|
||||
{
|
||||
return await GetProcessedLinkDataAsync(key, email, EmployeeType.All);
|
||||
}
|
||||
|
||||
public async Task<InvitationLinkData> GetProcessedLinkDataAsync(string key, string email, EmployeeType employeeType, Guid userId = default)
|
||||
{
|
||||
Tenant tenant;
|
||||
var linkData = new InvitationLinkData { Result = EmailValidationKeyProvider.ValidationResult.Invalid };
|
||||
|
||||
try
|
||||
{
|
||||
tenant = _tenantManager.GetCurrentTenant();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return linkData;
|
||||
}
|
||||
|
||||
if (_tariffService.GetTariff(tenant.Id).State > TariffState.Paid)
|
||||
{
|
||||
return new InvitationLinkData { Result = EmailValidationKeyProvider.ValidationResult.Invalid };
|
||||
}
|
||||
|
||||
if (userId != default)
|
||||
{
|
||||
var account = _authManager.GetAccountByID(tenant.Id, userId);
|
||||
|
||||
if (!_permissionContext.CheckPermissions(account, new UserSecurityProvider(employeeType), Constants.Action_AddRemoveUser))
|
||||
{
|
||||
return linkData;
|
||||
}
|
||||
}
|
||||
|
||||
var validationResult = await _invitationLinkHelper.ValidateAsync(key, email, employeeType);
|
||||
linkData.Result = validationResult.Result;
|
||||
linkData.LinkType = validationResult.LinkType;
|
||||
linkData.EmployeeType = employeeType;
|
||||
|
||||
|
||||
if (validationResult.LinkId == default)
|
||||
{
|
||||
if (!await CheckQuota(linkData.LinkType, employeeType))
|
||||
{
|
||||
linkData.Result = EmailValidationKeyProvider.ValidationResult.Invalid;
|
||||
}
|
||||
|
||||
return linkData;
|
||||
}
|
||||
|
||||
var record = await GetLinkRecordAsync(validationResult.LinkId);
|
||||
|
||||
if (record?.FileShareOptions == null)
|
||||
{
|
||||
linkData.Result = EmailValidationKeyProvider.ValidationResult.Invalid;
|
||||
return linkData;
|
||||
}
|
||||
|
||||
linkData.Result = record.FileShareOptions.ExpirationDate > DateTime.UtcNow ?
|
||||
EmailValidationKeyProvider.ValidationResult.Ok : EmailValidationKeyProvider.ValidationResult.Expired;
|
||||
linkData.Share = record.Share;
|
||||
linkData.RoomId = record.EntryId.ToString();
|
||||
linkData.EmployeeType = FileSecurity.GetTypeByShare(record.Share);
|
||||
|
||||
if (!await CheckQuota(linkData.LinkType, linkData.EmployeeType))
|
||||
{
|
||||
linkData.Result = EmailValidationKeyProvider.ValidationResult.Invalid;
|
||||
}
|
||||
|
||||
return linkData;
|
||||
}
|
||||
|
||||
private async Task<FileShareRecord> GetLinkRecordAsync(Guid linkId)
|
||||
{
|
||||
var securityDao = _daoFactory.GetSecurityDao<int>();
|
||||
var share = await securityDao.GetSharesAsync(new[] { linkId })
|
||||
.FirstOrDefaultAsync(s => s.SubjectType == SubjectType.InvitationLink);
|
||||
|
||||
return share;
|
||||
}
|
||||
|
||||
private async Task<bool> CheckQuota(InvitationLinkType linkType, EmployeeType employeeType)
|
||||
{
|
||||
if (linkType == InvitationLinkType.Individual ||
|
||||
employeeType is not (EmployeeType.DocSpaceAdmin or EmployeeType.RoomAdmin or EmployeeType.Collaborator))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await _countPaidUserChecker.CheckAppend();
|
||||
}
|
||||
catch (TenantQuotaException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class InvitationLinkData
|
||||
{
|
||||
public string RoomId { get; set; }
|
||||
public FileShare Share { get; set; }
|
||||
public InvitationLinkType LinkType { get; set; }
|
||||
public EmployeeType EmployeeType { get; set; }
|
||||
public EmailValidationKeyProvider.ValidationResult Result { get; set; }
|
||||
public bool IsCorrect => Result == EmailValidationKeyProvider.ValidationResult.Ok;
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Files.Core.VirtualRooms;
|
||||
|
||||
[Scope]
|
||||
public class RoomLinkService
|
||||
{
|
||||
private readonly CommonLinkUtility _commonLinkUtility;
|
||||
private readonly IDaoFactory _daoFactory;
|
||||
private readonly DocSpaceLinkHelper _docSpaceLinksHelper;
|
||||
|
||||
public RoomLinkService(CommonLinkUtility commonLinkUtility, IDaoFactory daoFactory, DocSpaceLinkHelper docSpaceLinksHelper)
|
||||
{
|
||||
_commonLinkUtility = commonLinkUtility;
|
||||
_daoFactory = daoFactory;
|
||||
_docSpaceLinksHelper = docSpaceLinksHelper;
|
||||
}
|
||||
|
||||
public string GetInvitationLink(Guid linkId, Guid createdBy)
|
||||
{
|
||||
var key = _docSpaceLinksHelper.MakeKey(linkId);
|
||||
|
||||
return _commonLinkUtility.GetConfirmationUrl(key, ConfirmType.LinkInvite, createdBy) + "&toRoom=true";
|
||||
}
|
||||
|
||||
public string GetInvitationLink(string email, FileShare share, Guid createdBy)
|
||||
{
|
||||
var type = FileSecurity.GetTypeByShare(share);
|
||||
|
||||
var link = _commonLinkUtility.GetConfirmationEmailUrl(email, ConfirmType.LinkInvite, type, createdBy)
|
||||
+ $"&emplType={type:d}&toRoom=true";
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
public string GetInvitationLink(string email, EmployeeType employeeType, Guid createdBy)
|
||||
{
|
||||
var link = _commonLinkUtility.GetConfirmationEmailUrl(email, ConfirmType.LinkInvite, employeeType, createdBy)
|
||||
+ $"&emplType={employeeType:d}";
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
public async Task<LinkOptions> GetOptionsAsync(string key, string email)
|
||||
{
|
||||
return await GetOptionsAsync(key, email, EmployeeType.All);
|
||||
}
|
||||
|
||||
public async Task<LinkOptions> GetOptionsAsync(string key, string email, EmployeeType employeeType)
|
||||
{
|
||||
var options = new LinkOptions();
|
||||
|
||||
var payload = _docSpaceLinksHelper.Parse(key);
|
||||
|
||||
if (payload != default)
|
||||
{
|
||||
options.LinkType = LinkType.InvitationToRoom;
|
||||
|
||||
var record = await GetRecordAsync(payload);
|
||||
|
||||
if (record == null)
|
||||
{
|
||||
return options;
|
||||
}
|
||||
|
||||
options.IsCorrect = true;
|
||||
options.RoomId = record.EntryId.ToString();
|
||||
options.Share = record.Share;
|
||||
options.Id = record.Subject;
|
||||
options.EmployeeType = FileSecurity.GetTypeByShare(record.Share);
|
||||
}
|
||||
else if (_docSpaceLinksHelper.ValidateEmailLink(email, key, employeeType) == EmailValidationKeyProvider.ValidationResult.Ok)
|
||||
{
|
||||
options.IsCorrect = true;
|
||||
options.LinkType = LinkType.InvitationByEmail;
|
||||
options.EmployeeType = employeeType;
|
||||
}
|
||||
else if (_docSpaceLinksHelper.ValidateExtarnalLink(key, employeeType) == EmailValidationKeyProvider.ValidationResult.Ok)
|
||||
{
|
||||
options.LinkType = LinkType.DefaultInvitation;
|
||||
options.IsCorrect = true;
|
||||
options.EmployeeType = employeeType;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private async Task<FileShareRecord> GetRecordAsync(Guid key)
|
||||
{
|
||||
var securityDao = _daoFactory.GetSecurityDao<int>();
|
||||
var share = await securityDao.GetSharesAsync(new[] { key })
|
||||
.Where(s => s.SubjectType == SubjectType.InvitationLink)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
return share;
|
||||
}
|
||||
}
|
||||
|
||||
public class LinkOptions
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string RoomId { get; set; }
|
||||
public FileShare Share { get; set; }
|
||||
public LinkType LinkType { get; set; }
|
||||
public EmployeeType EmployeeType { get; set; }
|
||||
public bool IsCorrect { get; set; }
|
||||
}
|
||||
|
||||
[EnumExtensions]
|
||||
public enum LinkType
|
||||
{
|
||||
DefaultInvitation,
|
||||
InvitationByEmail,
|
||||
InvitationToRoom,
|
||||
}
|
@ -126,6 +126,9 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
var folder = await FolderDao.GetFolderAsync(folderId);
|
||||
var isRoom = DocSpaceHelper.IsRoom(folder.FolderType);
|
||||
|
||||
var canDelete = await FilesSecurity.CanDeleteAsync(folder);
|
||||
checkPermissions = isRoom ? !canDelete : checkPermissions;
|
||||
|
||||
T canCalculate = default;
|
||||
if (folder == null)
|
||||
{
|
||||
@ -136,7 +139,7 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
{
|
||||
this[Err] = FilesCommonResource.ErrorMassage_SecurityException_DeleteFolder;
|
||||
}
|
||||
else if (!_ignoreException && checkPermissions && !await FilesSecurity.CanDeleteAsync(folder))
|
||||
else if (!_ignoreException && checkPermissions && !canDelete)
|
||||
{
|
||||
canCalculate = FolderDao.CanCalculateSubitems(folderId) ? default : folderId;
|
||||
|
||||
@ -144,8 +147,6 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
}
|
||||
else
|
||||
{
|
||||
checkPermissions = isRoom ? false : checkPermissions;
|
||||
|
||||
canCalculate = FolderDao.CanCalculateSubitems(folderId) ? default : folderId;
|
||||
|
||||
await fileMarker.RemoveMarkAsNewForAllAsync(folder);
|
||||
|
@ -42,7 +42,7 @@ public class FileSharingAceHelper<T>
|
||||
private readonly FileSharingHelper _fileSharingHelper;
|
||||
private readonly FileTrackerHelper _fileTracker;
|
||||
private readonly FilesSettingsHelper _filesSettingsHelper;
|
||||
private readonly RoomLinkService _roomLinkService;
|
||||
private readonly InvitationLinkService _invitationLinkService;
|
||||
private readonly StudioNotifyService _studioNotifyService;
|
||||
private readonly UsersInRoomChecker _usersInRoomChecker;
|
||||
private readonly UserManagerWrapper _userManagerWrapper;
|
||||
@ -62,7 +62,7 @@ public class FileSharingAceHelper<T>
|
||||
FileSharingHelper fileSharingHelper,
|
||||
FileTrackerHelper fileTracker,
|
||||
FilesSettingsHelper filesSettingsHelper,
|
||||
RoomLinkService roomLinkService,
|
||||
InvitationLinkService invitationLinkService,
|
||||
StudioNotifyService studioNotifyService,
|
||||
ILoggerProvider loggerProvider,
|
||||
UsersInRoomChecker usersInRoomChecker,
|
||||
@ -81,7 +81,7 @@ public class FileSharingAceHelper<T>
|
||||
_fileSharingHelper = fileSharingHelper;
|
||||
_fileTracker = fileTracker;
|
||||
_filesSettingsHelper = filesSettingsHelper;
|
||||
_roomLinkService = roomLinkService;
|
||||
_invitationLinkService = invitationLinkService;
|
||||
_studioNotifyService = studioNotifyService;
|
||||
_usersInRoomChecker = usersInRoomChecker;
|
||||
_logger = loggerProvider.CreateLogger("ASC.Files");
|
||||
@ -226,7 +226,7 @@ public class FileSharingAceHelper<T>
|
||||
|
||||
if (emailInvite)
|
||||
{
|
||||
var link = _roomLinkService.GetInvitationLink(w.Email, share, _authContext.CurrentAccount.ID);
|
||||
var link = _invitationLinkService.GetInvitationLink(w.Email, share, _authContext.CurrentAccount.ID);
|
||||
_studioNotifyService.SendEmailRoomInvite(w.Email, entry.Title, link);
|
||||
_logger.Debug(link);
|
||||
}
|
||||
@ -431,7 +431,7 @@ public class FileSharing
|
||||
private readonly IDaoFactory _daoFactory;
|
||||
private readonly FileSharingHelper _fileSharingHelper;
|
||||
private readonly FilesSettingsHelper _filesSettingsHelper;
|
||||
private readonly RoomLinkService _roomLinkService;
|
||||
private readonly InvitationLinkService _invitationLinkService;
|
||||
|
||||
public FileSharing(
|
||||
Global global,
|
||||
@ -444,7 +444,7 @@ public class FileSharing
|
||||
IDaoFactory daoFactory,
|
||||
FileSharingHelper fileSharingHelper,
|
||||
FilesSettingsHelper filesSettingsHelper,
|
||||
RoomLinkService roomLinkService)
|
||||
InvitationLinkService invitationLinkService)
|
||||
{
|
||||
_global = global;
|
||||
_fileSecurity = fileSecurity;
|
||||
@ -456,7 +456,7 @@ public class FileSharing
|
||||
_fileSharingHelper = fileSharingHelper;
|
||||
_filesSettingsHelper = filesSettingsHelper;
|
||||
_logger = logger;
|
||||
_roomLinkService = roomLinkService;
|
||||
_invitationLinkService = invitationLinkService;
|
||||
}
|
||||
|
||||
public Task<bool> CanSetAccessAsync<T>(FileEntry<T> entry)
|
||||
@ -545,7 +545,7 @@ public class FileSharing
|
||||
|
||||
if (isRoom && r.IsLink)
|
||||
{
|
||||
w.Link = _roomLinkService.GetInvitationLink(r.Subject, r.Owner);
|
||||
w.Link = _invitationLinkService.GetInvitationLink(r.Subject, _authContext.CurrentAccount.ID);
|
||||
w.SubjectGroup = true;
|
||||
w.CanEditAccess = false;
|
||||
}
|
||||
@ -568,7 +568,7 @@ public class FileSharing
|
||||
var w = new AceWrapper
|
||||
{
|
||||
Id = id,
|
||||
Link = _roomLinkService.GetInvitationLink(id, _authContext.CurrentAccount.ID),
|
||||
Link = _invitationLinkService.GetInvitationLink(id, _authContext.CurrentAccount.ID),
|
||||
SubjectGroup = true,
|
||||
Access = FileShare.Read,
|
||||
Owner = false
|
||||
|
@ -591,7 +591,7 @@ public class VirtualRoomsCommonController : ApiControllerBase
|
||||
private readonly RoomLogoManager _roomLogoManager;
|
||||
private readonly SetupInfo _setupInfo;
|
||||
private readonly FileSizeComment _fileSizeComment;
|
||||
private readonly RoomLinkService _roomLinkService;
|
||||
private readonly InvitationLinkService _invitationLinkService;
|
||||
private readonly AuthContext _authContext;
|
||||
|
||||
public VirtualRoomsCommonController(
|
||||
@ -607,7 +607,7 @@ public class VirtualRoomsCommonController : ApiControllerBase
|
||||
FileSizeComment fileSizeComment,
|
||||
FolderDtoHelper folderDtoHelper,
|
||||
FileDtoHelper fileDtoHelper,
|
||||
RoomLinkService roomLinkService,
|
||||
InvitationLinkService invitationLinkService,
|
||||
AuthContext authContext) : base(folderDtoHelper, fileDtoHelper)
|
||||
{
|
||||
_fileStorageServiceInt = fileStorageServiceInt;
|
||||
@ -620,7 +620,7 @@ public class VirtualRoomsCommonController : ApiControllerBase
|
||||
_roomLogoManager = roomLogoManager;
|
||||
_setupInfo = setupInfo;
|
||||
_fileSizeComment = fileSizeComment;
|
||||
_roomLinkService = roomLinkService;
|
||||
_invitationLinkService = invitationLinkService;
|
||||
_authContext = authContext;
|
||||
}
|
||||
|
||||
@ -846,18 +846,18 @@ public class VirtualRoomsCommonController : ApiControllerBase
|
||||
[HttpPost("rooms/accept")]
|
||||
public async Task SetSecurityByLink(AcceptInvitationDto inDto)
|
||||
{
|
||||
var options = await _roomLinkService.GetOptionsAsync(inDto.Key, null);
|
||||
var linkData = await _invitationLinkService.GetProcessedLinkDataAsync(inDto.Key, null);
|
||||
|
||||
if (!options.IsCorrect)
|
||||
if (!linkData.IsCorrect)
|
||||
{
|
||||
throw new SecurityException(FilesCommonResource.ErrorMessage_InvintationLink);
|
||||
}
|
||||
|
||||
var aces = new List<AceWrapper>
|
||||
{
|
||||
new AceWrapper
|
||||
new()
|
||||
{
|
||||
Access = options.Share,
|
||||
Access = linkData.Share,
|
||||
Id = _authContext.CurrentAccount.ID
|
||||
}
|
||||
};
|
||||
@ -867,7 +867,7 @@ public class VirtualRoomsCommonController : ApiControllerBase
|
||||
InvitationLink = true
|
||||
};
|
||||
|
||||
if (int.TryParse(options.RoomId, out var id))
|
||||
if (int.TryParse(linkData.RoomId, out var id))
|
||||
{
|
||||
var aceCollection = new AceCollection<int>
|
||||
{
|
||||
@ -885,7 +885,7 @@ public class VirtualRoomsCommonController : ApiControllerBase
|
||||
{
|
||||
Aces = aces,
|
||||
Files = Array.Empty<string>(),
|
||||
Folders = new[] { options.RoomId },
|
||||
Folders = new[] { linkData.RoomId },
|
||||
AdvancedSettings = settings
|
||||
};
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using ASC.Api.Core.Security;
|
||||
using ASC.Common.Log;
|
||||
|
||||
namespace ASC.People.Api;
|
||||
@ -58,7 +59,7 @@ public class UserController : PeopleControllerBase
|
||||
private readonly AuthContext _authContext;
|
||||
private readonly SetupInfo _setupInfo;
|
||||
private readonly SettingsManager _settingsManager;
|
||||
private readonly RoomLinkService _roomLinkService;
|
||||
private readonly InvitationLinkService _invitationLinkService;
|
||||
private readonly FileSecurity _fileSecurity;
|
||||
private readonly IQuotaService _quotaService;
|
||||
private readonly CountPaidUserChecker _countPaidUserChecker;
|
||||
@ -99,7 +100,7 @@ public class UserController : PeopleControllerBase
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
SettingsManager settingsManager,
|
||||
RoomLinkService roomLinkService,
|
||||
InvitationLinkService invitationLinkService,
|
||||
FileSecurity fileSecurity,
|
||||
UsersQuotaSyncOperation usersQuotaSyncOperation,
|
||||
CountPaidUserChecker countPaidUserChecker,
|
||||
@ -134,7 +135,7 @@ public class UserController : PeopleControllerBase
|
||||
_authContext = authContext;
|
||||
_setupInfo = setupInfo;
|
||||
_settingsManager = settingsManager;
|
||||
_roomLinkService = roomLinkService;
|
||||
_invitationLinkService = invitationLinkService;
|
||||
_fileSecurity = fileSecurity;
|
||||
_countPaidUserChecker = countPaidUserChecker;
|
||||
_countUserChecker = activeUsersChecker;
|
||||
@ -207,26 +208,26 @@ public class UserController : PeopleControllerBase
|
||||
{
|
||||
_apiContext.AuthByClaim();
|
||||
|
||||
var options = inDto.FromInviteLink ? await _roomLinkService.GetOptionsAsync(inDto.Key, inDto.Email, inDto.Type) : null;
|
||||
if (options is { IsCorrect: false })
|
||||
var linkData = inDto.FromInviteLink ? await _invitationLinkService.GetProcessedLinkDataAsync(inDto.Key, inDto.Email, inDto.Type) : null;
|
||||
if (linkData is { IsCorrect: false })
|
||||
{
|
||||
throw new SecurityException(FilesCommonResource.ErrorMessage_InvintationLink);
|
||||
}
|
||||
|
||||
if (options != null)
|
||||
{
|
||||
_permissionContext.DemandPermissions(new UserSecurityProvider(Guid.Empty, options.EmployeeType) ,Constants.Action_AddRemoveUser);
|
||||
if (linkData != null)
|
||||
{
|
||||
_permissionContext.DemandPermissions(new UserSecurityProvider(Guid.Empty, linkData.EmployeeType) ,Constants.Action_AddRemoveUser);
|
||||
}
|
||||
else
|
||||
{
|
||||
_permissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
|
||||
}
|
||||
|
||||
inDto.Type = options?.EmployeeType ?? inDto.Type;
|
||||
inDto.Type = linkData?.EmployeeType ?? inDto.Type;
|
||||
|
||||
var user = new UserInfo();
|
||||
|
||||
var byEmail = options?.LinkType == LinkType.InvitationByEmail;
|
||||
var byEmail = linkData?.LinkType == InvitationLinkType.Individual;
|
||||
|
||||
if (byEmail)
|
||||
{
|
||||
@ -276,7 +277,7 @@ public class UserController : PeopleControllerBase
|
||||
_cache.Insert("REWRITE_URL" + _tenantManager.GetCurrentTenant().Id, HttpContext.Request.GetUrlRewriter().ToString(), TimeSpan.FromMinutes(5));
|
||||
|
||||
user = await _userManagerWrapper.AddUser(user, inDto.PasswordHash, inDto.FromInviteLink, true, inDto.Type,
|
||||
inDto.FromInviteLink && options is { IsCorrect: true }, true, true, byEmail);
|
||||
inDto.FromInviteLink && linkData is { IsCorrect: true }, true, true, byEmail);
|
||||
|
||||
await UpdateDepartments(inDto.Department, user);
|
||||
|
||||
@ -285,19 +286,19 @@ public class UserController : PeopleControllerBase
|
||||
await UpdatePhotoUrl(inDto.Files, user);
|
||||
}
|
||||
|
||||
if (options is { LinkType: LinkType.InvitationToRoom })
|
||||
if (linkData is { LinkType: InvitationLinkType.CommonWithRoom })
|
||||
{
|
||||
var success = int.TryParse(options.RoomId, out var id);
|
||||
var success = int.TryParse(linkData.RoomId, out var id);
|
||||
|
||||
if (success)
|
||||
{
|
||||
await _usersInRoomChecker.CheckAppend();
|
||||
await _fileSecurity.ShareAsync(id, FileEntryType.Folder, user.Id, options.Share);
|
||||
await _fileSecurity.ShareAsync(id, FileEntryType.Folder, user.Id, linkData.Share);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _usersInRoomChecker.CheckAppend();
|
||||
await _fileSecurity.ShareAsync(options.RoomId, FileEntryType.Folder, user.Id, options.Share);
|
||||
await _fileSecurity.ShareAsync(linkData.RoomId, FileEntryType.Folder, user.Id, linkData.Share);
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,7 +325,7 @@ public class UserController : PeopleControllerBase
|
||||
}
|
||||
|
||||
var user = await _userManagerWrapper.AddInvitedUserAsync(invite.Email, invite.Type);
|
||||
var link = _roomLinkService.GetInvitationLink(user.Email, invite.Type, _authContext.CurrentAccount.ID);
|
||||
var link = _invitationLinkService.GetInvitationLink(user.Email, invite.Type, _authContext.CurrentAccount.ID);
|
||||
|
||||
_studioNotifyService.SendDocSpaceInvite(user.Email, link);
|
||||
_logger.Debug(link);
|
||||
@ -742,7 +743,7 @@ public class UserController : PeopleControllerBase
|
||||
continue;
|
||||
}
|
||||
|
||||
var link = _roomLinkService.GetInvitationLink(user.Email, type, _authContext.CurrentAccount.ID);
|
||||
var link = _invitationLinkService.GetInvitationLink(user.Email, type, _authContext.CurrentAccount.ID);
|
||||
_studioNotifyService.SendDocSpaceInvite(user.Email, link);
|
||||
}
|
||||
else
|
||||
|
@ -70,7 +70,7 @@ public class AuthenticationController : ControllerBase
|
||||
private readonly EmailValidationKeyProvider _emailValidationKeyProvider;
|
||||
private readonly BruteForceLoginManager _bruteForceLoginManager;
|
||||
private readonly ILogger<AuthenticationController> _logger;
|
||||
private readonly RoomLinkService _roomLinkService;
|
||||
private readonly InvitationLinkService _invitationLinkService;
|
||||
|
||||
public AuthenticationController(
|
||||
UserManager userManager,
|
||||
@ -108,7 +108,7 @@ public class AuthenticationController : ControllerBase
|
||||
TfaAppAuthSettingsHelper tfaAppAuthSettingsHelper,
|
||||
EmailValidationKeyProvider emailValidationKeyProvider,
|
||||
ILogger<AuthenticationController> logger,
|
||||
RoomLinkService roomLinkService)
|
||||
InvitationLinkService invitationLinkService)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_tenantManager = tenantManager;
|
||||
@ -145,7 +145,7 @@ public class AuthenticationController : ControllerBase
|
||||
_tfaAppAuthSettingsHelper = tfaAppAuthSettingsHelper;
|
||||
_emailValidationKeyProvider = emailValidationKeyProvider;
|
||||
_logger = logger;
|
||||
_roomLinkService = roomLinkService;
|
||||
_invitationLinkService = invitationLinkService;
|
||||
}
|
||||
|
||||
[AllowNotPayment]
|
||||
@ -321,17 +321,14 @@ public class AuthenticationController : ControllerBase
|
||||
[HttpPost("confirm")]
|
||||
public async Task<ValidationResult> CheckConfirm(EmailValidationKeyModel inDto)
|
||||
{
|
||||
if (inDto.Type == ConfirmType.LinkInvite)
|
||||
if (inDto.Type != ConfirmType.LinkInvite)
|
||||
{
|
||||
var options = await _roomLinkService.GetOptionsAsync(inDto.Key, inDto.Email, inDto.EmplType ?? default);
|
||||
|
||||
if (options.LinkType == LinkType.InvitationToRoom && !options.IsCorrect)
|
||||
{
|
||||
return ValidationResult.Invalid;
|
||||
}
|
||||
return _emailValidationKeyModelHelper.Validate(inDto);
|
||||
}
|
||||
|
||||
return _emailValidationKeyModelHelper.Validate(inDto);
|
||||
|
||||
var linkData = await _invitationLinkService.GetProcessedLinkDataAsync(inDto.Key, inDto.Email, inDto.EmplType ?? default, inDto.UiD ?? default);
|
||||
|
||||
return linkData.Result;
|
||||
}
|
||||
|
||||
[AllowNotPayment]
|
||||
|
Loading…
Reference in New Issue
Block a user