Пример #1
0
        /// <summary>
        /// Retrieves an enumeration of message details available in the specified catalog
        /// </summary>
        /// <param name="identity">The identity of the user making the request</param>
        /// <param name="catalogName">The name of the catalog in which to retrieve message details</param>
        /// <param name="fromId">The lower bound of the message identifier range to retrieve</param>
        /// <param name="toId">If specified, the upper bound of the message identifier range to retrieve</param>
        /// <returns>An enumeration of message details available in the specified catalog</returns>
        public IEnumerable <IMessageDetail> GetMessageDetails(IIdentity identity, string catalogName, int fromId, int?toId)
        {
            // TODO: Add flags for virtual metagroups.
            IList <IMessageDetail> articleFlags;

            using (var session = SessionUtility.OpenSession())
            {
                var ng = session.Query <Newsgroup>().SingleOrDefault(n => n.Name == catalogName);

                if (toId == null)
                {
                    articleFlags = session.Query <ArticleFlag>()
                                   .Where(af => af.Id == ng.Id)
                                   .Where(af => af.Id >= fromId)
                                   .OrderBy(af => af.Id)
                                   .Cast <IMessageDetail>()
                                   .ToList();
                }
                else
                {
                    articleFlags = session.Query <ArticleFlag>()
                                   .Where(af => af.Id == ng.Id)
                                   .Where(af => af.Id >= fromId && af.Id <= toId.Value)
                                   .OrderBy(af => af.Id)
                                   .Cast <IMessageDetail>()
                                   .ToList();
                }

                session.Close();
            }

            return(articleFlags);
        }
Пример #2
0
        /// <summary>
        /// Deletes a subscription for a user from a catalog, indicating it is 'active' or 'subscribed' for that user
        /// </summary>
        /// <param name="identity">The identity of the user making the request</param>
        /// <param name="catalogName">The name of the catalog in which to subscribe the user</param>
        /// <returns>A value indicating whether the operation was successful</returns>
        public bool DeleteSubscription(IIdentity identity, string catalogName)
        {
            var success = false;

            try
            {
                using (var session = SessionUtility.OpenSession())
                {
                    var owner = session.Query <User>().SingleOrDefault(u => u.Username == identity.Username);
                    if (owner != null)
                    {
                        var sub = session.Query <Subscription>().SingleOrDefault(s => s.Owner.Id == owner.Id && s.Newsgroup == catalogName);
                        if (sub != null)
                        {
                            session.Delete(sub);
                            session.Flush();
                        }

                        success = true;
                    }

                    session.Close();
                }
            }
            catch (MappingException mex)
            {
                _Logger.Error("NHibernate Mapping Exception! (Is schema out of date or damaged?)", mex);
            }
            catch (Exception ex)
            {
                _Logger.Error("Exception when trying to handle UNSUBSCRIBE", ex);
            }

            return(success);
        }
Пример #3
0
        /// <summary>
        /// Retrieves the list of catalogs a user has identified as 'active' or 'subscribed' for themselves
        /// </summary>
        /// <param name="identity">The identity of the user making the request</param>
        /// <returns>A list of catalog names that are subscribed to by the specified <paramref name="identity"/></returns>
        public IEnumerable <string> GetSubscriptions(IIdentity identity)
        {
            var subscriptions = new string[0];

            try
            {
                using (var session = SessionUtility.OpenSession())
                {
                    var owner = session.Query <User>().SingleOrDefault(u => u.Username == identity.Username);
                    if (owner != null)
                    {
                        subscriptions = session.Query <Subscription>().Where(ng => ng.Owner.Id == owner.Id).Select(ng => ng.Newsgroup).ToArray();
                    }

                    session.Close();
                }
            }
            catch (MappingException mex)
            {
                _Logger.Error("NHibernate Mapping Exception! (Is schema out of date or damaged?)", mex);
            }
            catch (Exception ex)
            {
                _Logger.Error("Exception when trying to handle LSUB", ex);
            }

            return(subscriptions);
        }
