예제 #1
0
        public static ControlHistory ControlLetter(string board_id, string discussion_id, string letter_id, string delta_flags)
        {
            string partition_key = SandId.CombineId(board_id, discussion_id);

            // todo: select only needed properties.
            TableResult        result = Warehouse.DiscussionLoadTable.Execute(TableOperation.Retrieve(partition_key, letter_id));
            DynamicTableEntity entity = (DynamicTableEntity)result.Result;

            // permanent deleting twice is not blocked.
            GroupStore.CheckControlRight(board_id, discussion_id, letter_id, ref delta_flags, entity);

            int ec = RevisionStore.IncreaseEditCount(entity);

            RevisionStore.CreateRevision(entity, board_id, discussion_id, letter_id, ec);

            int prev_report_cnt = SandFlags.GetNumber(entity.GetFlags(), SandFlags.MT_REPORT);

            LetterConverter.ModifyLetterFlags(entity, null, delta_flags);

            int new_report_cnt = SandFlags.GetNumber(entity.GetFlags(), SandFlags.MT_REPORT);

            Warehouse.DiscussionLoadTable.Execute(TableOperation.Replace(entity));                  // Throws StorageException ((412) Precondition Failed) if the entity is modified in between.

            Warehouse.DiscussionLoadPond.Notify(board_id, discussion_id);
            Warehouse.DiscussionSummaryPond.Notify(board_id, discussion_id);
            HttpResponse.RemoveOutputCacheItem("/discussionload/" + board_id + "/" + discussion_id);

            return(new ControlHistory {
                ReportCount = new_report_cnt - prev_report_cnt
            });
        }
예제 #2
0
        public static bool HasChairOwner(string board_id)
        {
            string role_name = SandId.CombineId(board_id, ChairOwnerGroupName);

            return(false);
            //2015-11-6 remove sql db. //return Roles.GetUsersInRole(role_name).Length > 0;
        }
예제 #3
0
        public static void EditLetter(string board_id, string discussion_id, string letter_id, string editor, string words,
                                      string delta_flags, HttpFileCollectionBase files)
        {
            string partition_key = SandId.CombineId(board_id, discussion_id);

            TableResult        result = Warehouse.DiscussionLoadTable.Execute(TableOperation.Retrieve(partition_key, letter_id));
            DynamicTableEntity entity = (DynamicTableEntity)result.Result;

            GroupStore.CheckEditRight(board_id, discussion_id, entity);

            HashSet <string> files_set = new HashSet <string>();

            words = processUploadFiles(words, files, files_set);
            words = processWords(words);
            claimFiles(words, SandId.CombineId(board_id, discussion_id, letter_id), files_set);

            // if (entity != null)		// let it throw null reference exception.
            int ec = RevisionStore.IncreaseEditCount(entity);

            RevisionStore.CreateRevision(entity, board_id, discussion_id, letter_id, ec);

            LetterConverter.EditLetterEntity(entity, editor, words, delta_flags, board_id, discussion_id);

            Warehouse.DiscussionLoadTable.Execute(TableOperation.Replace(entity));                  // Throws StorageException ((412) Precondition Failed) if the entity is modified in between.

            Warehouse.DiscussionLoadPond.Notify(board_id, discussion_id);
            Warehouse.DiscussionSummaryPond.Notify(board_id, discussion_id);

            HttpResponse.RemoveOutputCacheItem("/discussionload/" + board_id + "/" + discussion_id);
        }
예제 #4
0
        private static void upgradeTemporalAddBoardId()
        {
            string pkFilter = TableQuery.CombineFilters(
                TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.GreaterThanOrEqual, "bldr1.b0"),
                TableOperators.And,
                TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.LessThanOrEqual, "bldr1.b999"));

            TableQuery query = new TableQuery().Where(pkFilter);

            foreach (DynamicTableEntity entity in Warehouse.TemporalTable.ExecuteQuery(query))
            {
                string board_id;
                SandId.SplitId(entity.PartitionKey, out board_id);

                string[] parts = entity["part0"].StringValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                StringBuilder builder = new StringBuilder();

                foreach (string part in parts)
                {
                    builder.AppendFormat("{0}.{1},", board_id, part);
                }
                Warehouse.TemporalTable.SaveLongString(SandId.CombineId("bldr2", board_id), "segment0", builder.ToString());
            }
        }
