public async Task <User> LoginAsync(User user)
        {
            var db = _dbFactory.CreateDbContext();

            // If it is feedreader user already (has id property), query user in db.
            if (!string.IsNullOrEmpty(user.Id))
            {
                user = await db.Users.Include(u => u.Feeds).ThenInclude(f => f.Feed).FirstOrDefaultAsync(u => u.Id == user.Id);

                if (user == null)
                {
                    throw new UnauthorizedAccessException();
                }
            }
            else
            {
                // Not feedreader uuid, try to find from the related uuid index.
                var dbUser = await db.Users.Include(u => u.Feeds).ThenInclude(f => f.Feed).FirstOrDefaultAsync(u => u.ThirdPartyId == user.ThirdPartyId);

                if (dbUser != null)
                {
                    user = dbUser;
                }
                else
                {
                    // Not found, let's register it.
                    user.Id = Guid.NewGuid().ToString("N").ToLower();
                    user.RegistrationTimeInUtc = DateTime.UtcNow;
                    db.Users.Add(user);
                }
            }

            // Update last active time.
            user.LastActiveTimeInUtc = DateTime.UtcNow;
            await db.SaveChangesAsync();

            // Generate our jwt token.
            var now = DateTimeOffset.UtcNow;

            user.Token = new JwtBuilder()
                         .WithAlgorithm(new HMACSHA256Algorithm())
                         .WithSecret(Environment.GetEnvironmentVariable(Consts.ENV_KEY_JWT_SECRET))
                         .AddClaim("iss", Consts.FEEDREADER_ISS)
                         .AddClaim("aud", Consts.FEEDREADER_AUD)
                         .AddClaim("uid", user.Id)
                         .AddClaim("iat", now.ToUnixTimeSeconds())
                         .AddClaim("exp", now.AddDays(7).ToUnixTimeSeconds())
                         .Encode();
            return(user);
        }
Exemple #2
0
        public async Task UnsubscribeFeedAsync(string feedUri, User user)
        {
            var feedId   = Utils.Sha256(feedUri.Trim().ToLower());
            var userFeed = new ServerCore.Models.UserFeed
            {
                UserId = user.Id,
                FeedId = feedId
            };
            var db = _dbFactory.CreateDbContext();

            db.UserFeeds.Attach(userFeed);
            db.UserFeeds.Remove(userFeed);
            await db.SaveChangesAsync();
        }
Exemple #3
0
        public async Task UpdateFeedAsync(string feedUri, string newFeedGroup, User user)
        {
            // Get the original feed.
            var feedId   = Utils.Sha256(feedUri.Trim().ToLower());
            var db       = _dbFactory.CreateDbContext();
            var userFeed = await db.UserFeeds.FindAsync(user.Id, feedId);

            if (userFeed == null)
            {
                throw new ExternalErrorExceptionNotFound();
            }

            userFeed.Group = newFeedGroup;
            await db.SaveChangesAsync();
        }
        public async Task MarkItemsAsReaded(User user, string feedUri, DateTime lastReadedTime)
        {
            var feedId   = Utils.Sha256(feedUri.Trim().ToLower());
            var db       = _dbFactory.CreateDbContext();
            var userFeed = await db.UserFeeds.FindAsync(user.Id, feedId);

            if (userFeed == null)
            {
                throw new ExternalErrorExcepiton("'feedUri' is not found.");
            }

            // Update with latest feed info.
            userFeed.LastReadedTimeInUtc = lastReadedTime.ToUniversalTime();
            await db.SaveChangesAsync();
        }
        public async Task AddRemoveFavoriteAsync(string feedItemId, bool add, User user)
        {
            var db           = _dbFactory.CreateDbContext();
            var userFeedItem = await db.UserFeedItems.FindAsync(user.Id, feedItemId);

            if (userFeedItem == null)
            {
                if (add)
                {
                    db.UserFeedItems.Add(new UserFeedItem
                    {
                        UserId     = user.Id,
                        FeedItemId = feedItemId,
                        IsFavorite = true,
                    });
                }
            }
            else
            {
                userFeedItem.IsFavorite = add;
            }
            await db.SaveChangesAsync();
        }