Пример #4
0
        /// <summary>
        /// Creates a subscription for a user to a catalog, indicating it is 'active' or 'subscribed' for that user
        /// </summary>
        /// <param name="identity">The identity of the user making the request</param>
        /// <param name="catalogName">The name of the catalog in which to subscribe the user</param>
        /// <returns>A value indicating whether the operation was successful</returns>
        public bool CreateSubscription(IIdentity identity, string catalogName)
        {
            var success = false;

            try
            {
                using (var session = SessionUtility.OpenSession())
                {
                    var owner = session.Query <User>().SingleOrDefault(u => u.Username == identity.Username);
                    if (owner != null)
                    {
                        session.Save(new Subscription
                        {
                            Newsgroup = catalogName,
                            Owner     = owner
                        });
                        success = true;
                    }

                    session.Close();
                }
            }
            catch (MappingException mex)
            {
                _Logger.Error("NHibernate Mapping Exception! (Is schema out of date or damaged?)", mex);
            }
            catch (Exception ex)
            {
                _Logger.Error("Exception when trying to handle SUBSCRIBE", ex);
            }

            return(success);
        }
Пример #5
0
        /// <summary>
        /// Retrieves a user by their clear-text username and password
        /// </summary>
        /// <param name="username">The username of the user</param>
        /// <param name="password">The clear-text password of the user</param>
        /// <returns>The user, if one was found with the matching username and password</returns>
        public IIdentity GetIdentityByClearAuth(string username, string password)
        {
            User admin;

            using (var session = SessionUtility.OpenSession())
            {
                admin = session.Query <User>().Fetch(a => a.Moderates).SingleOrDefault(a => a.Username == username);
                if (admin != null)
                {
                    admin.LastLogin = DateTime.UtcNow;
                    session.SaveOrUpdate(admin);
                }

                session.Close();
            }

            if (admin == null)
            {
                return(null);
            }

            if (admin.PasswordHash != Convert.ToBase64String(new SHA512CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(string.Concat(admin.PasswordSalt, password)))))
            {
                _Logger.WarnFormat("User {0} failed authentication against local authentication database.", admin.Username);
                return(null);
            }

            return(admin);
        }
Пример #6
0
        /// <summary>
        /// Retrieves an enumeration of global catalogs available to an end-user at the root level in the store
        /// </summary>
        /// <param name="identity">The identity of the user making the request</param>
        /// <param name="parentCatalogName">The parent catalog.  When specified, this finds catalogs that are contained in this specified parent catalog</param>
        /// <returns>An enumeration of catalogs available to an end-user at the root level in the store</returns>
        public IEnumerable <ICatalog> GetGlobalCatalogs(IIdentity identity, string parentCatalogName)
        {
            IEnumerable <Newsgroup> newsGroups = null;

            if (this.HierarchyDelimiter == "NIL")
            {
                return(null);
            }

            try
            {
                using (var session = SessionUtility.OpenSession())
                {
                    newsGroups = session.Query <Newsgroup>()
                                 .Where(n => n.Owner == null)
                                 .ToList()
                                 .Where(n =>
                                        (parentCatalogName == null && (this.HierarchyDelimiter == "NIL" || n.Name.IndexOf(this.HierarchyDelimiter, StringComparison.OrdinalIgnoreCase) == -1)) ||
                                        (parentCatalogName != null && (this.HierarchyDelimiter != "NIL" && n.Name.StartsWith(parentCatalogName + this.HierarchyDelimiter))))
                                 .AddMetagroups(session, identity).OrderBy(n => n.Name).ToList();
                    session.Close();
                }
            }
            catch (MappingException mex)
            {
                _Logger.Error("NHibernate Mapping Exception! (Is schema out of date or damaged?)", mex);
            }
            catch (Exception ex)
            {
                _Logger.Error("Exception when trying to handle LIST", ex);
            }

            return(newsGroups);
        }