예제 #5
0
        private static string /*letter id*/ CreateLetterInternal(string board_id, string discussion_id,
                                                                 string creator, string words, Subtype subtype, string delta_flags)
        {
            string partition_key = SandId.CombineId(board_id, discussion_id);

            if (NextIdStore.GetLastId(Warehouse.DiscussionLoadTable, partition_key) >= HeartsConfiguration.MAX_NUM_OF_LETTERS_IN_A_DISCUSSION)
            {
                Util.ThrowBadRequestException("留言數超過上限(" + HeartsConfiguration.MAX_NUM_OF_LETTERS_IN_A_DISCUSSION + ")則。");
            }

            int    next_id   = NextIdStore.Next(Warehouse.DiscussionLoadTable, partition_key);                  // null reference exception for nonexistent board id.
            string letter_id = SandId.MakeLetterId(next_id);
            // if exception is thrown after getting id, the id is lost.

            DynamicTableEntity entity = new DynamicTableEntity(partition_key, letter_id);

            LetterConverter.CreateLetterEntity(entity, creator, words, subtype, delta_flags, board_id, discussion_id);
            //
            Warehouse.DiscussionLoadPond.Get(board_id, discussion_id).AddLetter(entity);
            Warehouse.DiscussionSummaryPond.Get(board_id, discussion_id).AddLetter(entity);

            Warehouse.DiscussionLoadTable.Execute(TableOperation.Insert(entity));
            //
            return(letter_id);
        }
예제 #6
0
        public static void SetBoardSetting(string board_id, string board_name)
        {
            TableResult        result = Warehouse.BoardListTable.Execute(TableOperation.Retrieve(board_id, EMPTY_ROW_KEY));
            DynamicTableEntity entity = (DynamicTableEntity)result.Result;

            // if (entity != null)		// let it throw null reference exception.
            int ec = RevisionStore.IncreaseEditCount(entity);

            string partition_key = SandId.CombineId(Warehouse.BoardListTable.Name, board_id);

            RevisionStore.CreateHistory(entity, partition_key, ec, "boardname");

            CreatorConverter.FillEntity(entity, CreatorConverter.Status.Editor, null);
            entity["boardname"].StringValue = board_name;

            Warehouse.BoardListTable.Execute(TableOperation.Replace(entity));                  // Throws StorageException ((412) Precondition Failed) if the entity is modified in between.
            //don't work for child action. //HttpResponse.RemoveOutputCacheItem("/boardlist");

            //List<string> selection_list = SelectionBoardListResult.GetSelectionList(board_id);

            //if (selection_list != null)
            //foreach (string selection_id in selection_list)
            //don't work for child action. //HttpResponse.RemoveOutputCacheItem("/discussionlist/" + selection_id);

            Warehouse.BsMapPond.Notify();
            Warehouse.DiscussionListPond.Notify(board_id);
            Warehouse.BoardSettingPond.Notify(board_id);
        }
예제 #7
0
        public static bool IsCurrentUserDiscussionCreator(string board_id, string discussion_id)
        {
            string             partition_key = SandId.CombineId(board_id, discussion_id);
            TableResult        result        = Warehouse.DiscussionLoadTable.Execute(TableOperation.Retrieve(partition_key, SandId.HEADING_LETTER_ID));
            DynamicTableEntity entity        = (DynamicTableEntity)result.Result;

            return(CreatorConverter.IsCurrentUserCreator(entity));
        }
예제 #8
0
        public static void Vote(string board_id, string discussion_id, string letter_id, string meta_title)
        {
            string partition_key = SandId.CombineId(board_id, discussion_id, letter_id);
            string row_key       = SandId.CombineId(meta_title, "uid", WebSecurity.CurrentUserId.ToString());                   // CurrentUserId is -1 if not logged in.

            DynamicTableEntity entity = new DynamicTableEntity(partition_key, row_key);

            Warehouse.VoteBookTable.Execute(TableOperation.Insert(entity));                     // (409) 衝突。 if already exists.
        }
예제 #9
0
        public void Notify(string board_id, string discussion_id)
        {
            string             key = SandId.CombineId("discussionload1", board_id, discussion_id);
            DiscussionLoadRoll obj = (DiscussionLoadRoll)HttpRuntime.Cache.Remove(key);

            if (obj != null)
            {
                insertNew(key, board_id, discussion_id);
            }
        }
