示例#1
0
        /// <summary>
        /// Creates a new message in the given thread
        /// Caller should validate input parameters.
        /// </summary>
        /// <param name="threadID">Thread wherein the new message will be placed</param>
        /// <param name="userID">User who posted this message</param>
        /// <param name="messageText">Message text</param>
        /// <param name="messageAsHTML">Message text as HTML</param>
        /// <param name="userIDIPAddress">IP address of user calling this method</param>
        /// <param name="messageAsXML">Message text as XML, which is the result of the parse action on MessageText.</param>
        /// <param name="subscribeToThread">if set to <c>true</c> [subscribe to thread].</param>
        /// <param name="threadUpdatedNotificationTemplate">The thread updated notification template.</param>
        /// <param name="emailData">The email data.</param>
        /// <param name="sendReplyNotifications">Flag to signal to send reply notifications. If set to false no notifications are mailed,
        /// otherwise a notification is mailed to all subscribers to the thread the new message is posted in</param>
        /// <returns>MessageID if succeeded, 0 if not.</returns>
        public static int CreateNewMessageInThread(int threadID, int userID, string messageText, string messageAsHTML, string userIDIPAddress, 
            string messageAsXML, bool subscribeToThread, string threadUpdatedNotificationTemplate, Dictionary<string,string> emailData,
            bool sendReplyNotifications)
        {
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "InsertNewMessage");
            int messageID = 0;
            try
            {
                DateTime postingDate = DateTime.Now;
                messageID = InsertNewMessage(threadID, userID, messageText, messageAsHTML, userIDIPAddress, messageAsXML, trans, postingDate);
                MessageManager.UpdateStatisticsAfterMessageInsert(threadID, userID, trans, postingDate, true, subscribeToThread);
                trans.Commit();
            }
            catch(Exception)
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }

            if(sendReplyNotifications)
            {
                // send notification email to all subscribers. Do this outside the transaction so a failed email send action doesn't terminate the save process
                // of the message.
                ThreadManager.SendThreadReplyNotifications(threadID, userID, threadUpdatedNotificationTemplate, emailData);
            }
            return messageID;
        }
示例#2
0
        /// <summary>
        /// Adds the thread with the ID specified to the support queue with the ID specified
        /// </summary>
        /// <param name="threadID">The thread ID.</param>
        /// <param name="queueID">The queue ID.</param>
        /// <param name="userID">The user ID of the user causing this thread to be placed in the queue specified.</param>
        /// <param name="transactionToUse">The transaction to use. Is not null if there's a transaction in progress.</param>
        /// <remarks>first removes the thread from a queue if it's in a queue</remarks>
        public static void AddThreadToQueue(int threadID, int queueID, int userID, Transaction transactionToUse)
        {
            // first remove the thread from any queue it's in.
            RemoveThreadFromQueue(threadID, transactionToUse);

            // then add it to the queue specified.
            SupportQueueThreadEntity supportQueueThread = new SupportQueueThreadEntity();
            supportQueueThread.ThreadID = threadID;
            supportQueueThread.QueueID = queueID;
            supportQueueThread.PlacedInQueueByUserID = userID;
            supportQueueThread.PlacedInQueueOn = DateTime.Now;

            if(transactionToUse != null)
            {
                // transaction in progress, add the entity to the transaction
                transactionToUse.Add(supportQueueThread);
            }
            supportQueueThread.Save();
        }
示例#3
0
		/// <summary>
		/// Gets the thread subscription object for the thread - user combination passed in. If there's no subscription, null is returned.
		/// </summary>
		/// <param name="threadID">The thread ID.</param>
		/// <param name="userID">The user ID.</param>
		/// <param name="transactionToUse">The transaction to use. Pass in the transaction object if this fetch has to take place inside a transaction</param>
		/// <returns>
		/// requested Threadsubscription entity or null if not found
		/// </returns>
		public static ThreadSubscriptionEntity GetThreadSubscription(int threadID, int userID, Transaction transactionToUse)
		{
			ThreadSubscriptionEntity toReturn = new ThreadSubscriptionEntity();
			if(transactionToUse != null)
			{
				// transaction in progress, add entity to it so it's not blocked
				transactionToUse.Add(toReturn);
			}

			// fetch the data
			toReturn.FetchUsingPK(userID, threadID);
			if(toReturn.IsNew)
			{
				// not found
				return null;
			}

			// done. Don't commit a passed in transaction here, it's controlled by the caller.
			return toReturn;
		}
