From 7904c55b411519172a9773d2532591acc35425aa Mon Sep 17 00:00:00 2001 From: inga-lovinde <52715130+inga-lovinde@users.noreply.github.com> Date: Sun, 12 Sep 2010 15:23:10 +0000 Subject: [PATCH] Auto restrictions implemented --- Builder/IISMainHandler/build.txt | 2 +- Common/Common.csproj | 1 + Common/TableManager.cs | 1 + Common/actions/ChangeSet.cs | 1 + Common/dataobjects/Board.cs | 19 ++ Common/dataobjects/Post.cs | 4 + Common/dataobjects/PostLayer.cs | 22 +- Common/dataobjects/Punishment.cs | 31 +++ Common/dataobjects/Restriction.cs | 237 ++++++++++++++++++ Common/dataobjects/User.cs | 2 + .../handlers/response/CreateThreadHandler.cs | 4 +- .../handlers/response/EditHandler.cs | 4 +- .../handlers/response/ReplyHandler.cs | 4 +- templates/Full/NewThread.xslt | 2 +- templates/Full/PostEdit.xslt | 2 +- templates/Full/PostPunish.xslt | 2 +- templates/Full/PostReply.xslt | 2 +- templates/Full/elems/TextEditor.xslt | 27 +- templates/Lite/NewThread.xslt | 4 +- templates/Lite/PostEdit.xslt | 2 +- templates/Lite/PostPunish.xslt | 2 +- templates/Lite/PostReply.xslt | 2 +- templates/Lite/elems/TextEditor.xslt | 27 +- 23 files changed, 374 insertions(+), 30 deletions(-) create mode 100644 Common/dataobjects/Restriction.cs diff --git a/Builder/IISMainHandler/build.txt b/Builder/IISMainHandler/build.txt index 7ff9fa9..fb9a769 100644 --- a/Builder/IISMainHandler/build.txt +++ b/Builder/IISMainHandler/build.txt @@ -1 +1 @@ -1227 \ No newline at end of file +1233 \ No newline at end of file diff --git a/Common/Common.csproj b/Common/Common.csproj index b79817d..cb37d15 100644 --- a/Common/Common.csproj +++ b/Common/Common.csproj @@ -108,6 +108,7 @@ + diff --git a/Common/TableManager.cs b/Common/TableManager.cs index 2e3636a..3979455 100644 --- a/Common/TableManager.cs +++ b/Common/TableManager.cs @@ -26,6 +26,7 @@ namespace FLocal.Common { dataobjects.PunishmentLayerChange.TableSpec.instance, dataobjects.PunishmentTransfer.TableSpec.instance, dataobjects.PunishmentType.TableSpec.instance, + dataobjects.Restriction.TableSpec.instance, dataobjects.QuickLink.TableSpec.instance, dataobjects.Revision.TableSpec.instance, dataobjects.Session.TableSpec.instance, diff --git a/Common/actions/ChangeSet.cs b/Common/actions/ChangeSet.cs index 740f030..ce40aee 100644 --- a/Common/actions/ChangeSet.cs +++ b/Common/actions/ChangeSet.cs @@ -39,6 +39,7 @@ namespace FLocal.Common.actions { dataobjects.Punishment.TableSpec.TABLE, dataobjects.PunishmentTransfer.TableSpec.TABLE, dataobjects.PunishmentLayerChange.TableSpec.TABLE, + dataobjects.Restriction.TableSpec.TABLE, dataobjects.TexImage.TableSpec.TABLE, dataobjects.Session.TableSpec.TABLE, } diff --git a/Common/dataobjects/Board.cs b/Common/dataobjects/Board.cs index 62ad2bf..7b470ec 100644 --- a/Common/dataobjects/Board.cs +++ b/Common/dataobjects/Board.cs @@ -435,5 +435,24 @@ namespace FLocal.Common.dataobjects { } } + public XElement exportLayersInfoForUser(UserContext context) { + Dictionary restrictionData = new Dictionary(); + if(context.account != null) { + restrictionData = Restriction.GetRestrictionData(context.account.user, this); + } + return new XElement("layers", + from layer in PostLayer.allLayers + select layer.exportToXml( + context, + new XElement("isRestricted", + (restrictionData.ContainsKey(layer.id) && restrictionData[layer.id].CompareTo(DateTime.Now) >= 0).ToPlainString() + ), + new XElement("restrictionExpires", + restrictionData.ContainsKey(layer.id) ? restrictionData[layer.id].ToXml() : null + ) + ) + ); + } + } } diff --git a/Common/dataobjects/Post.cs b/Common/dataobjects/Post.cs index 3da57e2..a8e0c9a 100644 --- a/Common/dataobjects/Post.cs +++ b/Common/dataobjects/Post.cs @@ -608,6 +608,10 @@ namespace FLocal.Common.dataobjects { newMessage.conversation.markAsRead(account, newMessage, newMessage); } + HashSet punishmentsBoards = new HashSet(from punishment in this.punishments select punishment.originalBoardId); + foreach(int boardId in punishmentsBoards) { + Restriction.RecalculateRestrictions(Board.LoadById(boardId), this.poster); + } } } } diff --git a/Common/dataobjects/PostLayer.cs b/Common/dataobjects/PostLayer.cs index 45b4fd7..8571999 100644 --- a/Common/dataobjects/PostLayer.cs +++ b/Common/dataobjects/PostLayer.cs @@ -19,6 +19,7 @@ namespace FLocal.Common.dataobjects { public const string TABLE = "Layers"; public const string FIELD_ID = "Id"; public const string FIELD_NAME = "Name"; + public const string FIELD_MAXPUNISHMENTS = "MaxPunishments"; public static readonly TableSpec instance = new TableSpec(); public string name { get { return TABLE; } } public string idName { get { return FIELD_ID; } } @@ -35,8 +36,17 @@ namespace FLocal.Common.dataobjects { } } + private int? _maxPunishments; + public int? maxPunishments { + get { + this.LoadIfNotLoaded(); + return this._maxPunishments; + } + } + protected override void doFromHash(Dictionary data) { this._name = data[TableSpec.FIELD_NAME]; + this._maxPunishments = Util.ParseInt(data[TableSpec.FIELD_MAXPUNISHMENTS]); } private static readonly object allLayers_Locker = new object(); @@ -46,11 +56,11 @@ namespace FLocal.Common.dataobjects { from id in Cache>.instance.get( allLayers_Locker, () => { - IEnumerable ids = from stringId in Config.instance.mainConnection.LoadIdsByConditions( + IEnumerable ids = (from stringId in Config.instance.mainConnection.LoadIdsByConditions( TableSpec.instance, new FLocal.Core.DB.conditions.EmptyCondition(), Diapasone.unlimited - ) select int.Parse(stringId); + ) select int.Parse(stringId)).ToList(); PostLayer.LoadByIds(ids); return ids; } @@ -64,11 +74,15 @@ namespace FLocal.Common.dataobjects { Cache>.instance.delete(allLayers_Locker); } - public XElement exportToXml(UserContext context) { - return new XElement("layer", + public XElement exportToXml(UserContext context, params XElement[] additional) { + XElement result = new XElement("layer", new XElement("id", this.id), new XElement("name", this.name) ); + if(additional.Length > 0) { + result.Add(additional); + } + return result; } } diff --git a/Common/dataobjects/Punishment.cs b/Common/dataobjects/Punishment.cs index 56eb7ec..fab6666 100644 --- a/Common/dataobjects/Punishment.cs +++ b/Common/dataobjects/Punishment.cs @@ -185,5 +185,36 @@ namespace FLocal.Common.dataobjects { ); } + public static IEnumerable getEffectivePunishments(User user, Board board) { + return + from stringId in Config.instance.mainConnection.LoadIdsByConditions( + TableSpec.instance, + new ComplexCondition( + ConditionsJoinType.AND, + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_OWNERID), + ComparisonType.EQUAL, + user.id.ToString() + ), + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_ORIGINALBOARDID), + ComparisonType.EQUAL, + board.id.ToString() + ), + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_ISWITHDRAWED), + ComparisonType.EQUAL, + "0" + ), + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_EXPIRES), + ComparisonType.GREATEROREQUAL, + DateTime.Now.ToUTCString() + ) + ), + Diapasone.unlimited + ) select Punishment.LoadById(int.Parse(stringId)); + } + } } diff --git a/Common/dataobjects/Restriction.cs b/Common/dataobjects/Restriction.cs new file mode 100644 index 0000000..b7bd023 --- /dev/null +++ b/Common/dataobjects/Restriction.cs @@ -0,0 +1,237 @@ +п»їusing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using FLocal.Core; +using FLocal.Core.DB; +using FLocal.Core.DB.conditions; +using FLocal.Common.actions; + +namespace FLocal.Common.dataobjects { + public class Restriction : SqlObject { + + public class TableSpec : ISqlObjectTableSpec { + public const string TABLE = "Restrictions"; + public const string FIELD_ID = "Id"; + public const string FIELD_USERID = "UserId"; + public const string FIELD_BOARDID = "BoardId"; + public const string FIELD_DATA = "Data"; + public static readonly TableSpec instance = new TableSpec(); + public string name { get { return TABLE; } } + public string idName { get { return FIELD_ID; } } + public void refreshSqlObject(int id) { + Refresh(id); + var restriction = Restriction.LoadById(id); + byUser_Recalculate(restriction.userId); + byBoard_Recalculate(restriction.boardId); + lock(restrictionId_cache) { + if(!restrictionId_cache.ContainsKey(restriction.userId)) restrictionId_cache[restriction.userId] = new Dictionary(); + restrictionId_cache[restriction.userId][restriction.boardId] = restriction.id; + } + } + } + + protected override ISqlObjectTableSpec table { get { return TableSpec.instance; } } + + private int _userId; + public int userId { + get { + this.LoadIfNotLoaded(); + return this._userId; + } + } + public User user { + get { + return User.LoadById(this.userId); + } + } + + private int _boardId; + public int boardId { + get { + this.LoadIfNotLoaded(); + return this._boardId; + } + } + public Board board { + get { + return Board.LoadById(this.boardId); + } + } + + private Dictionary _data; + public Dictionary data { + get { + this.LoadIfNotLoaded(); + return this._data; + } + } + + protected override void doFromHash(Dictionary data) { + this._userId = int.Parse(data[TableSpec.FIELD_USERID]); + this._boardId = int.Parse(data[TableSpec.FIELD_BOARDID]); + this._data = ( + from part in data[TableSpec.FIELD_DATA].Split(new char[] {';'}, StringSplitOptions.RemoveEmptyEntries) + let subparts = part.Split(new char[] {':'}, 2) + select new KeyValuePair( + int.Parse(subparts[0]), + new DateTime(long.Parse(subparts[1])) + ) + ).ToDictionary(); + } + + private static readonly Dictionary> restrictionId_cache = new Dictionary>(); + public static Restriction GetRestriction(User user, Board board) { + + if(!restrictionId_cache.ContainsKey(user.id) || !restrictionId_cache[user.id].ContainsKey(board.id)) { + lock(restrictionId_cache) { + if(!restrictionId_cache.ContainsKey(user.id) || !restrictionId_cache[user.id].ContainsKey(board.id)) { + if(!restrictionId_cache.ContainsKey(user.id)) restrictionId_cache[user.id] = new Dictionary(); + + List ids = Config.instance.mainConnection.LoadIdsByConditions( + TableSpec.instance, + new ComplexCondition( + ConditionsJoinType.AND, + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_USERID), + ComparisonType.EQUAL, + user.id.ToString() + ), + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_BOARDID), + ComparisonType.EQUAL, + board.id.ToString() + ) + ), + Diapasone.unlimited + ); + if(ids.Count < 1) { + restrictionId_cache[user.id][board.id] = null; + } else { + restrictionId_cache[user.id][board.id] = Restriction.LoadById(int.Parse(ids.Single())).id; + } + + } + } + } + + if(restrictionId_cache[user.id][board.id].HasValue) { + return Restriction.LoadById(restrictionId_cache[user.id][board.id].Value); + } else { + return null; + } + } + + public static Dictionary GetRestrictionData(User user, Board board) { + Restriction restriction = GetRestriction(user, board); + if(restriction != null) { + return restriction.data; + } else { + return new Dictionary(); + } + } + + private static readonly Dictionary> byBoard_cache = new Dictionary>(); + private static void byBoard_Recalculate(int boardId) { + lock(byBoard_cache) { + byBoard_cache[boardId] = + from stringId in Config.instance.mainConnection.LoadIdsByConditions( + TableSpec.instance, + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_BOARDID), + ComparisonType.EQUAL, + boardId.ToString() + ), + Diapasone.unlimited + ) + select Restriction.LoadById(int.Parse(stringId)).id; + } + } + public static IEnumerable GetRestrictedUsers(Board board) { + if(!byBoard_cache.ContainsKey(board.id)) { + byBoard_Recalculate(board.id); + } + return from id in byBoard_cache[board.id] select Restriction.LoadById(id).user; + } + + private static readonly Dictionary> byUser_cache = new Dictionary>(); + private static void byUser_Recalculate(int userId) { + lock(byUser_cache) { + byUser_cache[userId] = + from stringId in Config.instance.mainConnection.LoadIdsByConditions( + TableSpec.instance, + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_USERID), + ComparisonType.EQUAL, + userId.ToString() + ), + Diapasone.unlimited + ) + select Restriction.LoadById(int.Parse(stringId)).id; + } + } + public static IEnumerable GetRestrictions(User user) { + if(!byUser_cache.ContainsKey(user.id)) { + byUser_Recalculate(user.id); + } + return from id in byUser_cache[user.id] select Restriction.LoadById(id).board; + } + + public static void RecalculateRestrictions(Board board, User user) { + List punishments = (from punishment in Punishment.getEffectivePunishments(user, board) where punishment.punishmentType.weight > 0 orderby punishment.expires descending select punishment).ToList(); + + Dictionary layer2expirationDate = new Dictionary(); + foreach(var layer in PostLayer.allLayers) { + + if(!layer.maxPunishments.HasValue) continue; + + bool restricted = false; + int accumulated = 0; + DateTime? expirationDate = null; + foreach(var punishment in punishments) { + accumulated += punishment.punishmentType.weight; + if(accumulated >= layer.maxPunishments.Value) { + expirationDate = punishment.expires; + restricted = true; + break; + } + } + + if(restricted) { + layer2expirationDate[layer.id] = expirationDate.Value; + } + } + + string data = (from kvp in layer2expirationDate select string.Format("{0}:{1}", kvp.Key, kvp.Value.Ticks)).Join(";"); + + ChangeSetUtil.ApplyChanges( + new InsertOrUpdateChange( + TableSpec.instance, + new Dictionary { + { TableSpec.FIELD_BOARDID, new ScalarFieldValue(board.id.ToString()) }, + { TableSpec.FIELD_USERID, new ScalarFieldValue(user.id.ToString()) }, + { TableSpec.FIELD_DATA, new ScalarFieldValue(data) }, + }, + new Dictionary { + { TableSpec.FIELD_DATA, new ScalarFieldValue(data) }, + }, + new ComplexCondition( + ConditionsJoinType.AND, + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_BOARDID), + ComparisonType.EQUAL, + board.id.ToString() + ), + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_USERID), + ComparisonType.EQUAL, + user.id.ToString() + ) + ) + ) + ); + } + + } +} diff --git a/Common/dataobjects/User.cs b/Common/dataobjects/User.cs index 4862d4f..8c44aaa 100644 --- a/Common/dataobjects/User.cs +++ b/Common/dataobjects/User.cs @@ -226,6 +226,8 @@ namespace FLocal.Common.dataobjects { } public PostLayer getActualLayer(Board board, PostLayer desiredLayer) { + Dictionary restrictionData = Restriction.GetRestrictionData(this, board); + if(restrictionData.ContainsKey(desiredLayer.id) && (restrictionData[desiredLayer.id].CompareTo(DateTime.Now) >= 0)) throw new FLocalException("You're restricted from posting in this layer until " + restrictionData[desiredLayer.id].ToString()); return desiredLayer; } diff --git a/IISMainHandler/handlers/response/CreateThreadHandler.cs b/IISMainHandler/handlers/response/CreateThreadHandler.cs index 3eab456..3a13c9a 100644 --- a/IISMainHandler/handlers/response/CreateThreadHandler.cs +++ b/IISMainHandler/handlers/response/CreateThreadHandler.cs @@ -23,9 +23,7 @@ namespace FLocal.IISHandler.handlers.response { return new XElement[] { board.exportToXml(context, Board.SubboardsOptions.None), - new XElement("layers", - from layer in PostLayer.allLayers select layer.exportToXml(context) - ), + board.exportLayersInfoForUser(context), }; } } diff --git a/IISMainHandler/handlers/response/EditHandler.cs b/IISMainHandler/handlers/response/EditHandler.cs index 59a6e0a..cbd72d9 100644 --- a/IISMainHandler/handlers/response/EditHandler.cs +++ b/IISMainHandler/handlers/response/EditHandler.cs @@ -26,9 +26,7 @@ namespace FLocal.IISHandler.handlers.response { post.thread.exportToXml(context), post.exportToXml(context), post.latestRevision.exportToXml(context), - new XElement("layers", - from layer in PostLayer.allLayers select layer.exportToXml(context) - ), + post.thread.board.exportLayersInfoForUser(context), }; } } diff --git a/IISMainHandler/handlers/response/ReplyHandler.cs b/IISMainHandler/handlers/response/ReplyHandler.cs index ddd13b8..805fa27 100644 --- a/IISMainHandler/handlers/response/ReplyHandler.cs +++ b/IISMainHandler/handlers/response/ReplyHandler.cs @@ -34,9 +34,7 @@ namespace FLocal.IISHandler.handlers.response { post.thread.board.exportToXml(context, Board.SubboardsOptions.None), post.thread.exportToXml(context), post.exportToXml(context), - new XElement("layers", - from layer in PostLayer.allLayers select layer.exportToXml(context) - ), + post.thread.board.exportLayersInfoForUser(context), new XElement("quoted", quoted), }; } diff --git a/templates/Full/NewThread.xslt b/templates/Full/NewThread.xslt index 31b6a77..0a1eafa 100644 --- a/templates/Full/NewThread.xslt +++ b/templates/Full/NewThread.xslt @@ -38,7 +38,7 @@ Слой сообщения: diff --git a/templates/Full/PostEdit.xslt b/templates/Full/PostEdit.xslt index 0d41524..f974aa6 100644 --- a/templates/Full/PostEdit.xslt +++ b/templates/Full/PostEdit.xslt @@ -40,7 +40,7 @@ Слой сообщения: diff --git a/templates/Full/PostPunish.xslt b/templates/Full/PostPunish.xslt index a02df30..067216e 100644 --- a/templates/Full/PostPunish.xslt +++ b/templates/Full/PostPunish.xslt @@ -51,7 +51,7 @@ diff --git a/templates/Full/PostReply.xslt b/templates/Full/PostReply.xslt index 8119fdc..8a604ae 100644 --- a/templates/Full/PostReply.xslt +++ b/templates/Full/PostReply.xslt @@ -50,7 +50,7 @@ Слой сообщения: diff --git a/templates/Full/elems/TextEditor.xslt b/templates/Full/elems/TextEditor.xslt index 25d9a6d..96e7fdb 100644 --- a/templates/Full/elems/TextEditor.xslt +++ b/templates/Full/elems/TextEditor.xslt @@ -319,11 +319,32 @@ function insertInBody(str) { + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/templates/Lite/NewThread.xslt b/templates/Lite/NewThread.xslt index 54e6150..20e167c 100644 --- a/templates/Lite/NewThread.xslt +++ b/templates/Lite/NewThread.xslt @@ -33,9 +33,7 @@ Слой сообщения:

diff --git a/templates/Lite/PostEdit.xslt b/templates/Lite/PostEdit.xslt index d5a6fe9..1ff2dc0 100644 --- a/templates/Lite/PostEdit.xslt +++ b/templates/Lite/PostEdit.xslt @@ -35,7 +35,7 @@ Слой сообщения: diff --git a/templates/Lite/PostPunish.xslt b/templates/Lite/PostPunish.xslt index d461271..f7b3f2e 100644 --- a/templates/Lite/PostPunish.xslt +++ b/templates/Lite/PostPunish.xslt @@ -46,7 +46,7 @@ diff --git a/templates/Lite/PostReply.xslt b/templates/Lite/PostReply.xslt index 25842a5..10969d4 100644 --- a/templates/Lite/PostReply.xslt +++ b/templates/Lite/PostReply.xslt @@ -45,7 +45,7 @@ Слой сообщения: diff --git a/templates/Lite/elems/TextEditor.xslt b/templates/Lite/elems/TextEditor.xslt index b7a64ba..7e14da9 100644 --- a/templates/Lite/elems/TextEditor.xslt +++ b/templates/Lite/elems/TextEditor.xslt @@ -47,11 +47,32 @@ function insertInBody(str) { + + + + + + + + + + + + + + + + \ No newline at end of file