예제 #10
0
        public void Notify(string board_id)
        {
            string       key = SandId.CombineId("boardsetting1", board_id);
            BoardSetting obj = (BoardSetting)HttpRuntime.Cache.Remove(key);

            if (obj != null)
            {
                insertNew(key, obj.BoardId);
            }
        }
예제 #11
0
        public void Notify(string board_id)
        {
            string         key = SandId.CombineId("dlpond1", board_id);
            DiscussionList obj = (DiscussionList)HttpRuntime.Cache.Remove(key);

            if (obj != null)
            {
                insertNew(key, obj.BoardId);
            }
        }
예제 #12
0
        public static bool IsInsider(string board_id)
        {
            if (IsBoardOwner(board_id))
            {
                return(true);
            }
            string role_name = SandId.CombineId(board_id, InsiderGroupName);

            return(HttpContext.Current.User.IsInRole(role_name));
        }
예제 #13
0
        public static string[] GetBoardGroup(string board_id, string group_id, out int[] user_ids)
        {
            string role_name = SandId.CombineId(board_id, group_id);

            string[] user_names = Roles.GetUsersInRole(role_name);                      // zero length array for nonexistent role.

            user_ids = UserNamesToUserIds(user_names);

            return(user_names);
        }
예제 #14
0
        public static void CreateRevision(DynamicTableEntity letter_entity, string board_id, string discussion_id,
                                          string letter_id, int version)
        {
            string partition_key = SandId.CombineId(board_id, discussion_id, letter_id);

            DynamicTableEntity entity = new DynamicTableEntity(partition_key, SandId.MakeRevisionId(version));

            LetterConverter.CopyLetterRevision(letter_entity, entity, version);

            Warehouse.RevisionTable.Execute(TableOperation.Insert(entity));                     // If an exception is thrown after revision created but before edit count in letter entity is updated, next time edit will fail because the revision already exists.
        }
예제 #15
0
        public void Notify(string board_id, string discussion_id)
        {
            string            key = SandId.CombineId("summary1", board_id, discussion_id);
            DiscussionSummary obj = (DiscussionSummary)HttpRuntime.Cache.Remove(key);

            if (obj != null)
            {
                insertNew(key, obj.BoardId, obj.DiscussionId);
            }
            // todo: remove only if the edited letter is in the DiscussionSummary.
        }
예제 #16
0
        public static void GetLastLetters(string board_id, string discussion_id, int cnt, Action <DynamicTableEntity> act)
        {
            string partition_key = SandId.CombineId(board_id, discussion_id);

            int last_id = NextIdStore.GetLastId(Warehouse.DiscussionLoadTable, partition_key);

            if (last_id != -1)
            {
                Warehouse.DiscussionLoadTable.EnumerateRowRange(partition_key, SandId.LETTER_ID_PREFIX, last_id - cnt + 1, cnt, act);
            }
        }
예제 #17
0
        private BubblingRoll get(string id, int list_size)
        {
            string key = SandId.CombineId(BubblingRoll.PAR_KEY_PREFIX, id);

            BubblingRoll obj = (BubblingRoll)HttpRuntime.Cache.Get(key);

            if (obj == null)
            {
                obj = insertNew(key, id, list_size);
            }

            return(obj);
        }
예제 #18
0
        public string Get(string board_id, string discussion_id, bool insert_if_not_exist)
        {
            string key = SandId.CombineId("discussionkey1", board_id, discussion_id);

            string obj = (string)HttpRuntime.Cache.Get(key);

            if (obj == null)
            {
                obj = insertNew(key, board_id, discussion_id, insert_if_not_exist);
            }

            return(obj);
        }
예제 #19
0
        public DiscussionLoadRoll Get(string board_id, string discussion_id)
        {
            string key = SandId.CombineId("discussionload1", board_id, discussion_id);

            DiscussionLoadRoll obj = (DiscussionLoadRoll)HttpRuntime.Cache.Get(key);

            if (obj == null)
            {
                obj = insertNew(key, board_id, discussion_id);
            }

            return(obj);
        }
예제 #20
0
        public DiscussionList Get(string board_id)
        {
            string key = SandId.CombineId("dlpond1", board_id);

            DiscussionList obj = (DiscussionList)HttpRuntime.Cache.Get(key);

            if (obj == null)
            {
                obj = insertNew(key, board_id);
            }

            return(obj);
        }
