Esempio n. 1
0
        public async Task NotificationToAllAsync <T>(ApiNotificationResponseModel <T> message,
                                                     CancellationToken cancellationToken)
        {
            await _webSocketConnectionsService.SendToAllAsync(message, cancellationToken);

            await _notificationQuery.AddNotification(message);
        }
Esempio n. 2
0
        private async Task <List <FileIndexItem> > SyncTaskInternal(Tuple <string, string, WatcherChangeTypes> watcherOutput)
        {
            var(fullFilePath, toPath, type) = watcherOutput;
            var operation = CreateNewRequestTelemetry(fullFilePath);

            var syncData = new List <FileIndexItem>();

            _logger !.LogInformation($"[SyncWatcherConnector] [{fullFilePath}] - [{toPath}] - [{type}]");

            if (type == WatcherChangeTypes.Renamed && !string.IsNullOrEmpty(toPath))
            {
                // from path sync
                var   path = _appSettings !.FullPathToDatabaseStyle(fullFilePath);
                await _synchronize !.Sync(path);

                syncData.Add(new FileIndexItem(_appSettings.FullPathToDatabaseStyle(fullFilePath))
                {
                    IsDirectory = true,
                    Status      = FileIndexItem.ExifStatus.NotFoundSourceMissing
                });

                // and now to-path sync
                var pathToDatabaseStyle = _appSettings.FullPathToDatabaseStyle(toPath);
                syncData.AddRange(await _synchronize.Sync(pathToDatabaseStyle));
            }
            else
            {
                syncData = await _synchronize !.Sync(_appSettings !.FullPathToDatabaseStyle(fullFilePath));
            }

            var filtered = FilterBefore(syncData);

            if (!filtered.Any())
            {
                EndRequestOperation(operation);
                return(syncData);
            }

            // update users who are active right now
            var webSocketResponse =
                new ApiNotificationResponseModel <List <FileIndexItem> >(filtered, ApiNotificationType.SyncWatcherConnector);
            await _connectionsService !.SendToAllAsync(JsonSerializer.Serialize(webSocketResponse,
                                                                                DefaultJsonSerializer.CamelCase), CancellationToken.None);

            // And update the query Cache
            _query !.CacheUpdateItem(filtered.Where(p => p.Status == FileIndexItem.ExifStatus.Ok ||
                                                    p.Status == FileIndexItem.ExifStatus.Deleted).ToList());

            // remove files that are not in the index from cache
            _query.RemoveCacheItem(filtered.Where(p => p.Status == FileIndexItem.ExifStatus.NotFoundNotInIndex ||
                                                  p.Status == FileIndexItem.ExifStatus.NotFoundSourceMissing).ToList());

            if (_serviceScope != null)
            {
                await _query.DisposeAsync();
            }
            EndRequestOperation(operation);

            return(syncData);
        }
Esempio n. 3
0
        public Task <NotificationItem> AddNotification <T>(ApiNotificationResponseModel <T> content)
        {
            var stringMessage = JsonSerializer.Serialize(content,
                                                         DefaultJsonSerializer.CamelCase);

            return(AddNotification(stringMessage));
        }
Esempio n. 4
0
 private async Task TaskRun(List <FileIndexItem> fileIndexResultsList)
 {
     var webSocketResponse =
         new ApiNotificationResponseModel <List <FileIndexItem> >(fileIndexResultsList, ApiNotificationType.MetaUpdate);
     var realtimeConnectionsService = _scopeFactory.CreateScope()
                                      .ServiceProvider.GetRequiredService <IRealtimeConnectionsService>();
     await realtimeConnectionsService.NotificationToAllAsync(webSocketResponse, CancellationToken.None);
 }
Esempio n. 5
0
        public Task SendToAllAsync <T>(ApiNotificationResponseModel <T> message, CancellationToken cancellationToken)
        {
            var stringMessage = JsonSerializer.Serialize(message,
                                                         DefaultJsonSerializer.CamelCase);

            FakeSendToAllAsync.Add(stringMessage);
            return(Task.CompletedTask);
        }