Пример #7
0
        /// <summary>
        /// Retrieves a catalog by its name
        /// </summary>
        /// <param name="identity">The identity of the user making the request</param>
        /// <param name="name">The name of the catalog to retrieve</param>
        /// <returns>The catalog with the specified <paramref name="name"/>, if one exists</returns>
        public ICatalog GetCatalogByName(IIdentity identity, string name)
        {
            Newsgroup ng;

            using (var session = SessionUtility.OpenSession())
            {
                ng = session.Query <Newsgroup>().AddMetagroups(session, identity).SingleOrDefault(n => n.Name == name);
                session.Close();
            }

            return(ng);
        }
Пример #8
0
        /// <summary>
        /// Creates a personal catalog
        /// </summary>
        /// <param name="identity">The identity of the user making the request</param>
        /// <param name="catalogName">The name of the personal catalog</param>
        /// <returns>A value indicating whether the operation was successful</returns>
        public bool CreatePersonalCatalog(IIdentity identity, string catalogName)
        {
            if (string.Compare(catalogName, "INBOX", StringComparison.OrdinalIgnoreCase) == 0)
            {
                return(false);
            }

            try
            {
                using (var session = SessionUtility.OpenSession())
                {
                    var owner = session.Query <User>().SingleOrDefault(u => u.Username == identity.Username);
                    if (owner == null)
                    {
                        return(false);
                    }

                    var catalog = session.Query <Newsgroup>().SingleOrDefault(ng => ng.Name == catalogName && ng.Owner.Id == owner.Id);
                    if (catalog != null)
                    {
                        return(false);
                    }

                    catalog = new Newsgroup
                    {
                        CreateDate       = DateTime.UtcNow,
                        CreatorEntity    = identity.Username,
                        DenyLocalPosting = false,
                        DenyPeerPosting  = true,
                        Description      = "Personal inbox for " + identity.Username,
                        Moderated        = false,
                        Name             = catalogName,
                        Owner            = owner
                    };
                    session.Save(catalog);
                    session.Close();
                }
            }
            catch (MappingException mex)
            {
                _Logger.Error("NHibernate Mapping Exception! (Is schema out of date or damaged?)", mex);
                return(false);
            }
            catch (Exception ex)
            {
                _Logger.Error("Exception when trying to handle LIST", ex);
                return(false);
            }

            return(true);
        }
Пример #9
0
        /// <summary>
        /// Ensures a user has any requisite initialization in the store performed prior to their execution of other store methods
        /// </summary>
        /// <param name="identity">The identity of the user to ensure is initialized properly in the store</param>
        public void Ensure(IIdentity identity)
        {
            var personalCatalogs = this.GetPersonalCatalogs(identity, null);

            if (personalCatalogs != null && personalCatalogs.All(c => c.Name != "INBOX"))
            {
                using (var session = SessionUtility.OpenSession())
                {
                    var ng = new Newsgroup
                    {
                        CreateDate  = DateTime.UtcNow,
                        Description = "Personal inbox for " + identity.Username,
                        Name        = "INBOX",
                        Owner       = (User)identity
                    };

                    session.Save(ng);
                    session.Flush();
                    session.Close();
                }
            }
        }