示例#4
0
        /// <summary>
        /// Marks the thread as done.
        /// </summary>
        /// <param name="threadID">Thread ID.</param>
        /// <returns></returns>
        public static bool MarkThreadAsDone(int threadID)
        {
            // load the entity from the database
            ThreadEntity thread = ThreadGuiHelper.GetThread(threadID);
            if(thread == null)
            {
                // not found
                return false;
            }

            // get the support queue the thread is in (if any)
            SupportQueueEntity containingSupportQueue = SupportQueueGuiHelper.GetQueueOfThread(threadID);
            thread.MarkedAsDone = true;

            // if the thread is in a support queue, the thread has to be removed from that queue. This is a multi-entity action and therefore we've to start a
            // transaction if that's the case. If not, we can use the easy route and simply save the thread and be done with it.
            if(containingSupportQueue == null)
            {
                // not in a queue, simply save the thread.
                return thread.Save();
            }

            // in a queue, so remove from the queue and save the entity.
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "MarkThreadDone");
            trans.Add(thread);
            try
            {
                // save the thread
                bool result = thread.Save();
                if(result)
                {
                    // save succeeded, so remove from queue, pass the current transaction to the method so the action takes place inside this transaction.
                    SupportQueueManager.RemoveThreadFromQueue(threadID, trans);
                }

                trans.Commit();
                return true;
            }
            catch
            {
                // rollback transaction
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
示例#5
0
        /// <summary>
        /// Creates a new message in the given thread and closes the thread right after the addition of the message,
        /// which makes the just added message the 'close' message of the thread. Close messages are handy when the
        /// closure of a thread is not obvious.
        /// Caller should validate input parameters.
        /// </summary>
        /// <param name="threadID">Thread wherein the new message will be placed</param>
        /// <param name="userID">User who posted this message</param>
        /// <param name="messageText">Message text</param>
        /// <param name="messageAsHTML">Message text as HTML</param>
        /// <param name="userIDIPAddress">IP address of user calling this method</param>
        /// <param name="messageAsXML">Message text as XML, which is the result of the parse action on MessageText.</param>
        /// <param name="threadUpdatedNotificationTemplate">The thread updated notification template.</param>
        /// <param name="emailData">The email data.</param>
        /// <param name="sendReplyNotifications">Flag to signal to send reply notifications. If set to false no notifications are mailed,
        /// otherwise a notification is mailed to all subscribers to the thread the new message is posted in</param>
        /// <returns>MessageID if succeeded, 0 if not.</returns>
        public static int CreateNewMessageInThreadAndCloseThread(int threadID, int userID, string messageText, string messageAsHTML,
            string userIDIPAddress, string messageAsXML, string threadUpdatedNotificationTemplate, Dictionary<string, string> emailData,
            bool sendReplyNotifications)
        {
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "InsertNewMessage");
            int messageID = 0;
            try
            {
                DateTime postingDate = DateTime.Now;
                messageID = InsertNewMessage(threadID, userID, messageText, messageAsHTML, userIDIPAddress, messageAsXML, trans, postingDate);

                MessageManager.UpdateStatisticsAfterMessageInsert(threadID, userID, trans, postingDate, false, false);

                ThreadEntity thread = new ThreadEntity();
                trans.Add(thread);
                thread.FetchUsingPK(threadID);
                thread.IsClosed=true;
                thread.IsSticky=false;
                thread.MarkedAsDone = true;
                bool result = thread.Save();
                if(result)
                {
                    // save succeeded, so remove from queue, pass the current transaction to the method so the action takes place inside this transaction.
                    SupportQueueManager.RemoveThreadFromQueue(threadID, trans);
                }

                trans.Commit();
            }
            catch(Exception)
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }

            if(sendReplyNotifications)
            {
                // send notification email to all subscribers. Do this outside the transaction so a failed email send action doesn't terminate the save process
                // of the message.
                ThreadManager.SendThreadReplyNotifications(threadID, userID, threadUpdatedNotificationTemplate, emailData);
            }
            return messageID;
        }
示例#6
0
 /// <summary>
 /// Deletes the given Thread from the system, including <b>all</b> messages and related data in this Thread.
 /// </summary>
 /// <param name="ID">Thread to delete.</param>
 /// <returns>True if succeeded, false otherwise</returns>
 public static bool DeleteThread(int threadID)
 {
     // trying to delete the entity directly from the database without first loading it.
     // for that we use an entity collection and use the DeleteMulti method with a filter on the PK.
     PredicateExpression threadFilter = new PredicateExpression(ThreadFields.ThreadID == threadID);
     Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "DeleteThread");
     try
     {
         DeleteThreads(threadFilter, trans);
         trans.Commit();
         return true;
     }
     catch
     {
         // error occured
         trans.Rollback();
         throw;
     }
     finally
     {
         trans.Dispose();
     }
 }