예제 #21
0
        public BoardSetting Get(string board_id)
        {
            string key = SandId.CombineId("boardsetting1", board_id);

            BoardSetting obj = (BoardSetting)HttpRuntime.Cache.Get(key);

            if (obj == null)
            {
                obj = insertNew(key, board_id);
            }

            return(obj);
        }
예제 #22
0
        public DiscussionSummary Get(string board_id, string discussion_id)
        {
            string key = SandId.CombineId("summary1", board_id, discussion_id);

            DiscussionSummary obj = (DiscussionSummary)HttpRuntime.Cache.Get(key);

            if (obj == null)
            {
                obj = insertNew(key, board_id, discussion_id);
            }

            return(obj);
        }
예제 #23
0
        public static void SetBoardFlags(string board_id, string delta_flags)
        {
            TableResult        result = Warehouse.BoardListTable.Execute(TableOperation.Retrieve(board_id, EMPTY_ROW_KEY));
            DynamicTableEntity entity = (DynamicTableEntity)result.Result;

            int ec = RevisionStore.IncreaseEditCount(entity);

            string partition_key = SandId.CombineId(Warehouse.BoardListTable.Name, board_id);

            RevisionStore.CreateHistory(entity, partition_key, ec, "flags2");

            CreatorConverter.FillEntity(entity, CreatorConverter.Status.Editor, null);
            entity.OperateFlags(new FlagMergeOperation(delta_flags));

            Warehouse.BoardListTable.Execute(TableOperation.Replace(entity));                  // Throws StorageException ((412) Precondition Failed) if the entity is modified in between.

            Warehouse.BoardSettingPond.Notify(board_id);
        }
예제 #24
0
        public void Save()
        {
            // nodes overwrite each other.
            if (this.modified)
            {
                string serialized;
                lock (this.list)
                    serialized = Util.Serialize(this.list);

                // different nodes override each other.
                string key = SandId.CombineId(PAR_KEY_PREFIX, this.Id);
                Warehouse.TemporalTable.SaveLongString(key, "segment0", serialized);

                // if Put() is called in another thread here, the modified flag is cleared wrongly.

                this.modified = false;
            }
        }
예제 #25
0
        public static bool VoteLetter(string board_id, string discussion_id, string letter_id, string delta_flags)
        {
            try
            {
                SandFlags.SplitFlags(delta_flags, (meta_title, meta_value) =>
                {
                    VoteBookStore.Vote(board_id, discussion_id, letter_id, meta_title);
                });
            }
            catch (StorageException ex)
            {
                return(false);
            }

            string partition_key = SandId.CombineId(board_id, discussion_id);

            string pkFilter       = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partition_key);
            string rkFilter       = TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, letter_id);
            string combinedFilter = TableQuery.CombineFilters(pkFilter, TableOperators.And, rkFilter);

            TableQuery query = new TableQuery().Where(combinedFilter).Select(new string[] { "flags2" });

            foreach (DynamicTableEntity entity in Warehouse.DiscussionLoadTable.ExecuteQuery(query))
            {
                entity.OperateFlags(new FlagOperation
                {
                    type       = FlagOperation.Type.AddMultiple,
                    DeltaFlags = delta_flags,
                });

                if (entity.Properties.Count == 0)                               // TableOperation.Merge cannot be used to remove property. if "flags" becomes empty, it will be removed from properties and the merge will have no effect.
                {
                    throw new ProgramLogicException();
                }

                Warehouse.DiscussionLoadTable.Execute(TableOperation.Merge(entity));
            }
            Warehouse.DiscussionLoadPond.Notify(board_id, discussion_id);
            Warehouse.DiscussionSummaryPond.Notify(board_id, discussion_id);
            HttpResponse.RemoveOutputCacheItem("/discussionload/" + board_id + "/" + discussion_id);
            // Cache of ViewDiscussion is not removed so may serve old version.
            return(true);
        }