Exemple #6
0
        public async Task <Feed> GetFeedItemsAsync(string feedUri, string feedShortId, int page, User user)
        {
            if (string.IsNullOrEmpty(feedUri) && string.IsNullOrEmpty(feedShortId))
            {
                throw new ExternalErrorExcepiton($"FeedUri and FeedShortId can't be empty in both.");
            }

            string feedId = null;
            var    db     = _dbFactory.CreateDbContext();

            if (string.IsNullOrEmpty(feedShortId))
            {
                var originalUri = feedUri;
                feedUri = feedUri.Trim().ToLower();
                feedId  = Utils.Sha256(feedUri);
            }

            // Get feed information.
            // If the user blob is not null, we will get the feed from the user blob because user might customize the group and name on this feed.
            ServerCore.Models.UserFeed userFeed = null;
            ServerCore.Models.Feed     feedInDb = null;
            if (user != null)
            {
                userFeed = await db.UserFeeds.Include(f => f.Feed).FirstOrDefaultAsync(u => u.UserId == user.Id && (u.FeedId == feedId || u.Feed.ShortId == feedShortId));

                feedInDb = userFeed?.Feed;
            }

            // If we didn't get the feed, two possibility:
            // 1. The feed is not subscribed by user yet.
            // 2. Anonymous user.
            // No matter for which case, we will try to get the feed info from feed info table directly.
            if (feedInDb == null)
            {
                feedInDb = await db.Feeds.FirstOrDefaultAsync(f => f.Id == feedId || f.ShortId == feedShortId);
            }

            if (feedInDb == null)
            {
                throw new ExternalErrorExcepiton($"Feed '{feedUri ?? feedShortId}' is not found.");
            }
            feedId = feedInDb.Id;

            var feed = new Feed
            {
                ShortId     = feedInDb.ShortId,
                Description = feedInDb.Description,
                IconUri     = feedInDb.IconUri,
                Name        = feedInDb.Name,
                OriginalUri = feedInDb.Uri,
                Uri         = feedUri,
                WebsiteLink = feedInDb.WebSiteUri,
            };

            if (userFeed != null)
            {
                feed.Group = userFeed.Group;
            }

            // Get feed items.
            var feedItems = await db.FeedItems
                            .Where(f => f.FeedId == feedId)
                            .OrderByDescending(f => f.PublishTimeInUtc)
                            .Skip(page * 50)
                            .Take(50).ToListAsync();

            if (feedItems.Count > 0)
            {
                feed.Items = feedItems.Select(f => new FeedItem
                {
                    Id              = f.Id,
                    Summary         = f.Summary,
                    Content         = f.Content,
                    PermentLink     = f.Uri,
                    PubDate         = f.PublishTimeInUtc,
                    Title           = f.Title,
                    TopicPictureUri = f.TopicPictureUri,
                }).ToList();
            }

            // Mark readed or not.
            if (userFeed != null && userFeed.LastReadedTimeInUtc.Ticks != 0)
            {
                foreach (var feedItem in feed.Items)
                {
                    if (feedItem.PubDate <= userFeed.LastReadedTimeInUtc)
                    {
                        feedItem.IsReaded = true;
                    }
                }
            }

            // Mark stared or not.
            if (user != null)
            {
                // Mark stared or not
                var favorites = db.UserFeedItems.Where(f => f.UserId == user.Id && f.IsFavorite).Select(f => f.FeedItemId).ToList();
                if (favorites.Count > 0)
                {
                    foreach (var feedItem in feed.Items)
                    {
                        if (favorites.Find(id => id == feedItem.PermentLink.Sha256()) != null)
                        {
                            feedItem.IsStared = true;
                        }
                    }
                }
            }

            // All done.
            return(feed);
        }
