2020-01-27 11:15:18 +00:00
/ *
*
* ( 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.Linq ;
using System.Security ;
2020-02-06 13:06:36 +00:00
using ASC.Common.Logging ;
using ASC.Core ;
2020-01-27 11:15:18 +00:00
using ASC.Core.Users ;
using ASC.Files.Core ;
using ASC.Files.Core.Security ;
using ASC.Web.Core.Files ;
2020-02-06 13:06:36 +00:00
using ASC.Web.Core.Users ;
2020-01-27 11:15:18 +00:00
using ASC.Web.Files.Classes ;
using ASC.Web.Files.Resources ;
using ASC.Web.Files.Services.DocumentService ;
using ASC.Web.Files.Services.NotifyService ;
using ASC.Web.Files.Services.WCFService ;
2020-02-06 13:06:36 +00:00
using Microsoft.Extensions.Options ;
2020-01-27 11:15:18 +00:00
namespace ASC.Web.Files.Utils
{
2020-02-06 13:06:36 +00:00
public class FileSharing
2020-01-27 11:15:18 +00:00
{
2020-02-06 13:06:36 +00:00
public Global Global { get ; }
public GlobalFolderHelper GlobalFolderHelper { get ; }
public FileSecurity FileSecurity { get ; }
public AuthContext AuthContext { get ; }
public UserManager UserManager { get ; }
public DisplayUserSettingsHelper DisplayUserSettingsHelper { get ; }
public FileMarker FileMarker { get ; }
public FileShareLink FileShareLink { get ; }
public FileUtility FileUtility { get ; }
public DocumentServiceHelper DocumentServiceHelper { get ; }
public CoreBaseSettings CoreBaseSettings { get ; }
public ILog Logger { get ; }
public FileSharing (
Global global ,
GlobalFolderHelper globalFolderHelper ,
FileSecurity fileSecurity ,
AuthContext authContext ,
UserManager userManager ,
IOptionsMonitor < ILog > optionsMonitor ,
DisplayUserSettingsHelper displayUserSettingsHelper ,
FileMarker fileMarker ,
FileShareLink fileShareLink ,
FileUtility fileUtility ,
DocumentServiceHelper documentServiceHelper ,
CoreBaseSettings coreBaseSettings )
{
Global = global ;
GlobalFolderHelper = globalFolderHelper ;
FileSecurity = fileSecurity ;
AuthContext = authContext ;
UserManager = userManager ;
DisplayUserSettingsHelper = displayUserSettingsHelper ;
FileMarker = fileMarker ;
FileShareLink = fileShareLink ;
FileUtility = fileUtility ;
DocumentServiceHelper = documentServiceHelper ;
CoreBaseSettings = coreBaseSettings ;
Logger = optionsMonitor . CurrentValue ;
}
public bool CanSetAccess ( FileEntry entry )
2020-01-27 11:15:18 +00:00
{
return
entry ! = null
& & ( entry . RootFolderType = = FolderType . COMMON & & Global . IsAdministrator
| | entry . RootFolderType = = FolderType . USER
2020-02-06 13:06:36 +00:00
& & ( Equals ( entry . RootFolderId , GlobalFolderHelper . FolderMy ) | | FileSecurity . CanEdit ( entry ) )
& & ! UserManager . GetUsers ( AuthContext . CurrentAccount . ID ) . IsVisitor ( UserManager ) ) ;
2020-01-27 11:15:18 +00:00
}
2020-02-06 13:06:36 +00:00
public List < AceWrapper > GetSharedInfo ( FileEntry entry )
2020-01-27 11:15:18 +00:00
{
if ( entry = = null ) throw new ArgumentNullException ( FilesCommonResource . ErrorMassage_BadRequest ) ;
if ( ! CanSetAccess ( entry ) )
{
2020-02-06 13:06:36 +00:00
Logger . ErrorFormat ( "User {0} can't get shared info for {1} {2}" , AuthContext . CurrentAccount . ID , ( entry . FileEntryType = = FileEntryType . File ? "file" : "folder" ) , entry . ID ) ;
2020-01-27 11:15:18 +00:00
throw new SecurityException ( FilesCommonResource . ErrorMassage_SecurityException ) ;
}
var linkAccess = FileShare . Restrict ;
var result = new List < AceWrapper > ( ) ;
2020-02-06 13:06:36 +00:00
var fileSecurity = FileSecurity ;
2020-01-27 11:15:18 +00:00
var records = fileSecurity
. GetShares ( entry )
. GroupBy ( r = > r . Subject )
. Select ( g = > g . OrderBy ( r = > r . Level )
. ThenBy ( r = > r . Level )
. ThenByDescending ( r = > r . Share , new FileShareRecord . ShareComparer ( ) ) . FirstOrDefault ( ) ) ;
foreach ( var r in records )
{
if ( r . Subject = = FileConstant . ShareLinkId )
{
linkAccess = r . Share ;
continue ;
}
2020-02-06 13:06:36 +00:00
var u = UserManager . GetUsers ( r . Subject ) ;
2020-01-27 11:15:18 +00:00
var isgroup = false ;
2020-02-06 13:06:36 +00:00
var title = u . DisplayUserName ( false , DisplayUserSettingsHelper ) ;
2020-01-27 11:15:18 +00:00
if ( u . ID = = Constants . LostUser . ID )
{
2020-02-06 13:06:36 +00:00
var g = UserManager . GetGroupInfo ( r . Subject ) ;
2020-01-27 11:15:18 +00:00
isgroup = true ;
title = g . Name ;
if ( g . ID = = Constants . GroupAdmin . ID )
title = FilesCommonResource . Admin ;
if ( g . ID = = Constants . GroupEveryone . ID )
title = FilesCommonResource . Everyone ;
if ( g . ID = = Constants . LostGroupInfo . ID )
{
fileSecurity . RemoveSubject ( r . Subject ) ;
continue ;
}
}
var w = new AceWrapper
2020-02-06 13:06:36 +00:00
{
SubjectId = r . Subject ,
SubjectName = title ,
SubjectGroup = isgroup ,
Share = r . Share ,
Owner =
2020-01-27 11:15:18 +00:00
entry . RootFolderType = = FolderType . USER
? entry . RootFolderCreator = = r . Subject
: entry . CreateBy = = r . Subject ,
2020-02-06 13:06:36 +00:00
LockedRights = r . Subject = = AuthContext . CurrentAccount . ID
} ;
2020-01-27 11:15:18 +00:00
result . Add ( w ) ;
}
if ( entry . FileEntryType = = FileEntryType . File & & result . All ( w = > w . SubjectId ! = FileConstant . ShareLinkId )
& & entry . FileEntryType = = FileEntryType . File
& & ! ( ( File ) entry ) . Encrypted )
{
var w = new AceWrapper
2020-02-06 13:06:36 +00:00
{
SubjectId = FileConstant . ShareLinkId ,
Link = FileShareLink . GetLink ( ( File ) entry ) ,
SubjectGroup = true ,
Share = linkAccess ,
Owner = false
} ;
2020-01-27 11:15:18 +00:00
result . Add ( w ) ;
}
if ( ! result . Any ( w = > w . Owner ) )
{
var ownerId = entry . RootFolderType = = FolderType . USER ? entry . RootFolderCreator : entry . CreateBy ;
var w = new AceWrapper
2020-02-06 13:06:36 +00:00
{
SubjectId = ownerId ,
SubjectName = Global . GetUserName ( ownerId ) ,
SubjectGroup = false ,
Share = FileShare . ReadWrite ,
Owner = true
} ;
2020-01-27 11:15:18 +00:00
result . Add ( w ) ;
}
2020-02-06 13:06:36 +00:00
if ( result . Any ( w = > w . SubjectId = = AuthContext . CurrentAccount . ID ) )
2020-01-27 11:15:18 +00:00
{
2020-02-06 13:06:36 +00:00
result . Single ( w = > w . SubjectId = = AuthContext . CurrentAccount . ID ) . LockedRights = true ;
2020-01-27 11:15:18 +00:00
}
if ( entry . RootFolderType = = FolderType . COMMON )
{
if ( result . All ( w = > w . SubjectId ! = Constants . GroupAdmin . ID ) )
{
var w = new AceWrapper
2020-02-06 13:06:36 +00:00
{
SubjectId = Constants . GroupAdmin . ID ,
SubjectName = FilesCommonResource . Admin ,
SubjectGroup = true ,
Share = FileShare . ReadWrite ,
Owner = false ,
LockedRights = true ,
} ;
2020-01-27 11:15:18 +00:00
result . Add ( w ) ;
}
if ( result . All ( w = > w . SubjectId ! = Constants . GroupEveryone . ID ) )
{
var w = new AceWrapper
2020-02-06 13:06:36 +00:00
{
SubjectId = Constants . GroupEveryone . ID ,
SubjectName = FilesCommonResource . Everyone ,
SubjectGroup = true ,
Share = fileSecurity . DefaultCommonShare ,
Owner = false ,
DisableRemove = true
} ;
2020-01-27 11:15:18 +00:00
result . Add ( w ) ;
}
}
return result ;
}
2020-02-06 13:06:36 +00:00
public bool SetAceObject ( List < AceWrapper > aceWrappers , FileEntry entry , bool notify , string message )
2020-01-27 11:15:18 +00:00
{
if ( entry = = null ) throw new ArgumentNullException ( FilesCommonResource . ErrorMassage_BadRequest ) ;
if ( ! CanSetAccess ( entry ) ) throw new SecurityException ( FilesCommonResource . ErrorMassage_SecurityException ) ;
2020-02-06 13:06:36 +00:00
var fileSecurity = FileSecurity ;
2020-01-27 11:15:18 +00:00
var entryType = entry . FileEntryType ;
var recipients = new Dictionary < Guid , FileShare > ( ) ;
var usersWithoutRight = new List < Guid > ( ) ;
var changed = false ;
foreach ( var w in aceWrappers . OrderByDescending ( ace = > ace . SubjectGroup ) )
{
var subjects = fileSecurity . GetUserSubjects ( w . SubjectId ) ;
var ownerId = entry . RootFolderType = = FolderType . USER ? entry . RootFolderCreator : entry . CreateBy ;
if ( entry . RootFolderType = = FolderType . COMMON & & subjects . Contains ( Constants . GroupAdmin . ID )
| | ownerId = = w . SubjectId )
continue ;
var share = w . Share ;
if ( w . SubjectId = = FileConstant . ShareLinkId )
{
2020-02-06 13:06:36 +00:00
if ( w . Share = = FileShare . ReadWrite & & UserManager . GetUsers ( AuthContext . CurrentAccount . ID ) . IsVisitor ( UserManager ) ) throw new SecurityException ( FilesCommonResource . ErrorMassage_SecurityException ) ;
if ( CoreBaseSettings . Personal & & ! FileUtility . CanWebView ( entry . Title ) & & w . Share ! = FileShare . Restrict ) throw new SecurityException ( FilesCommonResource . ErrorMassage_BadRequest ) ;
2020-01-27 11:15:18 +00:00
share = w . Share = = FileShare . Restrict ? FileShare . None : w . Share ;
}
fileSecurity . Share ( entry . ID , entryType , w . SubjectId , share ) ;
changed = true ;
if ( w . SubjectId = = FileConstant . ShareLinkId )
continue ;
entry . Access = share ;
var listUsersId = new List < Guid > ( ) ;
if ( w . SubjectGroup )
2020-02-06 13:06:36 +00:00
listUsersId = UserManager . GetUsersByGroup ( w . SubjectId ) . Select ( ui = > ui . ID ) . ToList ( ) ;
2020-01-27 11:15:18 +00:00
else
listUsersId . Add ( w . SubjectId ) ;
2020-02-06 13:06:36 +00:00
listUsersId . Remove ( AuthContext . CurrentAccount . ID ) ;
2020-01-27 11:15:18 +00:00
if ( entryType = = FileEntryType . File )
{
listUsersId . ForEach ( uid = > FileTracker . ChangeRight ( entry . ID , uid , true ) ) ;
}
var addRecipient = share = = FileShare . Read
| | share = = FileShare . ReadWrite
| | share = = FileShare . Review
| | share = = FileShare . FillForms
| | share = = FileShare . Comment
| | share = = FileShare . None & & entry . RootFolderType = = FolderType . COMMON ;
var removeNew = share = = FileShare . None & & entry . RootFolderType = = FolderType . USER
| | share = = FileShare . Restrict ;
listUsersId . ForEach ( id = >
{
recipients . Remove ( id ) ;
if ( addRecipient )
{
recipients . Add ( id , share ) ;
}
else if ( removeNew )
{
usersWithoutRight . Add ( id ) ;
}
} ) ;
}
if ( entryType = = FileEntryType . File )
{
2020-02-06 13:06:36 +00:00
DocumentServiceHelper . CheckUsersForDrop ( ( File ) entry ) ;
2020-01-27 11:15:18 +00:00
}
if ( recipients . Any ( ) )
{
if ( entryType = = FileEntryType . File
| | ( ( Folder ) entry ) . TotalSubFolders + ( ( Folder ) entry ) . TotalFiles > 0
| | entry . ProviderEntry )
{
FileMarker . MarkAsNew ( entry , recipients . Keys . ToList ( ) ) ;
}
if ( entry . RootFolderType = = FolderType . USER
& & notify )
{
NotifyClient . SendShareNotice ( entry , recipients , message ) ;
}
}
usersWithoutRight . ForEach ( userId = > FileMarker . RemoveMarkAsNew ( entry , userId ) ) ;
return changed ;
}
2020-02-06 13:06:36 +00:00
public void RemoveAce ( List < FileEntry > entries )
2020-01-27 11:15:18 +00:00
{
2020-02-06 13:06:36 +00:00
var fileSecurity = FileSecurity ;
2020-01-27 11:15:18 +00:00
entries . ForEach (
entry = >
{
2020-02-06 13:06:36 +00:00
if ( entry . RootFolderType ! = FolderType . USER | | Equals ( entry . RootFolderId , GlobalFolderHelper . FolderMy ) )
2020-01-27 11:15:18 +00:00
return ;
var entryType = entry . FileEntryType ;
2020-02-06 13:06:36 +00:00
fileSecurity . Share ( entry . ID , entryType , AuthContext . CurrentAccount . ID , fileSecurity . DefaultMyShare ) ;
2020-01-27 11:15:18 +00:00
if ( entryType = = FileEntryType . File )
{
DocumentServiceHelper . CheckUsersForDrop ( ( File ) entry ) ;
}
FileMarker . RemoveMarkAsNew ( entry ) ;
} ) ;
}
}
}