Beispiel #1
0
        private async Task PurgeBackups(SourceFolder sf)
        {
            var numberToKeep = 5;

            if (sf.Backups.Count() > numberToKeep)
            {
                var toDelete = sf.Backups.OrderByDescending(x => x.ScheduledOn).Skip(numberToKeep).ToArray();
                foreach (var b in toDelete)
                {
                    try
                    {
                        if (File.Exists(b.FullPath))
                        {
                            db.Backups.Remove(b);
                            await db.SaveChangesAsync();

                            File.Delete(b.FullPath);
                            log.LogInformation($"Backup {b.FullPath} purged");
                        }
                    }
                    catch (Exception xe)
                    {
                        log.LogError(xe, $"File purge failed: {b.FullPath}");
                    }
                }
            }
        }
Beispiel #2
0
        private async Task AddFolderSource(DateTimeOffset configuredOn, FolderSource fs)
        {
            var folder = fs.Folder.ToLower();
            var sf     = await db.SourceFolders.SingleOrDefaultAsync(x => x.FullPath == folder);

            if (sf != null && sf.DisplayName != fs.DisplayName)
            {
                log.LogError($"Source folder {folder} already exists in the database: display name {sf.DisplayName}");
            }
            else
            {
                sf = await db.SourceFolders.SingleOrDefaultAsync(x => string.Compare(x.DisplayName, fs.DisplayName, true) == 0);

                if (sf == null)
                {
                    sf = new SourceFolder
                    {
                        BackupEnabled = false,
                        DisplayName   = fs.DisplayName,
                        //Path = String.Empty,
                        FullPath      = folder,
                        ScheduledTime = 3,
                        Type          = fs.Type
                    };
                    await db.SourceFolders.AddAsync(sf);
                }
                else
                {
                    sf.FullPath = fs.Folder.ToLower();
                    sf.Type     = fs.Type;
                }
                sf.ConfiguredOn = configuredOn;
                await db.SaveChangesAsync();
            }
        }
Beispiel #3
0
        private async Task <ITaskState> DoTask(ITaskState taskState, ScheduleMode mode, CancellationToken cancellationToken)
        {
            var configuredOn = DateTimeOffset.Now;

            using (db = dbf.GetWebDbContext <ServiceDb>())
            {
                await db.Database.EnsureCreatedAsync();

                //var sm = new ServerManager();
                //foreach (var site in sm.Sites)
                //{
                //    await AddSiteFolder(configuredOn, site);
                //}
                foreach (var fs in options.FolderSources)
                {
                    await AddFolderSource(configuredOn, fs);
                }
                var staleList = await db.SourceFolders
                                .Include(x => x.Backups)
                                .Where(x => x.ConfiguredOn < configuredOn).ToArrayAsync();

                foreach (var sf in staleList)
                {
                    var backups = sf.Backups.ToArray();
                    db.Backups.RemoveRange(backups);
                    db.SourceFolders.Remove(sf);
                    log.LogInformation($"{sf.DisplayName} {sf.FullPath} (with {backups.Count()} backups) removed");
                }
                await db.SaveChangesAsync();

                var count = db.SourceFolders.Count();
                log.LogInformation($"found {count} source folders in database");
                return(null);// Task.FromResult<ITaskState>(null);
            }
        }
        public async Task <StandardResponse> UpdateAnswerMetadata(ClaimsPrincipal identity, AnswerMetadataUpdateViewModel model,
                                                                  ModelStateDictionary modelState)
        {
            if (!modelState.IsValid)
            {
                return(modelState.StandardError());
            }

            using (var db = new ServiceDb())
            {
                using (var user = await _userService.Become(db, identity, null))
                {
                    var metadata = await _answerService.UpdateAnswerMetadata(db, user, new UpdateAnswerMeta()
                    {
                        AnswerId   = model.AnswerId,
                        RowVersion = model.RowVersion,
                        Votes      = model.Votes,
                    });

                    await db.SaveChangesAsync();

                    return(StandardResponse.For(AnswerMetaViewModel.From(metadata)));
                }
            }
        }
        public async Task <StandardResponse> AskQuestion(ClaimsPrincipal identity, QuestionAddViewModel model, ModelStateDictionary modelState)
        {
            if (!modelState.IsValid)
            {
                return(modelState.StandardError());
            }

            using (var db = new ServiceDb())
            {
                using (var user = await _userService.Become(db, identity, null))
                {
                    var question = await _questionService.CreateQuestion(db, user, new CreateNewQuestion()
                    {
                        Title = model.Title,
                        Body  = model.Body, Tags = model.Tags,
                        Topic = model.Topic ?? Topic.DefaultTopic
                    });

                    await db.SaveChangesAsync();

                    return(StandardResponse.For(new
                    {
                        question.QuestionId
                    }));
                }
            }
        }
        public async Task <StandardResponse> UpdateQuestion(ClaimsPrincipal identity, QuestionUpdateViewModel model, ModelStateDictionary modelState)
        {
            if (!modelState.IsValid)
            {
                return(modelState.StandardError());
            }

            using (var db = new ServiceDb())
            {
                using (var user = await _userService.Become(db, identity))
                {
                    await _questionService.UpdateQuestion(db, user, new UpdateQuestion()
                    {
                        QuestionId = model.QuestionId,
                        RowVersion = model.RowVersion,
                        Body       = model.Body,
                        Tags       = model.Tags ?? new string[] { },
                        Title      = model.Title,
                        Topic      = model.Topic
                    });

                    await db.SaveChangesAsync();

                    var question = await _questionService.GetQuestion(db, user, model.QuestionId);

                    return(StandardResponse.For(QuestionViewModel.From(question)));
                }
            }
        }