Пример #10
0
        public static bool VerifyDatabase(bool quiet = false)
        {
            var configuration = new Configuration();

            configuration.AddAssembly(typeof(Newsgroup).Assembly);
            configuration.Configure();

            //try
            //{
            //    var validator = new SchemaValidator(configuration);
            //    validator.Validate();
            //}
            //catch (Exception ex)
            //{
            //    _logger.Error("The database schema is out of date: " + ex.Message, ex);
            //    return false;
            //}

            try
            {
                using (var session = SessionUtility.OpenSession())
                {
                    var newsgroupCount = session.Query <Newsgroup>().Count(n => n.Name != null);
                    if (newsgroupCount == 0 && !quiet)
                    {
                        _Logger.Warn("Verified database has 0 newsgroups");
                    }
                    else if (!quiet)
                    {
                        _Logger.InfoFormat("Verified database has {0} newsgroup{1}", newsgroupCount, newsgroupCount == 1 ? null : "s");
                    }

                    var articleCount = session.Query <Article>().Count(a => a.Headers != null);
                    var article      = session.Query <Article>().FirstOrDefault(a => a.ArticleNewsgroups.Any(an => !an.Cancelled));
                    if (article != null)
                    {
                        var an = article.InjectionDate;
                        article.InjectionDate = "test";
                        session.Save(article);
                        article.InjectionDate = an;
                        session.Save(article);
                    }
                    if (!quiet)
                    {
                        _Logger.InfoFormat("Verified database has {0} article{1}", articleCount, articleCount == 1 ? null : "s");
                    }

                    var adminCount = session.Query <User>().Count(a => a.CanInject);
                    if (adminCount == 0 && !quiet)
                    {
                        _Logger.Warn("Verified database has 0 local admins");
                    }
                    else if (!quiet)
                    {
                        _Logger.InfoFormat("Verified database has {0} local admin{1}", adminCount, adminCount == 1 ? null : "s");
                    }

                    var peerCount = session.Query <Peer>().Count();
                    if (peerCount == 0 && !quiet)
                    {
                        _Logger.Warn("Verified database has 0 distribution patterns");
                    }
                    else if (!quiet)
                    {
                        _Logger.InfoFormat("Verified database has {0} distribution pattern{1}", peerCount, peerCount == 1 ? null : "s");
                    }


                    var distPatternCount = session.Query <DistributionPattern>().Count();
                    if (distPatternCount == 0 && !quiet)
                    {
                        _Logger.Warn("Verified database has 0 distribution patterns");
                    }
                    else if (!quiet)
                    {
                        _Logger.InfoFormat("Verified database has {0} distribution pattern{1}", distPatternCount, distPatternCount == 1 ? null : "s");
                    }

                    session.Close();

                    return(newsgroupCount > 0);
                }
            }
            catch (Exception)
            {
                return(false);
            }
        }
Пример #11
0
        private static void WriteBaselineData()
        {
            // Ensure placeholder data is there.
            using (var session = SessionUtility.OpenSession())
            {
                if (!session.Query <Newsgroup>().Any(n => n.Name == "freenews.config"))
                {
                    session.Save(new Newsgroup
                    {
                        CreateDate  = DateTime.UtcNow,
                        Description = "Control group for the repository",
                        Moderated   = true,
                        Name        = "freenews.config"
                    });
                    _Logger.InfoFormat("Created 'freenews.config' group");
                }

                if (!session.Query <Newsgroup>().Any(n => n.Name == "freenews.misc"))
                {
                    session.Save(new Newsgroup
                    {
                        CreateDate  = DateTime.UtcNow,
                        Description = "Test group for the repository",
                        Moderated   = false,
                        Name        = "freenews.misc"
                    });
                    _Logger.InfoFormat("Created 'freenews.misc' group");
                }

                if (!session.Query <Newsgroup>().Any(n => n.Name == "junk"))
                {
                    session.Save(new Newsgroup
                    {
                        CreateDate  = DateTime.UtcNow,
                        Description = "Junk group for the repository",
                        Moderated   = true,
                        Name        = "junk"
                    });
                    _Logger.InfoFormat("Created 'junk' group");
                }

                if (!session.Query <User>().Any())
                {
                    var admin = new User
                    {
                        CanApproveAny           = true,
                        CanCancel               = true,
                        CanCheckCatalogs        = true,
                        CanCreateCatalogs       = true,
                        CanDeleteCatalogs       = true,
                        CanInject               = true,
                        LocalAuthenticationOnly = true,
                        Username = "******"
                    };

                    var ss = new SecureString();
                    foreach (var c in "CHANGEME")
                    {
                        ss.AppendChar(c);
                    }
                    admin.SetPassword(ss);

                    session.Save(admin);

                    _Logger.InfoFormat("Created 'LOCALADMIN' administrator with password 'CHANGEME'.  Please authenticate locally and change your password with a 'changepass' control message");
                }

                session.Close();
            }
        }