Esempio n. 6
0
        private async Task HeartbeatAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                var webSocketResponse =
                    new ApiNotificationResponseModel <HeartbeatModel>(new HeartbeatModel(SpeedInSeconds),
                                                                      ApiNotificationType.Heartbeat);
                await _connectionsService.SendToAllAsync(webSocketResponse, cancellationToken);

                await Task.Delay(TimeSpan.FromSeconds(SpeedInSeconds), cancellationToken);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Update other users with a message from SyncViewModel
        /// </summary>
        /// <param name="syncResultsList">SyncViewModel</param>
        /// <param name="type">optional debug name</param>
        /// <returns>Completed send of Socket SendToAllAsync</returns>
        private async Task SyncMessageToSocket(IEnumerable <SyncViewModel> syncResultsList, ApiNotificationType type = ApiNotificationType.Unknown)
        {
            var list = syncResultsList.Select(t => new FileIndexItem(t.FilePath)
            {
                Status = t.Status, IsDirectory = true
            }).ToList();

            var webSocketResponse = new ApiNotificationResponseModel <
                List <FileIndexItem> >(list, type);

            await _notificationQuery.AddNotification(webSocketResponse);

            await _connectionsService.SendToAllAsync(webSocketResponse, CancellationToken.None);
        }
Esempio n. 8
0
        public async Task <IActionResult> Replace(string f, string fieldName, string search,
                                                  string replace, bool collections = true)
        {
            var stopwatch = StopWatchLogger.StartUpdateReplaceStopWatch();

            var fileIndexResultsList = await _metaReplaceService
                                       .Replace(f, fieldName, search, replace, collections);

            var resultsOkOrDeleteList = fileIndexResultsList.Where(
                p => p.Status == FileIndexItem.ExifStatus.Ok ||
                p.Status == FileIndexItem.ExifStatus.Deleted).ToList();

            var changedFileIndexItemName = resultsOkOrDeleteList.
                                           ToDictionary(item => item.FilePath, item => new List <string> {
                fieldName
            });

            // Update >
            _bgTaskQueue.QueueBackgroundWorkItem(async _ =>
            {
                var metaUpdateService = _scopeFactory.CreateScope()
                                        .ServiceProvider.GetRequiredService <IMetaUpdateService>();
                await metaUpdateService
                .UpdateAsync(changedFileIndexItemName, resultsOkOrDeleteList,
                             null, collections, false, 0);
            });

            // before sending not founds
            new StopWatchLogger(_logger).StopUpdateReplaceStopWatch("update", f, collections, stopwatch);

            // When all items are not found
            if (!resultsOkOrDeleteList.Any())
            {
                return(NotFound(fileIndexResultsList));
            }

            // Push direct to socket when update or replace to avoid undo after a second
            var webSocketResponse =
                new ApiNotificationResponseModel <List <FileIndexItem> >(resultsOkOrDeleteList, ApiNotificationType.Replace);
            await _connectionsService.NotificationToAllAsync(webSocketResponse, CancellationToken.None);

            return(Json(fileIndexResultsList));
        }
Esempio n. 9
0
        public async Task <IActionResult> Rename(string f, string to, bool collections = true, bool currentStatus = true)
        {
            var rename = await new RenameService(_query, _iStorage).Rename(f, to, collections);

            // When all items are not found
            if (rename.All(p => p.Status != FileIndexItem.ExifStatus.Ok))
            {
                return(NotFound(rename));
            }

            var webSocketResponse =
                new ApiNotificationResponseModel <List <FileIndexItem> >(rename, ApiNotificationType.Rename);

            await _notificationQuery.AddNotification(webSocketResponse);

            await _connectionsService.SendToAllAsync(webSocketResponse, CancellationToken.None);

            return(Json(currentStatus ? rename.Where(p => p.Status
                                                     != FileIndexItem.ExifStatus.NotFoundSourceMissing).ToList() : rename));
        }