Exemple #7
0
        public async Task <Feed> SubscribeFeedAsync(string feedOriginalUri, string customGroup, User user)
        {
            Feed   feed        = null;
            string feedUriHash = null;
            var    db          = _dbFactory.CreateDbContext();

            for (var i = 0; i < 10; ++i)
            {
                var feedUri = feedOriginalUri.Trim().ToLower();
                feedUriHash = Utils.Sha256(feedUri);

                // Do we have this feed already?
                var feedInDb = await db.Feeds.FindAsync(feedUriHash);

                if (feedInDb == null)
                {
                    // Get information of this feed.
                    feed = await RefreshFeedAsync(feedOriginalUri, noItems : true);

                    if (feed.Error != null)
                    {
                        // This uri may not be the feed uri. It maybe the webpage, let's try to find out the potential feed uri in this webpage.
                        feedOriginalUri = await DiscoverFeedUriAsync(feedOriginalUri);

                        if (string.IsNullOrWhiteSpace(feedOriginalUri))
                        {
                            break;
                        }
                        continue;
                    }

                    // Save to feed table.
                    feedInDb = new ServerCore.Models.Feed
                    {
                        Description           = feed.Description,
                        IconUri               = feed.IconUri,
                        Id                    = feedUriHash,
                        UriHash               = feedUriHash,
                        Name                  = feed.Name,
                        RegistrationTimeInUtc = DateTime.UtcNow,
                        WebSiteUri            = feed.WebsiteLink,
                        Uri                   = feed.OriginalUri,
                    };
                    db.Feeds.Add(feedInDb);

                    var tryTimes = 0;
                    for (; tryTimes < 10; ++tryTimes)
                    {
                        if (tryTimes == 0)
                        {
                            feedInDb.ShortId = Utils.Crc32(feedInDb.Id);
                        }
                        else
                        {
                            feedInDb.ShortId = Utils.Crc32(feedInDb.Id + tryTimes);
                        }
                        try
                        {
                            await db.SaveChangesAsync();

                            feed.ShortId = feedInDb.ShortId;
                            break;
                        }
                        catch (DbUpdateException ex) when(ex.IsUniqueConstraintException())
                        {
                            if (await _dbFactory.CreateDbContext().Feeds.FindAsync(feedUriHash) != null)
                            {
                                // Save to ignore.
                                break;
                            }
                        }
                    }

                    if (tryTimes < 10)
                    {
                        break;
                    }
                    else
                    {
                        throw new ExternalErrorExcepiton($"Save feed {feed.OriginalUri} failed.");
                    }
                }
                else
                {
                    feed = new Feed
                    {
                        ShortId     = feedInDb.ShortId,
                        Description = feedInDb.Description,
                        IconUri     = feedInDb.IconUri,
                        Name        = feedInDb.Name,
                        OriginalUri = feedInDb.Uri,
                        Uri         = feedUri,
                        WebsiteLink = feedInDb.WebSiteUri,
                    };
                    break;
                }
            }

            Debug.Assert(feed != null);
            Debug.Assert(feedUriHash != null);

            // User user customized group.
            feed.Group = customGroup;

            // Save to usersfeeds table.
            db.UserFeeds.Add(new ServerCore.Models.UserFeed
            {
                UserId = user.Id,
                FeedId = feedUriHash,
                Group  = customGroup
            });
            try
            {
                await db.SaveChangesAsync();
            }
            catch (DbUpdateException ex) when(ex.IsUniqueConstraintException())
            {
                // Save to ignore.
            }

            // Return
            return(feed);
        }
        public async Task <List <ServerCore.Models.FeedItem> > GetStaredFeedItemsAsync(int page, User user)
        {
            var db = _dbFactory.CreateDbContext();

            return(await db.UserFeedItems
                   .Where(f => f.UserId == user.Id && f.IsFavorite)
                   .OrderByDescending(f => f.FeedItem.PublishTimeInUtc)
                   .Skip(page * 50)
                   .Take(50)
                   .Include(f => f.FeedItem)
                   .ThenInclude(f => f.Feed)
                   .Select(f => f.FeedItem)
                   .ToListAsync());
        }
        public async Task UnstarFeedItemAsync(string feedItemPermentLink, DateTime pubDate, User user)
        {
            // Remove from the star items table.
            var db           = _dbFactory.CreateDbContext();
            var feedItemId   = feedItemPermentLink.Sha256();
            var userFeedItem = await db.UserFeedItems.FindAsync(user.Id, feedItemId);

            if (userFeedItem != null)
            {
                userFeedItem.IsFavorite = false;
                await db.SaveChangesAsync();
            }
        }