Beispiel #7
0
        public async Task <StandardResponse> UpdateTopic(ClaimsPrincipal identity, TopicUpdateViewModel model, ModelStateDictionary modelState)
        {
            if (!modelState.IsValid)
            {
                return(modelState.StandardError());
            }

            using (var db = new ServiceDb())
            {
                using (var user = await _userService.Become(db, identity))
                {
                    var result = await _topicService.UpdateTopic(db, user, new UpdateTopic()
                    {
                        TopicId     = model.TopicId,
                        Description = model.Description,
                        Icon        = PangulStringEncoding.GetBytesFromDataUrl(model.Icon),
                        IconType    = PangulStringEncoding.GetTypeFromDataUrl(model.Icon),
                        RowVersion  = model.RowVersion
                    });

                    await db.SaveChangesAsync();

                    return(StandardResponse.For(new { result.TopicId }));
                }
            }
        }
Beispiel #8
0
        public async Task <IActionResult> SetSourceBackup(int id, bool enabled)
        {
            var sf = await serviceDb.SourceFolders.FindAsync(id);

            sf.BackupEnabled = enabled;
            await serviceDb.SaveChangesAsync();

            return(SuccessDataResult(null));
        }
Beispiel #9
0
        private async Task RequireUserRecordForUser(string username)
        {
            using (var db = new ServiceDb())
            {
                try
                {
                    await _userService.Become(db, username, null);
                }
                catch (Exception)
                {
                    await _userService.Create(db, username);

                    await db.SaveChangesAsync();
                }
            }
        }
Beispiel #10
0
        public async Task <StandardResponse> DeleteTopic(ClaimsPrincipal identity, TopicDeleteViewModel model, ModelStateDictionary modelState)
        {
            if (!modelState.IsValid)
            {
                return(modelState.StandardError());
            }

            using (var db = new ServiceDb())
            {
                using (var user = await _userService.Become(db, identity))
                {
                    await _topicService.DeleteTopic(db, user, model.TopicId, model.RowVersion);

                    await db.SaveChangesAsync();

                    return(StandardResponse.ForSuccess());
                }
            }
        }
        public async Task <StandardResponse> AddAnswerToQuestion(ClaimsPrincipal identity, AddAnswerViewModel model, ModelStateDictionary modelState)
        {
            if (!modelState.IsValid)
            {
                return(modelState.StandardError());
            }

            using (var db = new ServiceDb())
            {
                using (var user = await _userService.Become(db, identity, null))
                {
                    var answer = await _answerService.CreateAnswer(db, user, model.QuestionId, model.Body);

                    await db.SaveChangesAsync();

                    return(StandardResponse.For(new
                    {
                        answer.AnswerId
                    }));
                }
            }
        }
        public async Task <StandardResponse> UpdateAnswer(ClaimsPrincipal identity, UpdateAnswerViewModel model, ModelStateDictionary modelState)
        {
            if (!modelState.IsValid)
            {
                return(modelState.StandardError());
            }

            using (var db = new ServiceDb())
            {
                using (var user = await _userService.Become(db, identity, null))
                {
                    await _answerService.UpdateExistingAnswer(db, user, new UpdateAnswer()
                    {
                        AnswerId   = model.AnswerId,
                        NewBody    = model.Body,
                        RowVersion = model.RowVersion
                    });

                    await db.SaveChangesAsync();

                    return(StandardResponse.ForSuccess());
                }
            }
        }