Esempio n. 10
0
        internal async Task WorkItem(string subPath, IStorage subPathStorage,
                                     IStorage thumbnailStorage)
        {
            try
            {
                _logger.LogInformation($"[ThumbnailGenerationController] start {subPath}");
                var thumbnail = new Thumbnail(subPathStorage,
                                              thumbnailStorage, _logger);
                var thumbs = await thumbnail.CreateThumb(subPath);

                var getAllFilesAsync = await _query.GetAllFilesAsync(subPath);

                var result = new List <FileIndexItem>();
                foreach (var item in
                         getAllFilesAsync.Where(item => thumbs.FirstOrDefault(p => p.Item1 == item.FilePath).Item2))
                {
                    if (item.Tags.Contains("!delete!"))
                    {
                        continue;
                    }

                    item.SetLastEdited();
                    result.Add(item);
                }

                if (!result.Any())
                {
                    return;
                }

                var webSocketResponse =
                    new ApiNotificationResponseModel <List <FileIndexItem> >(result, ApiNotificationType.ThumbnailGeneration);
                await _connectionsService.SendToAllAsync(webSocketResponse, CancellationToken.None);

                _logger.LogInformation($"[ThumbnailGenerationController] done {subPath}");
            }
            catch (UnauthorizedAccessException e)
            {
                _logger.LogError($"[ThumbnailGenerationController] catch-ed exception {e.Message}", e);
            }
        }
Esempio n. 11
0
        public async Task <IActionResult> UploadToFolder()
        {
            var to = Request.Headers["to"].ToString();

            if (string.IsNullOrWhiteSpace(to))
            {
                return(BadRequest("missing 'to' header"));
            }

            var parentDirectory = GetParentDirectoryFromRequestHeader();

            if (parentDirectory == null)
            {
                return(NotFound(new ImportIndexItem {
                    Status = ImportStatus.ParentDirectoryNotFound
                }));
            }

            var tempImportPaths = await Request.StreamFile(_appSettings, _selectorStorage);

            var fileIndexResultsList = await _import.Preflight(tempImportPaths,
                                                               new ImportSettingsModel { IndexMode = false });

            for (var i = 0; i < fileIndexResultsList.Count; i++)
            {
                if (fileIndexResultsList[i].Status != ImportStatus.Ok)
                {
                    continue;
                }

                var tempFileStream = _iHostStorage.ReadStream(tempImportPaths[i]);
                var fileName       = Path.GetFileName(tempImportPaths[i]);

                // subPath is always unix style
                var subPath = PathHelper.AddSlash(parentDirectory) + fileName;
                if (parentDirectory == "/")
                {
                    subPath = parentDirectory + fileName;
                }

                // to get the output in the result right
                fileIndexResultsList[i].FileIndexItem.FileName        = fileName;
                fileIndexResultsList[i].FileIndexItem.ParentDirectory = parentDirectory;
                fileIndexResultsList[i].FilePath = subPath;
                // Do sync action before writing it down
                fileIndexResultsList[i].FileIndexItem = await SyncItem(fileIndexResultsList[i].FileIndexItem);

                var writeStatus =
                    await _iStorage.WriteStreamAsync(tempFileStream, subPath + ".tmp");

                await tempFileStream.DisposeAsync();

                // to avoid partly written stream to be read by an other application
                _iStorage.FileDelete(subPath);
                _iStorage.FileMove(subPath + ".tmp", subPath);
                _logger.LogInformation($"write {subPath} is {writeStatus}");

                // clear directory cache
                _query.RemoveCacheParentItem(subPath);

                var deleteStatus = _iHostStorage.FileDelete(tempImportPaths[i]);
                _logger.LogInformation($"[UploadController] delete {tempImportPaths[i]} is {deleteStatus}");

                var parentPath = Directory.GetParent(tempImportPaths[i])?.FullName;
                if (!string.IsNullOrEmpty(parentPath) && parentPath != _appSettings.TempFolder)
                {
                    _iHostStorage.FolderDelete(parentPath);
                }

                await _metaExifThumbnailService.AddMetaThumbnail(subPath,
                                                                 fileIndexResultsList[i].FileIndexItem.FileHash);
            }

            // send all uploads as list
            var socketResult = fileIndexResultsList
                               .Where(p => p.Status == ImportStatus.Ok)
                               .Select(item => item.FileIndexItem).ToList();

            var webSocketResponse = new ApiNotificationResponseModel <List <FileIndexItem> >(
                socketResult, ApiNotificationType.UploadFile);
            await _connectionsService.NotificationToAllAsync(webSocketResponse, CancellationToken.None);

            // Wrong input (extension is not allowed)
            if (fileIndexResultsList.All(p => p.Status == ImportStatus.FileError))
            {
                _logger.LogInformation($"Wrong input extension is not allowed" +
                                       $" {string.Join(",",fileIndexResultsList.Select(p => p.FilePath))}");
                Response.StatusCode = 415;
            }

            return(Json(fileIndexResultsList));
        }
