示例#1
0
        public async Task <Paged <StoryDto> > HandleAsync(BrowseStories query)
        {
            var now       = (query.Now.HasValue ? query.Now.Value : _clock.Current()).ToUnixTimeMilliseconds();
            var documents = _database.GetCollection <StoryDocument>($"{Schema}.stories")
                            .AsQueryable()
                            .Where(x => x.From <= now && x.To >= now);

            var input = query.Query;

            if (!string.IsNullOrWhiteSpace(input))
            {
                documents = documents.Where(x =>
                                            x.Title.Contains(input) || x.Author.Name.Contains(input) || x.Tags.Contains(input));
            }

            var result = await documents.OrderByDescending(x => x.CreatedAt).PaginateAsync(query);

            var storyIds = result.Items.Select(x => x.Id);

            var rates = await _database.GetCollection <StoryRatingDocument>($"{Schema}.ratings")
                        .AsQueryable()
                        .Where(x => storyIds.Contains(x.StoryId))
                        .ToListAsync();

            var pagedResult = Paged <StoryDto> .From(result, result.Items.Select(x => x.ToDto(rates)));

            return(new Paged <StoryDto>
            {
                CurrentPage = pagedResult.CurrentPage,
                TotalPages = pagedResult.TotalPages,
                ResultsPerPage = pagedResult.ResultsPerPage,
                TotalResults = pagedResult.TotalResults,
                Items = pagedResult.Items
            });
        }
示例#2
0
        public async Task <StoryDetailsDto> HandleAsync(GetStory query)
        {
            var story = await _database.GetCollection <StoryDocument>($"{Schema}.stories")
                        .AsQueryable()
                        .SingleOrDefaultAsync(x => x.Id == query.StoryId);

            if (story is null)
            {
                return(null);
            }

            var now = _clock.Current().ToUnixTimeMilliseconds();

            if (story.From > now || story.To < now)
            {
                return(null);
            }

            var rates = await _database.GetCollection <StoryRatingDocument>($"{Schema}.ratings")
                        .AsQueryable()
                        .Where(x => x.StoryId == query.StoryId)
                        .ToListAsync();

            return(story.ToDetailsDto(rates, query.UserId));
        }
示例#3
0
        public async Task HandleAsync(SendStory command)
        {
            var user = await _userRepository.GetAsync(command.UserId);

            if (user is null)
            {
                throw new UserNotFoundException(command.UserId);
            }

            if (!_storyAuthorPolicy.CanCreate(user))
            {
                throw new CannotCreateStoryException(user.Id);
            }

            var author     = Author.Create(user);
            var text       = _storyTextFactory.Create(command.Text);
            var now        = _clock.Current();
            var visibility = command.VisibleFrom.HasValue && command.VisibleTo.HasValue
                ? new Visibility(command.VisibleFrom.Value, command.VisibleTo.Value, command.Highlighted)
                : Visibility.Default(now);
            var storyId = command.StoryId <= 0 ? _idGenerator.Generate() : command.StoryId;
            var story   = Story.Create(storyId, author, command.Title, text, command.Tags, now, visibility);
            await _storyRepository.AddAsync(story);

            var domainEvents = story.Events.ToArray();
            await _domainEventDispatcher.DispatchAsync(domainEvents);

            var integrationEvents = _eventMapper.Map(domainEvents).ToArray();

            _storyRequestStorage.SetStoryId(command.Id, story.Id);
            await _messageBroker.PublishAsync(integrationEvents);
        }
        public async Task <Paged <Story> > GetTimelineAsync(Guid userId, DateTime?from = null, DateTime?to = null)
        {
            var now      = _clock.Current();
            var minScore = GetScore(from ?? now.AddDays(-7));
            var maxScore = GetScore(to ?? now);
            var storyIds = await _database.SortedSetRangeByScoreAsync(GetTimelineKey(userId), minScore, maxScore);

            var storyKeys    = storyIds.Select(x => (RedisKey)GetStoryKey((long)x)).ToArray();
            var storyEntries = await _database.StringGetAsync(storyKeys);

            var stories = new List <Story>();

            foreach (var entry in storyEntries)
            {
                if (!entry.HasValue)
                {
                    continue;
                }

                var story = JsonSerializer.Deserialize <Story>(entry);
                if (story.Visibility.From <= now && story.Visibility.To >= now)
                {
                    stories.Add(story);
                }
            }

            return(new Paged <Story>
            {
                Items = stories,
                CurrentPage = 1,
                TotalPages = 1,
                TotalResults = stories.Count,
                ResultsPerPage = stories.Count
            });
        }
        public JsonWebToken CreateToken(string userId, string role = null, string audience = null,
                                        IDictionary <string, IEnumerable <string> > claims = null)
        {
            if (string.IsNullOrWhiteSpace(userId))
            {
                throw new ArgumentException("User ID claim (subject) cannot be empty.", nameof(userId));
            }

            var now       = _clock.Current();
            var jwtClaims = new List <Claim>
            {
                new Claim(JwtRegisteredClaimNames.Sub, userId),
                new Claim(JwtRegisteredClaimNames.UniqueName, userId),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Iat, now.ToUnixTimeMilliseconds().ToString())
            };

            if (!string.IsNullOrWhiteSpace(role))
            {
                jwtClaims.Add(new Claim(ClaimTypes.Role, role));
            }

            if (!string.IsNullOrWhiteSpace(audience))
            {
                jwtClaims.Add(new Claim(JwtRegisteredClaimNames.Aud, audience));
            }

            if (claims?.Any() is true)
            {
                var customClaims = new List <Claim>();
                foreach (var(claim, values) in claims)
                {
                    customClaims.AddRange(values.Select(value => new Claim(claim, value)));
                }

                jwtClaims.AddRange(customClaims);
            }

            var expires = now.AddMilliseconds(_options.Expiry.TotalMilliseconds);
            var jwt     = new JwtSecurityToken(
                _issuer,
                claims: jwtClaims,
                notBefore: now,
                expires: expires,
                signingCredentials: _signingCredentials
                );

            var token = new JwtSecurityTokenHandler().WriteToken(jwt);

            return(new JsonWebToken
            {
                AccessToken = token,
                RefreshToken = string.Empty,
                Expires = expires.ToUnixTimeMilliseconds(),
                Id = userId,
                Role = role ?? string.Empty,
                Claims = claims ?? EmptyClaims
            });
        }
        private async Task <string> CreateRefreshTokenAsync(Guid userId)
        {
            var token        = _rng.Generate(30, true);
            var refreshToken = new RefreshToken(new AggregateId(), userId, token, _clock.Current());
            await _refreshTokenRepository.AddAsync(refreshToken);

            return(token);
        }
