public async Task <ClientConfigurationModel> Configuration() { if (UploadChunkSize == 0) { UploadChunkSize = await APIConnection.File.GetUploadChunkSizeAsync(null); } var config = new ClientConfigurationModel { MaxChunkSize = UploadChunkSize, UserTimeZone = this.APIConnection.UserTimeZone, MaxFileSize = ManagerConfiguration.MaxFileSize }; if (APIConnection.ClientClaims == "FullFrame") { config.IsTopNavigationVisible = true; } if (EDiscoveryUtility.IsUserEDiscovery(APIConnection.UserAccessIdentifiers)) { config.IsSearchEnabled = false; } else { config.IsSearchEnabled = ManagerConfiguration.IsFeatureEnabledSearch; } return(config); }
public override void BuildDynamicFolders(PathIdentifier identifier, ItemQueryResponse page, FolderModel folder, bool isRestrictedView = false) { if (EDiscoveryUtility.IsUserEDiscovery(connection.UserAccessIdentifiers) || LEOUploadUtility.IsUserLeo(connection.UserAccessIdentifiers)) { return; } var logPathIdentifier = new PathIdentifier(identifier) { PathKey = LOG_READER_PATH_KEY }; if (page.PathTree.Paths == null) { page.PathTree.Paths = new List <ManagerPathModel>(); } // Last the parent / root node of 'eDiscovery' var logPath = new ManagerPathModel { Identifier = logPathIdentifier, Icons = new string[] { "fa-history" }, Name = "Logs", FullPath = LOG_READER_PATH_KEY, AllowedOperations = null, Paths = new List <ManagerPathModel>(), IsExpanded = false }; page.PathTree.Paths.Add(logPath); }
public List <EDiscoveryManagerPathModel> BuildDatedPackagesDynamicFolder(FolderModel folder) { var managerPaths = new List <EDiscoveryManagerPathModel>(); var packageMap = folder.Read <EDiscoveryPackageMap>(MetadataKeyConstants.E_DISCOVERY_PACKAGE_MAP_METAKEY); if (this.IsModuleActive(folder)) { // go through all the folders, and find all the foreach (var file in folder.Files.Rows .Where(f => f.Read <string>(MetadataKeyConstants.E_DISCOVERY_SHARE_PACKGAGE) != null) ) { var sharePackageName = file.Read <string>(MetadataKeyConstants.E_DISCOVERY_SHARE_PACKGAGE); var sharePackageIdentifier = new PathIdentifier(file.Identifier as FolderIdentifier, "eDiscovery/" + sharePackageName); // Here we're checking to make sure we haven't already added this 'dated share folder' if (!managerPaths.Any(mp => mp.Identifier.Equals(sharePackageIdentifier))) { var processor = new PathProcessor(folder.Identifier); processor.Read(folder, skipFolderPaths: true, pathReader: f => { var sharePath = f.MetaEDiscoveryPathIdentifierRead(); if (sharePackageName != null && f.Read <string>(MetadataKeyConstants.E_DISCOVERY_SHARE_PACKGAGE) != sharePackageName) { return(null); } if (sharePath != null) { return(sharePackageIdentifier.CreateChild(sharePath.PathKey)); } else { return(sharePath); } }); var packagePath = new EDiscoveryManagerPathModel() { Identifier = sharePackageIdentifier, Icons = new string[] { EDiscoveryUtility.EDISCOVERY_FOLDER_COLOR_STYLE }, Name = sharePackageName, FullPath = sharePackageIdentifier.FullName, Paths = processor[sharePackageIdentifier]?.Paths, CustomName = EDiscoveryUtility.GetCustomName(packageMap, sharePackageName), AllowedOperations = EDiscoveryUtility.IsUserEDiscovery(connection.UserAccessIdentifiers) ? new AllowedOperation[] { } : new AllowedOperation[] { AllowedOperation.GetAllowedOperationEditPackageName(folder.Identifier, sharePackageName) }, }; managerPaths.Add(packagePath); } } } return(managerPaths); }
public override BaseItemQueryHandler GetInitialQueryHandler(PathIdentifier identifier, PathService pathService, APIConnection connection, IAuditLogStore auditLogStore, ManagerConfiguration managerConfiguration, FileService fileService) { // If the user is an eDiscovery user, we're going to use a special query handler that will return only the files the user is allowed to see. if (EDiscoveryUtility.IsUserEDiscovery(connection.UserAccessIdentifiers)) { var userKey = connection.UserIdentifier.UserKey; // here we're going to do some basic security check. The userKey has a folder key on it. We need to make sure that matches. var userKeyTokens = userKey.Split(':').ToList(); // now this will be an array, of tokens, keep in mind userkeys can be something like Defendant:18337980:[email protected], so we want everything before the last ':' // so we can remove the last token, and then we'll be able to just join back everything else. userKeyTokens.RemoveAt(userKeyTokens.Count - 1); var folderKeyFromUser = String.Join(':', userKeyTokens); if (folderKeyFromUser != identifier.FolderKey) { throw (new UnauthorizedAccessException($"You're not authorized for this eDiscovery Folder userKey:{userKey} tried to access: {identifier.FolderKey}")); } return(new EDiscoveryUserItemQueryHandler(pathService, connection, auditLogStore, this, managerConfiguration, fileService)); } if (identifier.PathKey == EDiscoveryUtility.E_DISCOVERY_PATH_KEY) { return(new EDiscoveryRootQueryHandler(pathService, connection, auditLogStore, this, managerConfiguration, fileService)); } if (identifier.PathKey != null && identifier.FullName.StartsWith(EDiscoveryUtility.E_DISCOVERY_NOT_SHARED_PATH_KEY)) { return(new EDiscoveryStagedItemQueryHandler(pathService, connection, managerConfiguration, fileService)); } if (identifier.PathKey != null && (identifier.FullName.StartsWith(EDiscoveryUtility.E_DISCOVERY_DATED_PACKAGE_PATH_KEY) || identifier.FullName.StartsWith(EDiscoveryUtility.E_DISCOVERY_ALL_PACKAGE_PATH_KEY))) { return(new EDiscoveryDatedPackageItemQueryHandler(pathService, connection, managerConfiguration, fileService)); } return(null); }
private async Task ExecuteDownload( DownloadRequest request, HttpResponse httpResponse, FileModel fileModel, long?from = 0, long?to = 0, CancellationToken cancellationToken = default(CancellationToken) ) { // setup a handler to configure response headers void doHeaders(DownloadHeaderInformation headerInfo) { if (from != 0 || to != null) { httpResponse.StatusCode = 206; httpResponse.Headers.Add("Content-Range", new ContentRangeHeaderValue( headerInfo.RangeFrom, headerInfo.RangeTo, headerInfo.RangeLength ).ToString()); } var contentDisposition = new ContentDispositionHeaderValue(request.Open ? "inline" : "attachment"); contentDisposition.SetHttpFileName(headerInfo.FileName); httpResponse.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString(); httpResponse.Headers[HeaderNames.Pragma] = "no-cache"; httpResponse.Headers[HeaderNames.AcceptRanges] = "bytes"; } if (WatermarkFilter.IsSupportedFileType(fileModel.Extension) && EDiscoveryUtility.IsUserEDiscovery(Connection.UserAccessIdentifiers)) { // we're going to inject the Watermarker into the stream processing // so we don't use the standard FileDownloadAsync overload, instead we pass a stream callback await Connection.File.DownloadAsync( fileModel.Identifier, onDownloadHeaderInformation : doHeaders, onStreamAvailable : async(stream, cancel) => { // If we're downloading a child file, for instance in the case of a docx, we're generating a pdf. // when we generate that pdf, it won't inherit the metadata around eDiscovery. We need to get that file info, so we can get a share package name. FileIdentifier parentIdentifier; FileModel parentFileModel = fileModel; if ((parentIdentifier = fileModel.MetaChildOfRead()) != null) { parentFileModel = await Connection.File.GetAsync(parentIdentifier); } else { parentFileModel = fileModel; } // stream is a readstream of the file from the API server // pass that to the Watermarker adn the HTTPResponse body stream as the output // We need to get the path name for this file, which will give us what the discovery package it's in. var packageName = parentFileModel.Read <string>(MetadataKeyConstants.E_DISCOVERY_SHARE_PACKGAGE); var watermarkUser = await Connection.User.GetAsync(Connection.UserIdentifier); // this code is redundant with PathService.DownloadZip await WatermarkFilter.Execute(stream, httpResponse.Body, fileModel.Extension, $"Defense {packageName} {watermarkUser.EmailAddress}" ); }, from : from, to : to, cancellationToken : cancellationToken ); } else { await Connection.File.DownloadAsync( fileModel.Identifier, onDownloadHeaderInformation : doHeaders, onStreamAvailable : (stream, cancel) => stream.CopyToAsync(httpResponse.Body), from : from, to : to, cancellationToken : cancellationToken ); } }
public async Task <T> LoadSet <T>(FileIdentifier fileIdentifier) where T : BaseSet { var file = await api.File.GetAsync(fileIdentifier); var fileStatus = await api.File.GetOnlineStatusAsync(fileIdentifier); var organization = await api.Organization.GetAsync(fileIdentifier as OrganizationIdentifier); BaseSet set = null; // this is awful, but no clear security check to perform bool isPrivileged = !EDiscoveryUtility.IsUserEDiscovery(this.api.UserAccessIdentifiers) && !LEOUploadUtility.IsUserLeo(this.api.UserAccessIdentifiers); if (typeof(T).Equals(typeof(TextSet))) { set = TextService.TextSetGet(file, true); } if (typeof(T).Equals(typeof(DocumentSet))) { set = DocumentSetService.DocumentSetGet(file); } if (typeof(T).Equals(typeof(MediaSet))) { set = MediaService.MediaSetGet(organization, file, isPrivileged); } if (typeof(T).Equals(typeof(TranscriptSet))) { var transcriptSet = TranscriptService.TranscriptSetGet(organization, file); transcriptSet.Segments = await TranscriptService.LoadSegments(api, transcriptSet.Subtitles?.FirstOrDefault()?.FileIdentifier); set = transcriptSet; } if (typeof(T).Equals(typeof(ClipSet))) { var clipSet = ClipService.ClipSetGet(organization, file); set = clipSet; } if (typeof(T).Equals(typeof(ImageSet))) { set = ImageService.ImageSetGet(file); } if (typeof(T).Equals(typeof(UnknownSet))) { set = UnknownService.UnknownSetGet(file); } if (set.AllowedOperations == null) { set.AllowedOperations = new[] { AllowedOperation.GetAllowedOperationDownload(fileIdentifier, false) } } ; set.RootFileIdentifier = file.Read(MetadataKeyConstants.CHILDOF, defaultValue: file.Identifier); if (set.RootFileIdentifier.Equals(fileIdentifier)) { set.Views = DetectFileViews(organization, file); } else { set.Views = DetectFileViews(organization, await api.File.GetAsync(set.RootFileIdentifier)); } // some wierd logic for eDiscovery // if eDiscovery, then no subtitles if (set is MediaSet && EDiscoveryUtility.IsUserEDiscovery(api.UserAccessIdentifiers)) { var media = set as MediaSet; media.Subtitles = null; } if (fileStatus != FileModel.OnlineStatus.Online) { set.Views = new ManagerFileView[] { new ManagerFileView { ViewerType = ManagerFileView.ViewerTypeEnum.Offline, Identifier = set.RootFileIdentifier } }; set.AllowedOperations = new AllowedOperation[] { AllowedOperation.GetAllowedOperationRequestOnlineFolder(set.RootFileIdentifier) }; set.RootFileIdentifier = null; } return(set as T); }
public async Task DownloadZip( string fileName, IEnumerable <FileIdentifier> fileIdentifiers, HttpResponse response, Func <FileModel, PathIdentifier> pathGenerator = null, CancellationToken cancellationToken = default(CancellationToken) ) { if (pathGenerator == null) { pathGenerator = APIModelExtensions.MetaPathIdentifierRead; } response.StatusCode = 200; response.ContentType = "application/zip"; var contentDisposition = new ContentDispositionHeaderValue("attachment"); contentDisposition.SetHttpFileName(fileName); response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString(); var isEDiscoveryUser = EDiscoveryUtility.IsUserEDiscovery(Connection.UserAccessIdentifiers); OrganizationModel organization = null; using (var archive = new ZipArchive(response.Body, ZipArchiveMode.Create)) { foreach (var fileIdentifier in fileIdentifiers) { if (organization == null || organization.Identifier.OrganizationKey != fileIdentifier.OrganizationKey) { organization = await Connection.Organization.GetAsync(fileIdentifier as OrganizationIdentifier); } var fileModel = await Connection.File.GetAsync(fileIdentifier); var views = ViewSetService.DetectFileViews(organization, fileModel); var newFileExtension = null as string; var contentsFileIdentifier = fileIdentifier; if (views.Any()) { var first = views.First(); switch (first.ViewerType) { case ManagerFileView.ViewerTypeEnum.Video: var mediaSet = await viewSetService.LoadSet <MediaSet>(fileIdentifier); var mp4 = mediaSet.Sources.FirstOrDefault(s => s.Type == "video/mp4"); if (mp4 != null) { newFileExtension = "mp4"; contentsFileIdentifier = mp4.FileIdentifier; } break; case ManagerFileView.ViewerTypeEnum.Document: if (fileModel.Extension == "docx") { var documentSet = await viewSetService.LoadSet <DocumentSet>(fileIdentifier); var pdf = documentSet.FileIdentifier; if (pdf != null) { newFileExtension = "pdf"; contentsFileIdentifier = pdf; } } break; } } var path = pathGenerator(fileModel); string name = fileModel.Name; if (newFileExtension != null) { name = $"{Path.GetFileNameWithoutExtension(name)}.{newFileExtension}"; } else { newFileExtension = fileModel.Extension; } name = MakeFilenameSafe(name); var filename = path != null ? Path.Combine(path.PathKey, name) : name; var entry = archive.CreateEntry(filename); using (var fileStream = entry.Open()) { await Connection.File.DownloadAsync( contentsFileIdentifier, onStreamAvailable : async(stream, cancel) => { if (isEDiscoveryUser && WatermarkFilter.IsSupportedFileType(newFileExtension)) { var packageName = fileModel.Read <string>( MetadataKeyConstants.E_DISCOVERY_SHARE_PACKGAGE); var watermarkUser = await Connection.User.GetAsync(Connection.UserIdentifier); // this code is redundant with FileService.ExecuteDownload await WatermarkFilter.Execute(stream, fileStream, newFileExtension, $"Defense {packageName} {watermarkUser.EmailAddress}" ); } else { await stream.CopyToAsync(fileStream); } }, cancellationToken : cancellationToken ); } } } }