Esempio n. 12
0
 internal async Task PushToSockets(List <FileIndexItem> updatedList)
 {
     var webSocketResponse =
         new ApiNotificationResponseModel <List <FileIndexItem> >(updatedList, ApiNotificationType.ManualBackgroundSync);
     await _connectionsService.SendToAllAsync(webSocketResponse, CancellationToken.None);
 }
        public async Task Invoke(HttpContext context)
        {
            if (ValidateOrigin(context))
            {
                if (context.WebSockets.IsWebSocketRequest)
                {
                    WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();

                    if (!context.User.Identity.IsAuthenticated)
                    {
                        // Status Code 1008 PolicyViolation
                        await webSocket.CloseOutputAsync(WebSocketCloseStatus.PolicyViolation,
                                                         "Please login first", CancellationToken.None);

                        return;
                    }

                    WebSocketConnection webSocketConnection = new WebSocketConnection(webSocket, _options.ReceivePayloadBufferSize);

                    async void OnWebSocketConnectionOnNewConnection(object sender, EventArgs message)
                    {
                        await Task.Delay(150);

                        try
                        {
                            var welcomeMessage = new ApiNotificationResponseModel <HeartbeatModel>(new HeartbeatModel(null))
                            {
                                Type = ApiNotificationType.Welcome,
                            };
                            await webSocketConnection.SendAsync(JsonSerializer.Serialize(welcomeMessage,
                                                                                         DefaultJsonSerializer.CamelCase), CancellationToken.None);
                        }
                        catch (WebSocketException)
                        {
                            // if the client is closing the socket the wrong way
                        }
                    }

                    webSocketConnection.NewConnection += OnWebSocketConnectionOnNewConnection;

                    _connectionsService.AddConnection(webSocketConnection);

                    await webSocketConnection.ReceiveMessagesUntilCloseAsync();

                    if (webSocketConnection.CloseStatus.HasValue)
                    {
                        await webSocket.CloseOutputAsync(webSocketConnection.CloseStatus.Value,
                                                         webSocketConnection.CloseStatusDescription, CancellationToken.None);
                    }

                    _connectionsService.RemoveConnection(webSocketConnection.Id);
                }
                else
                {
                    context.Response.StatusCode = StatusCodes.Status400BadRequest;
                }
            }
            else
            {
                context.Response.StatusCode = StatusCodes.Status403Forbidden;
            }
        }
 public Task NotificationToAllAsync <T>(ApiNotificationResponseModel <T> message,
                                        CancellationToken cancellationToken)
 {
     FakeSendToAllAsync.Add(new Tuple <string, DateTime>(JsonSerializer.Serialize(message), DateTime.UtcNow));
     return(Task.CompletedTask);
 }