示例#7
0
        public async Task HandleAsync(CreateAd command)
        {
            var ad = new Ad(command.AdId, command.UserId, command.Header, command.Content, command.Tags,
                            AdState.New, command.From, command.To, _clock.Current());
            await _adRepository.AddAsync(ad);

            await _messageBroker.PublishAsync(new AdCreated(command.AdId));
        }
        public async Task HandleAsync(IMessage message, Func <Task> handler, string module)
        {
            if (!Enabled)
            {
                _logger.LogWarning("Inbox is disabled, incoming messages won't be processed.");
                return;
            }

            if (message.Id == Guid.Empty)
            {
                // A synchronous request
                await handler();

                return;
            }

            var collection = _database.GetCollection <InboxMessage>($"{module}-module.{_collectionName}");

            _logger.LogTrace($"Received a message with ID: '{message.Id}' to be processed.");
            if (await collection.AsQueryable().AnyAsync(x => x.Id == message.Id))
            {
                _logger.LogWarning($"Message with ID: '{message.Id}' was already processed.");
                return;
            }

            IClientSessionHandle session = null;

            if (_transactionsEnabled)
            {
                session = await _sessionFactory.CreateAsync();

                session.StartTransaction();
            }

            try
            {
                _logger.LogTrace($"Handling a message with ID: '{message.Id}'...");
                await handler();

                await collection.InsertOneAsync(new InboxMessage
                {
                    Id            = message.Id,
                    CorrelationId = message.CorrelationId,
                    Name          = message.GetType().Name.Underscore(),
                    Module        = message.GetModuleName(),
                    Timestamp     = _clock.Current().ToUnixTimeMilliseconds()
                });

                if (session is {})
                {
                    await session.CommitTransactionAsync();
                }

                _logger.LogTrace($"Handled a message with ID: '{message.Id}'.");
            }
示例#9
0
        public async Task HandleAsync(PublishAd command)
        {
            var ad = await _adRepository.GetAsync(command.AdId);

            if (ad is null)
            {
                throw new AdNotFoundException(command.AdId);
            }

            ad.Publish(_clock.Current());
            var storyId = await _storyApiClient.SendStoryAsync(new SendStory(default, ad.UserId,
        public async Task HandleAsync(RevokeRefreshToken command)
        {
            var token = await _refreshTokenRepository.GetAsync(command.RefreshToken);

            if (token is null)
            {
                throw new InvalidRefreshTokenException();
            }

            token.Revoke(_clock.Current());
            await _refreshTokenRepository.UpdateAsync(token);
        }
        public async Task HandleAsync(ApproveAd command)
        {
            var ad = await _adRepository.GetAsync(command.AdId);

            if (ad is null)
            {
                throw new AdNotFoundException(command.AdId);
            }

            ad.Approve(_clock.Current());
            await _adRepository.UpdateAsync(ad);

            await _messageBroker.PublishAsync(new AdApproved(ad.Id));
        }
示例#12
0
        public async Task HandleAsync(PayAd command)
        {
            var ad = await _adRepository.GetAsync(command.AdId);

            if (ad is null)
            {
                throw new AdNotFoundException(command.AdId);
            }

            ad.Pay(_clock.Current());
            var fundsCharged = await _usersApiClient.ChargeFundsAsync(ad.UserId, ad.Amount);

            if (!fundsCharged)
            {
                throw new CannotPayAdException(ad.Id);
            }

            await _adRepository.UpdateAsync(ad);

            await _messageBroker.PublishAsync(new AdPaid(ad.Id));
        }
示例#13
0
 public async Task HandleAsync(UserCreated @event)
 {
     var user = new User(@event.UserId, @event.Name, _clock.Current());
     await _userRepository.AddAsync(user);
 }