示例#7
0
        /// <summary>
        /// Modifies the given role: it resets the system action rights for the given role to the given set of action rights and it modifies
        /// the role description for the given role. If the user specified a role description that is already available, false will be returned to signal
        /// that the save failed.
        /// </summary>
        /// <param name="actionRightIDs">The action rights.</param>
        /// <param name="roleID">The role ID.</param>
        /// <param name="roleDescription">The role description.</param>
        /// <returns>true if succeeded, false otherwise</returns>
        public static bool ModifyRole(List<int> actionRightIDs, int roleID, string roleDescription)
        {
            // read the existing role entity from the database.
            RoleEntity roleToModify = new RoleEntity(roleID);
            if(roleToModify.IsNew)
            {
                // not found
                return false;
            }

            // check if the description is different. If so, we've to check if the new roledescription is already present. If so, we'll
            // abort the save
            if(roleToModify.RoleDescription != roleDescription)
            {
                if(CheckIfRoleDescriptionIsPresent(roleDescription))
                {
                    // new description, is already present, fail
                    return false;
                }
            }

            // all set. We're going to delete all Role - SystemAction Rights combinations first, as we're going to re-insert them later on.
            // We'll use a transaction to be able to roll back all our changes if something fails.
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "ModifyRole");
            try
            {
                RoleSystemActionRightCollection roleActionRights = new RoleSystemActionRightCollection();
                // add this collection to the transaction so all actions executed through this collection will be inside the transaction
                trans.Add(roleActionRights);
                // delete all role-systemactionright combinations directly from the database, by issuing a direct delete on the database, using a filter
                // on roleid
                roleActionRights.DeleteMulti(RoleSystemActionRightFields.RoleID == roleID);

                // add new role-systemactionright entities which we'll save to the database after that
                foreach(int actionRightID in actionRightIDs)
                {
                    RoleSystemActionRightEntity toAdd = new RoleSystemActionRightEntity();
                    toAdd.ActionRightID = actionRightID;
                    toAdd.RoleID = roleID;
                    roleActionRights.Add(toAdd);
                }
                // save the new entities to the database
                roleActionRights.SaveMulti();

                // we'll now save the role and the role description, if it's changed. Otherwise the save action will be a no-op.
                // add it to the transaction
                trans.Add(roleToModify);
                roleToModify.RoleDescription = roleDescription;
                roleToModify.Save();

                // all done, commit the transaction
                trans.Commit();
                return true;
            }
            catch
            {
                // failed, roll back transaction.
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
示例#8
0
        /// <summary>
        /// Deletes the user with the ID passed in. Will reset all posts made by the user to the userid 0. 
        /// </summary>
        /// <param name="userID">The user ID.</param>
        /// <remarks>Can't delete user 0</remarks>
        /// <returns>true if succeeded, false otherwise</returns>
        public static bool DeleteUser(int userID)
        {
            if(userID == 0)
            {
                // can't delete the Anonymous coward user.
                return false;
            }

            UserEntity toDelete = UserGuiHelper.GetUser(userID);
            if(toDelete==null)
            {
                // user doesn't exist
                return false;
            }

            // all actions have to take place in a transaction.
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "DeleteUser");

            try
            {
                // we'll first update all PostedByUserId fields of all messages which are posted by the user to delete.
                MessageEntity messageUpdater = new MessageEntity();
                messageUpdater.PostedByUserID = 0;	// reset to AC.
                MessageCollection messages = new MessageCollection();
                trans.Add(messages);	// add to the transaction
                // update all entities directly in the DB, which match the following filter and update them with the new values set in messageUpdater.
                messages.UpdateMulti(messageUpdater, (MessageFields.PostedByUserID == userID));

                // set the startuser of threads started by this user to 0
                ThreadEntity threadUpdater = new ThreadEntity();
                threadUpdater.StartedByUserID = 0;
                ThreadCollection threads = new ThreadCollection();
                trans.Add(threads);
                threads.UpdateMulti(threadUpdater, (ThreadFields.StartedByUserID == userID));

                // remove the user from the UserRoles set, as the user shouldn't be in any roles.
                RoleUserCollection roleUsersDeleter = new RoleUserCollection();
                trans.Add(roleUsersDeleter);
                // delete all entities directly from the DB which match the following filter.
                roleUsersDeleter.DeleteMulti(RoleUserFields.UserID == userID);

                // delete all bookmarks of user
                BookmarkCollection bookmarkDeleter = new BookmarkCollection();
                trans.Add(bookmarkDeleter);
                // delete all bookmarks for this user directly from the DB using the following filter.
                bookmarkDeleter.DeleteMulti(BookmarkFields.UserID == userID);

                // delete all audit data
                AuditDataCoreCollection auditDataDeleter = new AuditDataCoreCollection();
                // first fetch it, then delete all entities from the collection, as the audit data is in an inheritance hierarchy of TargetPerEntity which can't
                // be deleted directly from the db.
                trans.Add(auditDataDeleter);
                auditDataDeleter.GetMulti(AuditDataCoreFields.UserID == userID);
                auditDataDeleter.DeleteMulti();

                // set IP bans set by this user to userid 0
                IPBanEntity ipbanUpdater = new IPBanEntity();
                ipbanUpdater.IPBanSetByUserID = 0;
                IPBanCollection ipBans = new IPBanCollection();
                trans.Add(ipBans);
                ipBans.UpdateMulti(ipbanUpdater, (IPBanFields.IPBanSetByUserID == userID));

                // delete threadsubscriptions
                ThreadSubscriptionCollection threadSubscriptionsDeleter = new ThreadSubscriptionCollection();
                trans.Add(threadSubscriptionsDeleter);
                threadSubscriptionsDeleter.DeleteMulti(ThreadSubscriptionFields.UserID == userID);

                // remove supportqueuethread claims
                SupportQueueThreadCollection supportQueueThreads = new SupportQueueThreadCollection();
                trans.Add(supportQueueThreads);
                supportQueueThreads.DeleteMulti(SupportQueueThreadFields.ClaimedByUserID == userID);

                // set all placed in queue references to userid 0, so the threads stay in the queues.
                SupportQueueThreadEntity supportQueueThreadUpdater = new SupportQueueThreadEntity();
                supportQueueThreadUpdater.PlacedInQueueByUserID=0;
                supportQueueThreads.UpdateMulti(supportQueueThreadUpdater, (SupportQueueThreadFields.PlacedInQueueByUserID == userID));

                // now delete the actual user entity
                trans.Add(toDelete);
                toDelete.Delete();

                // all done
                trans.Commit();
                return true;
            }
            catch
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
示例#9
0
        /// <summary>
        /// Saves the audit actions for role specified. First removes all present rows for the roleid
        /// </summary>
        /// <param name="auditActionIDs">Audit action IDs.</param>
        /// <param name="roleID">Role ID.</param>
        /// <returns>true if the save action succeeded, false otherwise</returns>
        public static bool SaveAuditActionsForRole(List<int> auditActionIDs, int roleID)
        {
            RoleAuditActionCollection roleAuditActions = new RoleAuditActionCollection();
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "SaveAuditActionsForRole");

            // add this collection to the transaction so all actions executed through this collection will be inside the transaction
            trans.Add(roleAuditActions);

            try
            {
                // first remove the existing rows for the role
                roleAuditActions.DeleteMulti((RoleAuditActionFields.RoleID == roleID));

                // THEN add new ones to the same collection.
                foreach(int auditActionID in auditActionIDs)
                {
                    RoleAuditActionEntity newRoleAuditAction = new RoleAuditActionEntity();
                    newRoleAuditAction.AuditActionID = auditActionID;
                    newRoleAuditAction.RoleID = roleID;
                    roleAuditActions.Add(newRoleAuditAction);
                }

                // save all new entities
                roleAuditActions.SaveMulti();

                // succeeded, commit transaction
                trans.Commit();
                return true;
            }
            catch
            {
                // failed, rollback transaction
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
示例#10
0
        /// <summary>
        /// Removes the thread with the threadid specified from the queue it's in. A thread can be in a single queue, so we don't need the queueID.
        /// </summary>
        /// <param name="threadID">The thread ID.</param>
        /// <param name="transactionToUse">The transaction currently in progress. Can be null if no transaction is in progress.</param>
        public static void RemoveThreadFromQueue(int threadID, Transaction transactionToUse)
        {
            // delete the SupportQueueThread entity for this thread directly from the db, inside the transaction specified (if applicable)
            SupportQueueThreadCollection supportQueueThreads = new SupportQueueThreadCollection();
            if(transactionToUse != null)
            {
                // there's a transaction in progress, simply add it to the transaction
                transactionToUse.Add(supportQueueThreads);
            }

            // delete directly, using a filter on threadid
            supportQueueThreads.DeleteMulti((SupportQueueThreadFields.ThreadID == threadID));

            // don't commit the current transaction if specified, simply return to caller.
        }
示例#11
0
        /// <summary>
        /// Marks the thread as un-done, and add it to the default queue of the forum.
        /// </summary>
        /// <param name="threadID">Thread ID</param>
        /// <returns></returns>
        public static bool UnMarkThreadAsDone(int threadID, int userID)
        {
            // load the entity from the database
            ThreadEntity thread = ThreadGuiHelper.GetThread(threadID);
            if (thread == null)
            {
                // not found
                return false;
            }

            thread.MarkedAsDone = false;

            ForumEntity forum = new ForumEntity(thread.ForumID);

            // Save the thread and add it to the default queue of the forum.
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "MarkThreadUnDone");
            trans.Add(thread);
            try
            {
                thread.Save();

                if ((forum.Fields.State == EntityState.Fetched) && (forum.DefaultSupportQueueID.HasValue))
                {
                    // not in a queue, and the forum has a default queue. Add the thread to the queue of the forum
                    SupportQueueManager.AddThreadToQueue(threadID, forum.DefaultSupportQueueID.Value, userID, trans);
                }

                trans.Commit();
                return true;
            }
            catch
            {
                // rollback transaction
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
示例#12
0
        /// <summary>
        /// Deletes the threads matching the passed in filter, inside the transaction specified.
        /// </summary>
        /// <param name="threadFilter">The thread filter.</param>
        /// <param name="trans">The transaction to use.</param>
        private static void DeleteThreads(PredicateExpression threadFilter, Transaction trans)
        {
            // we've to perform a set of actions in a given order to make sure we're not violating FK constraints in the DB.

            // delete messages in thread
            MessageManager.DeleteAllMessagesInThreads(threadFilter, trans);

            // delete bookmarks (if exists) of the threads to be deleted
            BookmarkCollection bookmarks = new BookmarkCollection();
            trans.Add(bookmarks);
            // use again a fieldcompareset predicate
            bookmarks.DeleteMulti(new FieldCompareSetPredicate(BookmarkFields.ThreadID, ThreadFields.ThreadID, SetOperator.In, threadFilter));

            // delete audit info related to this thread. Can't be done directly on the db due to the fact the entities are in a TargetPerEntity hierarchy, which
            // can't be deleted directly on the db, so we've to fetch the entities first.
            AuditDataThreadRelatedCollection threadAuditData = new AuditDataThreadRelatedCollection();
            trans.Add(threadAuditData);
            // use a fieldcompareset predicate filter, based on the threadFilter.
            threadAuditData.GetMulti(new FieldCompareSetPredicate(AuditDataThreadRelatedFields.ThreadID, ThreadFields.ThreadID, SetOperator.In, threadFilter));
            threadAuditData.DeleteMulti();

            // delete support queue thread entity for this thread (if any)
            SupportQueueThreadCollection supportQueueThreads = new SupportQueueThreadCollection();
            trans.Add(supportQueueThreads);
            // use again a fieldcompareset predicate
            supportQueueThreads.DeleteMulti(new FieldCompareSetPredicate(SupportQueueThreadFields.ThreadID, ThreadFields.ThreadID, SetOperator.In, threadFilter));

            // delete threadsubscription entities
            ThreadSubscriptionCollection threadSubscriptions = new ThreadSubscriptionCollection();
            trans.Add(threadSubscriptions);
            // use again a fieldcompareset predicate
            threadSubscriptions.DeleteMulti(new FieldCompareSetPredicate(ThreadSubscriptionFields.ThreadID, ThreadFields.ThreadID, SetOperator.In, threadFilter));

            // delete the threads
            ThreadCollection threads = new ThreadCollection();
            trans.Add(threads);
            // we already have the filter to use, namely the filter passed in.
            threads.DeleteMulti(threadFilter);

            // don't commit the transaction, that's up to the caller.
        }
示例#13
0
        /// <summary>
        /// Deletes the given message from the database and the complete logged history.
        /// </summary>
        /// <param name="messageID">The ID of the message to delete</param>
        /// <returns>True if succeeded, false otherwise</returns>
        public static bool DeleteMessage(int messageID)
        {
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "DeleteMessage");

            try
            {
                // formulate a filter so we can re-use the delete routine for all messages in threads matching a filter.
                PredicateExpression messageFilter = new PredicateExpression(MessageFields.MessageID == messageID);

                // call the routine which is used to delete 1 or more messages and related data from the db.
                DeleteMessages(messageFilter, trans);
                trans.Commit();
                return true;
            }
            catch(Exception)
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
示例#14
0
        /// <summary>
        /// Deletes the messages matching the messagefilter passed in
        /// </summary>
        /// <param name="messageFilter">The message filter.</param>
        /// <param name="trans">The transaction to use.</param>
        private static void DeleteMessages(IPredicate messageFilter, Transaction trans)
        {
            // first delete all audit info for these message. This isn't done by a batch call directly on the db, as this is a targetperentity hierarchy
            // which can't be deleted directly into the database in all cases, so we first fetch the entities to delete.
            AuditDataMessageRelatedCollection messageAudits = new AuditDataMessageRelatedCollection();
            trans.Add(messageAudits);
            // use a fieldcompareset predicate to get the auditdata related to this message and then delete all of them using the collection.
            messageAudits.GetMulti(new FieldCompareSetPredicate(AuditDataMessageRelatedFields.MessageID, MessageFields.MessageID, SetOperator.In, messageFilter));
            messageAudits.DeleteMulti();

            // delete all attachments for this message. This can be done directly onto the db.
            AttachmentCollection attachments = new AttachmentCollection();
            trans.Add(attachments);
            // delete these directly from the db, using a fieldcompareset predicate
            attachments.DeleteMulti(new FieldCompareSetPredicate(AttachmentFields.MessageID, MessageFields.MessageID, SetOperator.In, messageFilter));

            // delete the message/messages
            MessageCollection messages = new MessageCollection();
            trans.Add(messages);
            // use the passed in filter to remove the messages
            messages.DeleteMulti(messageFilter);

            // don't commit the transaction, leave that to the caller.
        }
示例#15
0
        /// <summary>
        /// Updates the user/forum/thread statistics after a message insert. Also makes sure if the thread isn't in a queue and the forum has a default support
        /// queue that the thread is added to that queue
        /// </summary>
        /// <param name="threadID">The thread ID.</param>
        /// <param name="userID">The user ID.</param>
        /// <param name="transactionToUse">The transaction to use.</param>
        /// <param name="postingDate">The posting date.</param>
        /// <param name="addToQueueIfRequired">if set to true, the thread will be added to the default queue of the forum the thread is in, if the forum
        /// has a default support queue and the thread isn't already in a queue.</param>
        /// <remarks>Leaves the passed in transaction open, so it doesn't commit/rollback, it just performs a set of actions inside the
        /// passed in transaction.</remarks>
        internal static void UpdateStatisticsAfterMessageInsert(int threadID, int userID, Transaction transactionToUse, DateTime postingDate, bool addToQueueIfRequired, bool subscribeToThread)
        {
            // user statistics
            UserEntity userUpdater = new UserEntity();
            // set the amountofpostings field to an expression so it will be increased with 1.
            userUpdater.Fields[(int)UserFieldIndex.AmountOfPostings].ExpressionToApply = (UserFields.AmountOfPostings + 1);
            UserCollection users = new UserCollection();
            transactionToUse.Add(users);
            users.UpdateMulti(userUpdater, (UserFields.UserID == userID));	// update directly on the DB.

            // thread statistics
            ThreadEntity threadUpdater = new ThreadEntity();
            threadUpdater.ThreadLastPostingDate = postingDate;
            threadUpdater.MarkedAsDone = false;
            ThreadCollection threads = new ThreadCollection();
            transactionToUse.Add(threads);
            threads.UpdateMulti(threadUpdater, (ThreadFields.ThreadID == threadID));

            // forum statistics. Load the forum from the DB, as we need it later on. Use a fieldcompareset predicate to fetch the forum as we don't know the
            // forumID as we haven't fetched the thread
            ForumCollection forums = new ForumCollection();
            transactionToUse.Add(forums);
            // use a fieldcompare set predicate to select the forumid based on the thread. This filter is equal to
            // WHERE ForumID == (SELECT ForumID FROM Thread WHERE ThreadID=@ThreadID)
            var forumFilter = new FieldCompareSetPredicate(
                                ForumFields.ForumID, ThreadFields.ForumID, SetOperator.Equal, (ThreadFields.ThreadID == threadID));
            forums.GetMulti(forumFilter);
            ForumEntity containingForum = null;
            if(forums.Count>0)
            {
                // forum found. There's just one.
                containingForum = forums[0];
                containingForum.ForumLastPostingDate = postingDate;
                // save the forum. Just save the collection
                forums.SaveMulti();
            }

            if(addToQueueIfRequired)
            {
                // If the thread involved isn't in a queue, place it in the default queue of the forum (if applicable)
                SupportQueueEntity containingQueue = SupportQueueGuiHelper.GetQueueOfThread(threadID, transactionToUse);
                if((containingQueue == null) && (containingForum != null) && (containingForum.DefaultSupportQueueID.HasValue))
                {
                    // not in a queue, and the forum has a default queue. Add the thread to the queue of the forum
                    SupportQueueManager.AddThreadToQueue(threadID, containingForum.DefaultSupportQueueID.Value, userID, transactionToUse);
                }
            }

            //subscribe to thread if indicated
            if(subscribeToThread)
            {
                UserManager.AddThreadToSubscriptions(threadID, userID, transactionToUse);
            }
        }
示例#16
0
 /// <summary>
 /// Deletes all messages in threads which match the passed in filter. 
 /// </summary>
 /// <param name="threadFilter">The thread filter.</param>
 /// <param name="trans">The transaction to use.</param>
 internal static void DeleteAllMessagesInThreads(PredicateExpression threadFilter, Transaction trans)
 {
     // fabricate the messagefilter, based on the passed in filter on threads. We do this by creating a FieldCompareSetPredicate:
     // WHERE Message.ThreadID IN (SELECT ThreadID FROM Thread WHERE threadFilter)
     var messageFilter = MessageFields.ThreadID.In(new QueryFactory().Create()
                                                         .Select(ThreadFields.ThreadID)
                                                         .Where(threadFilter));
     DeleteMessages(messageFilter, trans);
 }
示例#17
0
        /// <summary>
        /// Saves the given set of actionrights as the set of forum action rights for the given forum / role combination.
        /// It first removes all current action rights for that combination.
        /// </summary>
        /// <param name="actionRightIDs">List of actionrights to set of this role</param>
        /// <param name="roleID">Role to use</param>
        /// <param name="forumID">Forum to use</param>
        /// <returns>true if succeeded, false otherwise</returns>
        public static bool SaveForumActionRightsForForumRole(List<int> actionRightIDs, int roleID, int forumID)
        {
            ForumRoleForumActionRightCollection forumRightsPerRole = new ForumRoleForumActionRightCollection();
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "SaveForumActionRights");

            // add this collection to the transaction so all actions executed through this collection will be inside the transaction
            trans.Add(forumRightsPerRole);
            try
            {
                // first remove the existing rows for the role
                forumRightsPerRole.DeleteMulti((ForumRoleForumActionRightFields.RoleID == roleID).And(ForumRoleForumActionRightFields.ForumID == forumID));

                // THEN add new ones
                foreach(int actionRightID in actionRightIDs)
                {
                    ForumRoleForumActionRightEntity newForumRightPerRole = new ForumRoleForumActionRightEntity();
                    newForumRightPerRole.ActionRightID = actionRightID;
                    newForumRightPerRole.ForumID = forumID;
                    newForumRightPerRole.RoleID = roleID;
                    forumRightsPerRole.Add(newForumRightPerRole);
                }

                // save the new entities
                forumRightsPerRole.SaveMulti();

                // all done, commit transaction
                trans.Commit();
                return true;
            }
            catch
            {
                // failed, rollback transaction
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
示例#18
0
 /// <summary>
 /// Deletes all threads in the specified forum.
 /// </summary>
 /// <param name="forumFilter">The forum filter.</param>
 /// <param name="trans">The transaction to use.</param>
 internal static void DeleteAllThreadsInForum(int forumID, Transaction trans)
 {
     // fabricate the threadfilter, based on the passed in forumId. We do this by creating a FieldCompareValuePredicate:
     // WHERE Thread.ForumID = forumID
     PredicateExpression threadFilter = new PredicateExpression();
     threadFilter.Add(ThreadFields.ForumID == forumID);
     DeleteThreads(threadFilter, trans);
 }
示例#19
0
        /// <summary>
        /// Gets the support queue of the thread with the threadID specified.
        /// </summary>
        /// <param name="threadID">The thread ID.</param>
        /// <param name="trans">The transaction currently in progress. Can be null if no transaction is in progress.</param>
        /// <returns>
        /// The requested supportqueue entity, or null if the thread isn't in a support queue.
        /// </returns>
        public static SupportQueueEntity GetQueueOfThread(int threadID, Transaction trans)
        {
            // the relation supportqueue - thread is stored in a SupportQueueThread entity. Use that entity as a filter for the support queue. If
            // that entity doesn't exist, the thread isn't in a supportqueue.
            var qf = new QueryFactory();
            var q = qf.SupportQueueThread
                        .From(QueryTarget.InnerJoin(qf.SupportQueue).On(SupportQueueThreadFields.QueueID == SupportQueueFields.QueueID))
                        .Where(SupportQueueThreadFields.ThreadID == threadID);

            // use a supportqueue collection to fetch the support queue, which will contain 0 or 1 entities after the fetch
            SupportQueueCollection supportQueues = new SupportQueueCollection();
            // if a transaction has been specified, we've to add the collection to the transaction so the fetch takes place inside the same transaction so no
            // deadlocks occur on sqlserver
            if(trans != null)
            {
                trans.Add(supportQueues);
            }
            supportQueues.GetMulti(q);
            if(supportQueues.Count > 0)
            {
                // in a queue, return the instance
                return supportQueues[0];
            }
            else
            {
                // not in a queue, return null
                return null;
            }
        }
示例#20
0
 /// <summary>
 /// Inserts a new message in thread given. All exceptions are passed upwards, caller has full control over transaction.
 /// </summary>
 /// <param name="threadID">Thread wherein the new message will be placed</param>
 /// <param name="userID">User who posted this message</param>
 /// <param name="messageText">Message text</param>
 /// <param name="messageAsHTML">Message text as HTML</param>
 /// <param name="userIDIPAddress">IP address of user calling this method</param>
 /// <param name="messageAsXML">Message text as XML, which is the result of the parse action on MessageText.</param>
 /// <param name="transactionToUse">the open transaction to use for saving this message.</param>
 /// <param name="postingDate">The posting date.</param>
 /// <returns>new messageid</returns>
 private static int InsertNewMessage(int threadID, int userID, string messageText, string messageAsHTML, string userIDIPAddress, 
     string messageAsXML, Transaction transactionToUse, DateTime postingDate)
 {
     MessageEntity message = new MessageEntity();
     message.MessageText = messageText;
     message.MessageTextAsHTML = messageAsHTML;
     message.PostedByUserID = userID;
     message.PostingDate = postingDate;
     message.ThreadID = threadID;
     message.PostedFromIP = userIDIPAddress;
     message.MessageTextAsXml = messageAsXML;
     transactionToUse.Add(message);
     bool result = message.Save();
     if(result)
     {
         return message.MessageID;
     }
     else
     {
         return 0;
     }
 }
示例#21
0
        /// <summary>
        /// Creates a new thread in the given forum and places the passed in message as the first message in the thread.
        /// Caller should validate input parameters.
        /// </summary>
        /// <param name="forumID">Forum wherein the new thread will be placed</param>
        /// <param name="userID">User who started this thread</param>
        /// <param name="subject">Subject of the thread</param>
        /// <param name="messageText">First message of the thread</param>
        /// <param name="messageAsHTML">Message text as HTML</param>
        /// <param name="isSticky">Flag if the thread is sticky / pinned (true) or not (false)</param>
        /// <param name="userIDIPAddress">IP address of user calling this method</param>
        /// <param name="defaultSupportQueueID">The ID of the default support queue for this forum. If not null, the thread created will be
        /// added to the support queue with the ID specified.</param>
        /// <param name="messageID">The message ID of the new message, which is the start message in the thread.</param>
        /// <returns>ThreadID if succeeded, 0 if not.</returns>
        public static int CreateNewThreadInForum(int forumID, int userID, string subject, string messageText, string messageAsHTML, bool isSticky, 
            string userIDIPAddress, int? defaultSupportQueueID, bool subscribeToThread, out int messageID)
        {
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "NewThread");
            try
            {
                DateTime postDate = DateTime.Now;

                ThreadEntity newThread = new ThreadEntity();
                newThread.ForumID = forumID;
                newThread.IsClosed = false;
                newThread.IsSticky = isSticky;
                newThread.StartedByUserID = userID;
                newThread.Subject = subject;
                newThread.ThreadLastPostingDate = postDate;

                if(defaultSupportQueueID.HasValue)
                {
                    // a support queue has been specified as the default support queue for this forum. Add the new thread to this support queue.
                    SupportQueueThreadEntity supportQueueThread = new SupportQueueThreadEntity();
                    supportQueueThread.QueueID = defaultSupportQueueID.Value;
                    supportQueueThread.PlacedInQueueByUserID = userID;
                    supportQueueThread.PlacedInQueueOn = DateTime.Now;
                    // assign the Thread property to the newly created thread entity, so this supportqueuethreadentity will be part of the graph
                    // of objects which will be saved.
                    supportQueueThread.Thread = newThread;
                }

                DateTime postingDate = DateTime.Now;
                MessageEntity newMessage = new MessageEntity();
                newMessage.MessageText = messageText;
                newMessage.MessageTextAsHTML = messageAsHTML;
                newMessage.PostedByUserID = userID;
                newMessage.PostingDate = postingDate;
                newMessage.PostedFromIP = userIDIPAddress;
                newMessage.Thread = newThread;

                // add the newMessage entity to the transaction object. All entities saved recursively will be added automatically
                trans.Add(newMessage);

                // save the complete graph
                newMessage.Save(true);

                messageID = newMessage.MessageID;
                int threadID = newMessage.ThreadID;

                // update thread statistics, this is the task for the message manager, and we pass the transaction object so the actions will run in
                // the same transaction.
                MessageManager.UpdateStatisticsAfterMessageInsert(threadID, userID, trans, postingDate, false, subscribeToThread);

                trans.Commit();
                return newThread.ThreadID;
            }
            catch(Exception)
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
示例#22
0
        /// <summary>
        /// Deletes the support queue with the ID specified.
        /// </summary>
        /// <param name="queueID">The queue ID of the queue to delete.</param>
        /// <returns>true if succeeded, false otherwise</returns>
        /// <remarks>All threads in the queue are automatically de-queued and not in a queue anymore. The Default support queue
        /// for forums which have this queue as the default support queue is reset to null.</remarks>
        public static bool DeleteSupportQueue(int queueID)
        {
            // we'll do several actions in one atomic transaction, so start a transaction first.
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "DeleteSupportQ");

            try
            {
                // first reset all the FKs in Forum to NULL if they point to this queue.
                ForumEntity forumUpdater = new ForumEntity();
                // set the field to NULL. This is a nullable field, so we can just set the field to 'null', thanks to nullable types.
                forumUpdater.DefaultSupportQueueID = null;
                // update the entities directly in the db, use a forum collection for that
                ForumCollection forums = new ForumCollection();
                trans.Add(forums);
                // specify a filter that only the forums which have this queue as the default queue are updated and have their FK field set to NULL.
                forums.UpdateMulti(forumUpdater, (ForumFields.DefaultSupportQueueID == queueID));

                // delete all SupportQueueThread entities which refer to this queue. This will make all threads which are in this queue become queue-less.
                SupportQueueThreadCollection supportQueueThreads = new SupportQueueThreadCollection();
                trans.Add(supportQueueThreads);
                // delete them directly from the db.
                supportQueueThreads.DeleteMulti((SupportQueueThreadFields.QueueID == queueID));

                // it's now time to delete the actual supportqueue entity.
                SupportQueueCollection supportQueues = new SupportQueueCollection();
                trans.Add(supportQueues);
                // delete it directly from the db.
                int numberOfQueuesDeleted = supportQueues.DeleteMulti((SupportQueueFields.QueueID == queueID));

                // done so commit the transaction.
                trans.Commit();
                return (numberOfQueuesDeleted > 0);
            }
            catch
            {
                // first roll back the transaction
                trans.Rollback();
                // then bubble up the exception
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
示例#23
0
        /// <summary>
        /// Deletes the given forum from the system, including <b>all</b> threads in this forum and messages in those threads.
        /// </summary>
        /// <param name="forumID">Forum ID.</param>
        /// <returns>True if succeeded, false otherwise</returns>
        public static bool DeleteForum(int forumID)
        {
            // first all threads in this forum have to be removed, then this forum should be removed. Do this in one transaction.
            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "DeleteForum");
            try
            {
                PredicateExpression forumFilter = new PredicateExpression();
                forumFilter.Add((ForumFields.ForumID == forumID));

                // remove all threads in this forum
                ThreadManager.DeleteAllThreadsInForum(forumID, trans);

                // remove all ForumRoleForumActionRight entities for this forum
                ForumRoleForumActionRightCollection forumRoleActionRights = new ForumRoleForumActionRightCollection();
                trans.Add(forumRoleActionRights);
                forumRoleActionRights.DeleteMulti(ForumRoleForumActionRightFields.ForumID == forumID);

                // remove the forum entity. do this by executing a direct delete statement on the database
                ForumCollection forums = new ForumCollection();
                trans.Add(forums);
                forums.DeleteMulti(forumFilter);
                trans.Commit();
                return true;
            }
            catch
            {
                // exception occured, rollback
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }
示例#24
0
 /// <summary>
 /// Subscribes the user specified to the thread specified for notifications. A transaction can be specified to save the information inside the
 /// transaction specified. If the user is already subscribed to this thread, nothing is done
 /// </summary>
 /// <param name="threadID">The thread ID.</param>
 /// <param name="userID">The user ID.</param>
 /// <param name="transactionToUse">The transaction to use. If no transaction is specified, no transaction is created</param>
 /// <returns></returns>
 public static bool AddThreadToSubscriptions(int threadID, int userID, Transaction transactionToUse)
 {
     // check if this user is already subscribed to this thread. If not, add a new subscription.
     ThreadSubscriptionEntity subscription = ThreadGuiHelper.GetThreadSubscription(threadID, userID, transactionToUse);
     if(subscription == null)
     {
         // user isn't yet subscribed, add the subscription
         subscription = new ThreadSubscriptionEntity();
         subscription.UserID = userID;
         subscription.ThreadID = threadID;
         if(transactionToUse != null)
         {
             transactionToUse.Add(subscription);
         }
         return subscription.Save();
     }
     // already subscribed, no-op.
     return true;
 }
示例#25
0
        /// <summary>
        /// Deletes the given role from the system.
        /// </summary>
        /// <param name="roleID">ID of role to delete</param>
        /// <returns>true if succeeded, false otherwise</returns>
        public static bool DeleteRole(int roleID)
        {
            RoleEntity toDelete = SecurityGuiHelper.GetRole(roleID);
            if(toDelete == null)
            {
                // not found
                return false;
            }

            Transaction trans = new Transaction(IsolationLevel.ReadCommitted, "DeleteRole");

            try
            {
                // remove the role - forum - action right entities
                ForumRoleForumActionRightCollection forumRoleActionRights = new ForumRoleForumActionRightCollection();
                trans.Add(forumRoleActionRights);
                forumRoleActionRights.DeleteMulti(ForumRoleForumActionRightFields.RoleID == roleID);

                // Remove role-audit action entities
                RoleAuditActionCollection roleAuditActions = new RoleAuditActionCollection();
                trans.Add(roleAuditActions);
                roleAuditActions.DeleteMulti(RoleAuditActionFields.RoleID == roleID);

                // remove Role - systemright entities
                RoleSystemActionRightCollection roleSystemRights = new RoleSystemActionRightCollection();
                trans.Add(roleSystemRights);
                roleSystemRights.DeleteMulti(RoleSystemActionRightFields.RoleID == roleID);

                // remove Role - user entities
                RoleUserCollection roleUsers = new RoleUserCollection();
                trans.Add(roleUsers);
                roleUsers.DeleteMulti(RoleUserFields.RoleID == roleID);

                // delete the actual role
                trans.Add(toDelete);
                toDelete.Delete();
                trans.Commit();
                return true;
            }
            catch
            {
                // error occured, rollback
                trans.Rollback();
                throw;
            }
            finally
            {
                trans.Dispose();
            }
        }