Пример #12
0
        /// <summary>
        /// Retrieves an enumeration of messages available in the specified catalog
        /// </summary>
        /// <param name="identity">The identity of the user making the request</param>
        /// <param name="catalogName">The name of the catalog in which to retrieve messages</param>
        /// <param name="fromId">The lower bound of the message identifier range to retrieve</param>
        /// <param name="toId">If specified, the upper bound of the message identifier range to retrieve</param>
        /// <returns>An enumeration of messages available in the specified catalog</returns>
        public IEnumerable <IMessage> GetMessages(IIdentity identity, string catalogName, int fromId, int?toId)
        {
            IList <IMessage> articleNewsgroups;

            using (var session = SessionUtility.OpenSession())
            {
                var ng = session.Query <Newsgroup>().AddMetagroups(session, identity).SingleOrDefault(n => n.Name == catalogName);

                if (toId == null)
                {
                    if (catalogName.EndsWith(".deleted"))
                    {
                        articleNewsgroups = session.Query <ArticleNewsgroup>()
                                            .Where(an => an.Newsgroup.Name == ng.Name.Substring(0, ng.Name.Length - 8) && an.Cancelled)
                                            .Where(an => an.Number >= fromId)
                                            .OrderBy(an => an.Number)
                                            .Cast <IMessage>()
                                            .ToList();
                    }
                    else if (catalogName.EndsWith(".pending"))
                    {
                        articleNewsgroups = session.Query <ArticleNewsgroup>()
                                            .Where(an => an.Newsgroup.Name == ng.Name.Substring(0, ng.Name.Length - 8) && an.Pending)
                                            .Where(an => an.Number >= fromId)
                                            .OrderBy(an => an.Number)
                                            .Cast <IMessage>()
                                            .ToList();
                    }
                    else
                    {
                        articleNewsgroups = session.Query <ArticleNewsgroup>()
                                            .Where(an => an.Newsgroup.Name == ng.Name && !an.Cancelled && !an.Pending)
                                            .Where(an => an.Number >= fromId)
                                            .OrderBy(an => an.Number)
                                            .Cast <IMessage>()
                                            .ToList();
                    }
                }
                else
                {
                    if (catalogName.EndsWith(".deleted"))
                    {
                        articleNewsgroups = session.Query <ArticleNewsgroup>()
                                            .Where(an => an.Newsgroup.Name == ng.Name.Substring(0, ng.Name.Length - 8) && an.Cancelled)
                                            .Where(an => an.Number >= fromId && an.Number <= toId.Value)
                                            .OrderBy(an => an.Number)
                                            .Cast <IMessage>()
                                            .ToList();
                    }
                    else if (catalogName.EndsWith(".pending"))
                    {
                        articleNewsgroups = session.Query <ArticleNewsgroup>()
                                            .Where(an => an.Newsgroup.Name == ng.Name.Substring(0, ng.Name.Length - 8) && an.Pending)
                                            .Where(an => an.Number >= fromId && an.Number <= toId.Value)
                                            .OrderBy(an => an.Number)
                                            .Cast <IMessage>()
                                            .ToList();
                    }
                    else
                    {
                        articleNewsgroups = session.Query <ArticleNewsgroup>()
                                            .Where(an => an.Newsgroup.Name == ng.Name && !an.Cancelled && !an.Pending)
                                            .Where(an => an.Number >= fromId && an.Number <= toId.Value)
                                            .OrderBy(an => an.Number)
                                            .Cast <IMessage>()
                                            .ToList();
                    }
                }

                session.Close();
            }

            return(articleNewsgroups);
        }