Ejemplo n.º 1
0
        /// <summary>
        /// Applies date filtering to the list of media.
        /// </summary>
        private IReadOnlyList <Media> TryFilterMediaByDate(FolderContentsRequestVM request, IReadOnlyList <Media> source)
        {
            var dateFrom = TryParse(request.From);
            var dateTo   = TryParse(request.To);

            if (dateFrom == null && dateTo == null)
            {
                return(source);
            }

            return(source.Select(x => new
            {
                Date = FuzzyDate.TryParse(x.Date),
                Media = x
            })
                   .Where(x => x.Date != null)
                   .Where(x => (dateFrom == null || x.Date >= dateFrom) && (dateTo == null || x.Date <= dateTo))
                   .Select(x => x.Media)
                   .ToList());

            FuzzyDate?TryParse(string value)
            {
                var date = value?.TryParse <DateTime?>();

                return(date == null ? (FuzzyDate?)null : new FuzzyDate(date.Value));
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Returns the details for a media.
        /// </summary>
        public async Task <MediaVM> GetMediaAsync(string key)
        {
            var id    = PageHelper.GetMediaId(key);
            var media = await _db.Media
                        .Include(x => x.Tags)
                        .ThenInclude(x => x.Object)
                        .Where(x => x.IsDeleted == false)
                        .FirstOrDefaultAsync(x => x.Id == id);

            if (media == null)
            {
                throw new KeyNotFoundException();
            }

            var descr = await _markdown.CompileAsync(media.Description);

            return(new MediaVM
            {
                Type = media.Type,
                IsProcessed = media.IsProcessed,
                Title = media.Title,
                Description = descr,
                Date = FuzzyDate.TryParse(media.Date),
                Tags = GetMediaTagsVMs(media.Tags).ToList(),
                Event = GetPageTitle(media.Tags.FirstOrDefault(x => x.Type == MediaTagType.Event)),
                Location = GetPageTitle(media.Tags.FirstOrDefault(x => x.Type == MediaTagType.Location)),
                OriginalPath = media.FilePath,
                PreviewPath = GetSizedMediaPath(media.FilePath, MediaSize.Large)
            });
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Performs additional checks on the registration request.
        /// </summary>
        private async Task ValidateRegisterRequestAsync(RegisterUserVM vm, bool usePasswordAuth)
        {
            var val = new Validator();

            if (FuzzyDate.TryParse(vm.Birthday) == null)
            {
                val.Add(nameof(vm.Birthday), "Дата рождения указана неверно.");
            }

            var emailExists = await _db.Users.AnyAsync(x => x.Email == vm.Email);

            if (emailExists)
            {
                val.Add(nameof(vm.Email), "Адрес электронной почты уже зарегистрирован.");
            }

            if (usePasswordAuth)
            {
                if (vm.Password == null || vm.Password.Length < 6)
                {
                    val.Add(nameof(vm.Password), "Пароль должен содержать как минимум 6 символов.");
                }

                if (vm.Password != vm.PasswordCopy)
                {
                    val.Add(nameof(vm.PasswordCopy), "Пароли не совпадают.");
                }
            }

            val.ThrowIfInvalid();
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Uploads a new media file.
        /// </summary>
        public async Task <MediaUploadResultVM> UploadAsync(MediaUploadRequestVM vm, IFormFile file, ClaimsPrincipal principal)
        {
            var id  = Guid.NewGuid();
            var key = PageHelper.GetMediaKey(id);

            var handler = _mediaHandlers.FirstOrDefault(x => x.SupportedMimeTypes.Contains(file.ContentType));

            if (handler == null)
            {
                throw new UploadException("Неизвестный тип файла!");
            }

            var userId = _userMgr.GetUserId(principal);
            var user   = await _db.Users.GetAsync(x => x.Id == userId, "Пользователь не найден");

            var paths = await SaveUploadAsync(file, key, handler);

            var tags = await GetTagsForUploadedMedia(vm);

            var meta = await handler.ExtractMetadataAsync(paths.LocalPath, file.ContentType);

            var media = new Media
            {
                Id          = id,
                Key         = key,
                Type        = handler.MediaType,
                MimeType    = file.ContentType,
                Title       = vm.Title,
                FilePath    = paths.UrlPath,
                UploadDate  = DateTimeOffset.Now,
                Uploader    = user,
                IsProcessed = handler.IsImmediate,
                Date        = FuzzyDate.TryParse(vm.Date) != null
                    ? vm.Date
                    : meta?.Date?.Date.ToString("yyyy.MM.dd", CultureInfo.InvariantCulture),
                Tags = tags
            };

            _db.Media.Add(media);

            if (!handler.IsImmediate)
            {
                _db.MediaJobs.Add(new MediaEncodingJob
                {
                    Id      = Guid.NewGuid(),
                    MediaId = media.Id
                });
            }

            var changeset = await GetChangesetAsync(null, _mapper.Map <MediaEditorVM>(media), id, principal, null);

            _db.Changes.Add(changeset);

            return(_mapper.Map <MediaUploadResultVM>(media));
        }
Ejemplo n.º 5
0
 public void Configure(IProfileExpression profile)
 {
     profile.CreateMap <Data.Models.Media, MediaThumbnailExtendedVM>()
     .MapMember(x => x.Id, x => x.Id)
     .MapMember(x => x.Key, x => x.Key)
     .MapMember(x => x.Type, x => x.Type)
     .MapMember(x => x.Date, x => FuzzyDate.TryParse(x.Date))
     .MapMember(x => x.UploadDate, x => x.UploadDate)
     .MapMember(x => x.Title, x => x.Title)
     .MapMember(x => x.MediaTagsCount, x => x.Tags.Count(y => y.Type == MediaTagType.DepictedEntity))
     .MapMember(x => x.ThumbnailUrl, x => MediaPresenterService.GetSizedMediaPath(x.FilePath, MediaSize.Small));
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Performs additional checks on the registration request.
        /// </summary>
        private async Task ValidateRegisterRequestAsync(RegisterUserVM vm)
        {
            var val = new Validator();

            if (FuzzyDate.TryParse(vm.Birthday) == null)
                val.Add(nameof(vm.Birthday), "Дата рождения указана неверно.");

            var emailExists = await _db.Users.AnyAsync(x => x.Email == vm.Email);
            if (emailExists)
                val.Add(nameof(vm.Email), "Адрес электронной почты уже зарегистрирован.");

            val.ThrowIfInvalid();
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Renders the property values.
        /// </summary>
        public async Task <IReadOnlyList <ChangePropertyValue> > RenderValuesAsync(string json)
        {
            var result = new List <ChangePropertyValue>();
            var data   = JsonConvert.DeserializeObject <RelationEditorVM>(StringHelper.Coalesce(json, "{}"));

            if (data.SourceIds == null)
            {
                data.SourceIds = Array.Empty <Guid>();
            }

            var pageIds = data.SourceIds
                          .Concat(new[] { data.DestinationId ?? Guid.Empty, data.EventId ?? Guid.Empty })
                          .ToList();

            var namesLookup = await _db.Pages
                              .Where(x => pageIds.Contains(x.Id))
                              .ToDictionaryAsync(x => x.Id, x => x.Title);

            Add(nameof(RelationEditorVM.DestinationId), "Основная страница", namesLookup.TryGetValue(data.DestinationId ?? Guid.Empty));
            Add(nameof(RelationEditorVM.Type), "Тип связи", string.IsNullOrEmpty(json) ? null : data.Type.GetEnumDescription());

            if (data.SourceIds.Length == 0)
            {
                Add(nameof(RelationEditorVM.SourceIds), "Связанная страница", null);
            }
            else if (data.SourceIds.Length == 1)
            {
                var name = namesLookup.TryGetValue(data.SourceIds[0]);
                Add(nameof(RelationEditorVM.SourceIds), "Связанная страница", name);
            }
            else
            {
                var pageNames = data.SourceIds
                                .Select(x => namesLookup.TryGetValue(x))
                                .Where(x => !string.IsNullOrEmpty(x));

                Add(nameof(RelationEditorVM.SourceIds), "Связанные страницы", ViewHelper.RenderBulletList(_html, pageNames));
            }

            Add(nameof(RelationEditorVM.EventId), "Событие", namesLookup.TryGetValue(data.EventId ?? Guid.Empty));
            Add(nameof(RelationEditorVM.DurationStart), "Начало", FuzzyDate.TryParse(data.DurationStart)?.ReadableDate);
            Add(nameof(RelationEditorVM.DurationEnd), "Конец", FuzzyDate.TryParse(data.DurationEnd)?.ReadableDate);

            return(result);

            void Add(string prop, string name, string value)
            {
                result.Add(new ChangePropertyValue(prop, name, value));
            }
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Returns the last N uploaded images.
 /// </summary>
 public async Task <IReadOnlyList <MediaThumbnailVM> > GetLastUploadedMediaAsync(int count)
 {
     return(await _db.Media
            .Where(x => !x.IsDeleted)
            .OrderByDescending(x => x.UploadDate)
            .Take(count)
            .Select(x => new MediaThumbnailVM
     {
         Key = x.Key,
         Type = x.Type,
         ThumbnailUrl = GetSizedMediaPath(x.FilePath, MediaSize.Small),
         Date = FuzzyDate.TryParse(x.Date),
     })
            .ToListAsync());
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Returns the photo model.
        /// </summary>
        public static MediaThumbnailVM GetMediaThumbnail(Media media, MediaSize size = MediaSize.Small)
        {
            if (media == null)
            {
                return(null);
            }

            return(new MediaThumbnailVM
            {
                Type = media.Type,
                Key = media.Key,
                ThumbnailUrl = GetSizedMediaPath(media.FilePath, size),
                Date = FuzzyDate.TryParse(media.Date)
            });
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Returns the media details.
        /// </summary>
        public async Task <MediaVM> GetMediaAsync(string key, UserContext ctx)
        {
            var errorKey = $"Media ({key})";

            var media = await _db.Media
                        .AsNoTracking()
                        .Include(x => x.Tags)
                        .ThenInclude(x => x.Tag)
                        .Include(x => x.Folder)
                        .GetAsync(x => x.Key == key, errorKey);

            if (ctx.Link != null)
            {
                // subfolders disallowed: only media immediately inside current folder are available
                if (ctx.Link.Scope == SearchScope.CurrentFolder && media.FolderKey != ctx.Link.Folder.Key)
                {
                    throw new NotFoundException(errorKey);
                }

                // inside subfolder
                if (!media.Folder.Path.StartsWith(ctx.Link.Folder.Path))
                {
                    throw new NotFoundException(errorKey);
                }

                // must have tags
                if (!string.IsNullOrEmpty(ctx.Link.Tags))
                {
                    var tagIds = ctx.Link.Tags.TryParseList <int>(",");
                    if (!media.Tags.Any(x => tagIds.Contains(x.TagId)))
                    {
                        throw new NotFoundException(errorKey);
                    }
                }

                var mediaDate = FuzzyDate.TryParse(media.Date);
                var dateFrom  = FuzzyDate.TryParse(ctx.Link.DateFrom);
                var dateTo    = FuzzyDate.TryParse(ctx.Link.DateTo);

                if ((dateFrom != null && !(mediaDate >= dateFrom)) || (dateTo != null && !(mediaDate <= dateTo)))
                {
                    throw new NotFoundException(errorKey);
                }
            }

            return(_mapper.Map <MediaVM>(media));
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Checks if the update request contains valid data.
        /// </summary>
        private async Task ValidateRequestAsync(MediaEditorVM vm)
        {
            var val = new Validator();

            if (!string.IsNullOrEmpty(vm.Date) && FuzzyDate.TryParse(vm.Date) == null)
            {
                val.Add(nameof(vm.Date), "Введите корректную дату.");
            }

            var depictedIds = JsonConvert.DeserializeObject <IEnumerable <MediaTagVM> >(vm.DepictedEntities ?? "[]")
                              .Select(x => x.PageId)
                              .ToList();

            var locId  = vm.Location.TryParse <Guid?>();
            var evtId  = vm.Event.TryParse <Guid?>();
            var tagIds = depictedIds.Concat(new[] { locId, evtId })
                         .Where(x => x != null)
                         .Select(x => x.Value)
                         .ToList();

            if (tagIds.Any())
            {
                var existing = await _db.Pages
                               .Where(x => tagIds.Contains(x.Id) && !x.IsDeleted)
                               .ToHashSetAsync(x => x.Id);

                if (depictedIds.Any(x => x != null && !existing.Contains(x.Value)))
                {
                    val.Add(nameof(vm.DepictedEntities), "Страница не существует!");
                }

                if (locId != null && !existing.Contains(locId.Value))
                {
                    val.Add(nameof(vm.Location), "Страница не существует!");
                }

                if (evtId != null && !existing.Contains(evtId.Value))
                {
                    val.Add(nameof(vm.Event), "Страница не существует!");
                }
            }

            val.ThrowIfInvalid();
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Checks if the create/update request contains valid data.
        /// </summary>
        private async Task ValidateRequestAsync(RelationEditorVM vm, bool isNew)
        {
            var val = new Validator();

            vm.SourceIds = vm.SourceIds ?? new Guid[0];

            var pageIds = vm.SourceIds
                          .Concat(new [] { vm.DestinationId ?? Guid.Empty, vm.EventId ?? Guid.Empty })
                          .ToList();

            var pages = await _db.Pages
                        .Where(x => pageIds.Contains(x.Id))
                        .ToDictionaryAsync(x => x.Id, x => x.Type);

            var sourceTypes = vm.SourceIds.Select(x => pages.TryGetNullableValue(x)).ToList();
            var destType    = pages.TryGetNullableValue(vm.DestinationId ?? Guid.Empty);
            var eventType   = pages.TryGetNullableValue(vm.EventId ?? Guid.Empty);

            if (vm.SourceIds == null || vm.SourceIds.Length == 0)
            {
                val.Add(nameof(vm.SourceIds), "Выберите страницу");
            }
            else if (isNew == false && vm.SourceIds.Length > 1)
            {
                val.Add(nameof(vm.SourceIds), "При редактировании может быть указана только одна страница");
            }
            else if (sourceTypes.Any(x => x == null))
            {
                val.Add(nameof(vm.SourceIds), "Страница не найдена");
            }

            if (vm.DestinationId == null)
            {
                val.Add(nameof(vm.DestinationId), "Выберите страницу");
            }
            else if (destType == null)
            {
                val.Add(nameof(vm.DestinationId), "Страница не найдена");
            }

            if (destType != null && sourceTypes.Any(x => x != null && !RelationHelper.IsRelationAllowed(x.Value, destType.Value, vm.Type)))
            {
                val.Add(nameof(vm.Type), "Тип связи недопустимм для данных страниц");
            }

            if (vm.EventId != null)
            {
                if (eventType == null)
                {
                    val.Add(nameof(vm.EventId), "Страница не найдена");
                }
                else if (eventType != PageType.Event)
                {
                    val.Add(nameof(vm.EventId), "Требуется страница события");
                }
                else if (!RelationHelper.IsRelationEventReferenceAllowed(vm.Type))
                {
                    val.Add(nameof(vm.EventId), "Событие нельзя привязать к данному типу связи");
                }
            }

            if (!string.IsNullOrEmpty(vm.DurationStart) || !string.IsNullOrEmpty(vm.DurationEnd))
            {
                if (!RelationHelper.IsRelationDurationAllowed(vm.Type))
                {
                    val.Add(nameof(vm.DurationStart), "Дату нельзя указать для данного типа связи");
                }
                else
                {
                    var from = FuzzyDate.TryParse(vm.DurationStart);
                    var to   = FuzzyDate.TryParse(vm.DurationEnd);

                    if (from > to)
                    {
                        val.Add(nameof(vm.DurationStart), "Дата начала не может быть больше даты конца");
                    }
                    else if (FuzzyRange.TryParse(FuzzyRange.TryCombine(vm.DurationStart, vm.DurationEnd)) == null)
                    {
                        val.Add(nameof(vm.DurationStart), "Введите дату в корректном формате");
                    }
                }
            }

            var existingRelation = await _db.Relations
                                   .AnyAsync(x => vm.SourceIds.Contains(x.SourceId) &&
                                             x.DestinationId == vm.DestinationId &&
                                             x.Type == vm.Type &&
                                             x.Id != vm.Id);

            if (existingRelation)
            {
                val.Add(nameof(vm.DestinationId), "Такая связь уже существует!");
            }

            val.ThrowIfInvalid();
        }