Beispiel #13
0
        private async Task <ITaskState> DoTask(ITaskState taskState, ScheduleMode mode, CancellationToken cancellationToken)
        {
            if (options.IsBackupDestinationAvailable())
            {
                using (db = dbf.GetWebDbContext <ServiceDb>())
                {
                    var sf = await db.SourceFolders
                             .Include(x => x.Backups)
                             .SingleAsync(x => x.Id == sourceFolderId);

                    //log.LogInformation($"Backup task for source {sf.DisplayName}");
                    var destinationFolder = Path.Combine(options.GetBackupDestination(), sf.DisplayName);
                    if (!Directory.Exists(destinationFolder))
                    {
                        Directory.CreateDirectory(destinationFolder);
                        log.LogInformation($"{destinationFolder} created");
                    }
                    var isPending = await IsBackupPending(sf);

                    if (isPending.result)
                    {
                        //log.LogInformation($"Backup of {sf.GetFullname()} to {destinationFolder} is required");
                        var backup         = isPending.backup;
                        var namePart       = sf.DisplayName;
                        var datePart       = $"{(backup.ScheduledOn.ToString("yyyy.MM.dd"))}";
                        var backupFileName = $"{namePart}.{datePart}.zip";
                        backup.FullPath = Path.Combine(destinationFolder, backupFileName);
                        backup.State    = BackupState.Started;
                        var now = DateTimeOffset.Now;
                        var todaysScheduledTime = new DateTimeOffset(now.Year, now.Month, now.Day, sf.ScheduledTime, 0, 0, now.Offset);
                        log.LogInformation($"Backup of {sf.DisplayName} to {destinationFolder} started ({(todaysScheduledTime.ToString("ddMMMyyyy HH:mm:ss"))})");
                        if (sf.Type == SourceType.Website)
                        {
                            TakeSiteOffline(sf);
                        }
                        await db.SaveChangesAsync();

                        try
                        {
                            if (File.Exists(backup.FullPath))
                            {
                                File.Delete(backup.FullPath);
                                log.LogWarning($"{backup.FullPath} deleted");
                            }
                            zip(sf.FullPath, backup.FullPath);
                            backup.State      = BackupState.Finished;
                            backup.BackedUpOn = DateTimeOffset.Now;
                            await db.SaveChangesAsync();

                            log.LogInformation($"Backup of {sf.DisplayName} to {backup.FullPath} completed");
                        }
                        catch (Exception xe)
                        {
                            log.LogError(xe, $"backup failed {sf.DisplayName} to {backup.FullPath}");
                            backup.State      = BackupState.Failed;
                            backup.BackedUpOn = DateTimeOffset.Now;
                            await db.SaveChangesAsync();

                            //throw;
                        }
                        finally
                        {
                            if (sf.Type == SourceType.Website)
                            {
                                BringSiteOnline(sf);
                            }
                        }
                        await PurgeBackups(sf);
                    }
                    else
                    {
                        log.LogInformation($"Backup of {sf.DisplayName} is not pending");
                    }
                }
            }
            else
            {
                foreach (var d in DriveInfo.GetDrives())
                {
                    log.LogInformation($"Found drive {d.Name}, label {d.VolumeLabel}, ready = {d.IsReady}");
                }
                log.LogWarning($"Backup destination not available - no disk with volume label {options.BackupDriveLabel} found");
            }
            return(null);
        }