예제 #26
0
        public BubblingRoll(string id, int list_size)
        {
            this.ListSize = list_size;
            this.Id       = id;
#if OLD
            DiscussionListStore.GetLastDiscussions(board_id, LIST_SIZE, entity => ll.AddFirst(entity.RowKey));
#else
            string key        = SandId.CombineId(PAR_KEY_PREFIX, id);
            string serialized = Warehouse.TemporalTable.LoadLongString(key, "segment0");

            if (serialized != null)
            {
                this.list = Util.DeserializeToLinkedList(serialized);
            }
            else
            {
                this.list = new LinkedList <string>();
            }
#endif
        }
예제 #27
0
        public void Put(string board_id, string discussion_id)
        {
            string combined_id = SandId.CombineId(board_id, discussion_id);

            Get(board_id).Put(combined_id);

            if (!Warehouse.BoardSettingPond.Get(board_id).LowKey)
            {
                Get(null).Put(combined_id);
            }
            //
            List <string> selection_list = Warehouse.BsMapPond.Get().GetSelectionList(board_id);

            if (selection_list != null)
            {
                foreach (string selection_id in selection_list)
                {
                    Get(selection_id).Put(combined_id);
                }
            }
        }
예제 #28
0
        public DiscussionLoadRoll(string board_id, string discussion_id)
        {
            this.OgImages = new List <string>();

            StringWriter writer = new StringWriter();

            string partition_key = SandId.CombineId(board_id, discussion_id);

            TableQuery query = new TableQuery().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partition_key));

            foreach (DynamicTableEntity entity in Warehouse.DiscussionLoadTable.ExecuteQuery(query))
            {
                if (entity.RowKey[0] != SandId.SPECIAL_KEY_PREFIX /* &&
                                                                   * !entity.IsPermanentlyDeleted()*/)
                {
                    addLetter(writer, entity);
                }
            }
            this.Output           = writer.ToString();
            this.LastModifiedTime = DateTime.Now;
        }
예제 #29
0
        public static void UpdateGroup(string board_id, string group_id, string add_users, string remove_users)
        {
            string role_name = SandId.CombineId(board_id, group_id);

            if (!Roles.RoleExists(role_name))
            {
                Roles.CreateRole(role_name);
            }

            string[] ru = remove_users.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            if (ru.Length > 0)
            {
                Roles.RemoveUsersFromRole(ru, role_name);
            }

            string[] au = add_users.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            int cnt = Roles.GetUsersInRole(role_name).Length;

            int limit = group_id == GroupStore.ChairOwnerGroupName ? 1 : HeartsConfiguration.MAX_NUM_OF_USERS_IN_A_GROUP;

            if (cnt + au.Length > limit)
            {
                Util.ThrowBadRequestException("使用者數量超過" + limit + "個。");
            }

            if (au.Length > 0)
            {
                Roles.AddUsersToRole(au, role_name);
            }

            Warehouse.BoardSettingPond.Notify(board_id);

            string month = Util.DateTimeToString(DateTime.Now, 5);

            RevisionStore.CreateActivity(SandId.CombineId(ActivityType.UpdateGroup.ToString(), board_id, month),
                                         new string[] { "group_id", "add_users", "remove_users" },
                                         new object[] { group_id, add_users, remove_users });
        }
예제 #30
0
        public static string /*letter id*/ CreateLetter(string board_id, string discussion_id, string creator, string words,
                                                        Subtype subtype, string delta_flags, HttpFileCollectionBase files)
        {
            HashSet <string> files_set = new HashSet <string>();

            if (files != null)
            {
                words = processUploadFiles(words, files, files_set);
            }
            words = processWords(words);

            string letter_id = null;

            string[] split_arr = Util.SplitLongWords(words);
            if (split_arr.Length == 0)
            {
                split_arr = new string[] { string.Empty }
            }
            ;

            for (int i = 0; i < split_arr.Length; i++)
            {
                string lid = CreateLetterInternal(board_id, discussion_id, creator, split_arr[i], subtype, delta_flags);
                // if subject is split into multiple segments, all will have subtype "s" and only the first segment gets into summary.

                if (i == 0)
                {
                    letter_id = lid;
                }

                claimFiles(split_arr[i], SandId.CombineId(board_id, discussion_id, lid), files_set);
            }
            HttpResponse.RemoveOutputCacheItem("/discussionload/" + board_id + "/" + discussion_id);
            if (subtype != Subtype.d)
            {
                Warehouse.HotDiscussionRollPond.Put(board_id, discussion_id);
            }

            return(letter_id);
        }