From b94a29b8d89359eca26f419129f11326aa55f062 Mon Sep 17 00:00:00 2001 From: inga-lovinde <52715130+inga-lovinde@users.noreply.github.com> Date: Thu, 9 Sep 2010 17:01:50 +0000 Subject: [PATCH] Active 'who is online' implemented; last activity of user implemented --- Builder/IISMainHandler/build.txt | 2 +- Common/dataobjects/Account.cs | 22 ++++++ Common/dataobjects/Session.cs | 71 +++++++++++++++++-- Core/DB/Diapasone.cs | 6 ++ IISMainHandler/WebContext.cs | 2 +- .../handlers/response/UserInfoHandler.cs | 5 ++ .../handlers/response/WhoIsOnlineHandler.cs | 29 ++++++-- templates/Full/UserInfo.xslt | 2 +- templates/Full/WhoIsOnline.xslt | 59 +++++++++++++++ 9 files changed, 183 insertions(+), 15 deletions(-) create mode 100644 templates/Full/WhoIsOnline.xslt diff --git a/Builder/IISMainHandler/build.txt b/Builder/IISMainHandler/build.txt index 5ec4258..8535dde 100644 --- a/Builder/IISMainHandler/build.txt +++ b/Builder/IISMainHandler/build.txt @@ -1 +1 @@ -1159 \ No newline at end of file +1161 \ No newline at end of file diff --git a/Common/dataobjects/Account.cs b/Common/dataobjects/Account.cs index cbf92c5..bdda8a1 100644 --- a/Common/dataobjects/Account.cs +++ b/Common/dataobjects/Account.cs @@ -20,6 +20,8 @@ namespace FLocal.Common.dataobjects { public const string FIELD_NAME = "Name"; public const string FIELD_IPADDRESS = "IpAddress"; public const string FIELD_REGISTRATIONEMAIL = "RegistrationEmail"; + public const string FIELD_ISSTATUSHIDDEN = "IsStatusHidden"; + public const string FIELD_ISDETAILEDSTATUSHIDDEN = "IsDetailedStatusHidden"; public static readonly TableSpec instance = new TableSpec(); public string name { get { return TABLE; } } public string idName { get { return FIELD_ID; } } @@ -65,11 +67,29 @@ namespace FLocal.Common.dataobjects { } } + private bool _isStatusHidden; + public bool isStatusHidden { + get { + this.LoadIfNotLoaded(); + return this._isStatusHidden; + } + } + + private bool _isDetailedStatusHidden; + public bool isDetailedStatusHidden { + get { + this.LoadIfNotLoaded(); + return this._isDetailedStatusHidden; + } + } + protected override void doFromHash(Dictionary data) { this._userId = int.Parse(data[TableSpec.FIELD_USERID]); this._passwordHash = data[TableSpec.FIELD_PASSWORDHASH]; this._needsMigration = Util.string2bool(data[TableSpec.FIELD_NEEDSMIGRATION]); this._name = data[TableSpec.FIELD_NAME]; + this._isStatusHidden = Util.string2bool(data[TableSpec.FIELD_ISSTATUSHIDDEN]); + this._isDetailedStatusHidden = Util.string2bool(data[TableSpec.FIELD_ISDETAILEDSTATUSHIDDEN]); } public XElement exportToXml(UserContext context) { @@ -205,6 +225,8 @@ namespace FLocal.Common.dataobjects { { Account.TableSpec.FIELD_USERID, new ReferenceFieldValue(userInsert) }, { Account.TableSpec.FIELD_IPADDRESS, new ScalarFieldValue(ip) }, { Account.TableSpec.FIELD_REGISTRATIONEMAIL, new ScalarFieldValue(registrationEmail) }, + { Account.TableSpec.FIELD_ISSTATUSHIDDEN, new ScalarFieldValue("0") }, + { Account.TableSpec.FIELD_ISDETAILEDSTATUSHIDDEN, new ScalarFieldValue("0") }, } ); var indicatorInsert = new InsertChange( diff --git a/Common/dataobjects/Session.cs b/Common/dataobjects/Session.cs index 35712a6..19ee3cf 100644 --- a/Common/dataobjects/Session.cs +++ b/Common/dataobjects/Session.cs @@ -48,6 +48,8 @@ namespace FLocal.Common.dataobjects { public const string FIELD_SESSIONKEY = "SessionKey"; public const string FIELD_ACCOUNTID = "AccountId"; public const string FIELD_LASTACTIVITY = "LastActivity"; + public const string FIELD_LASTURL = "LastUrl"; + public const string FIELD_ISDELETED = "IsDeleted"; public static readonly TableSpec instance = new TableSpec(); public string name { get { return TABLE; } } public string idName { get { return FIELD_ID; } } @@ -85,13 +87,31 @@ namespace FLocal.Common.dataobjects { } } + private string _lastUrl; + public string lastUrl { + get { + this.LoadIfNotLoaded(); + return this._lastUrl; + } + } + + private bool _isDeleted; + public bool isDeleted { + get { + this.LoadIfNotLoaded(); + return this._isDeleted; + } + } + protected override void doFromHash(Dictionary data) { this._sessionKey = data[TableSpec.FIELD_SESSIONKEY]; this._lastActivity = new DateTime(long.Parse(data[TableSpec.FIELD_LASTACTIVITY])); this._accountId = int.Parse(data[TableSpec.FIELD_ACCOUNTID]); + this._lastUrl = data[TableSpec.FIELD_LASTURL]; + this._isDeleted = Util.string2bool(data[TableSpec.FIELD_ISDELETED]); } - public void updateLastActivity() { + public void updateLastActivity(string lastUrl) { if(DateTime.Now.Subtract(this.lastActivity).TotalSeconds < 30) return; //to partially remove db load try { Config.Transactional(transaction => { @@ -100,7 +120,8 @@ namespace FLocal.Common.dataobjects { TableSpec.instance, this.id.ToString(), new Dictionary() { - { TableSpec.FIELD_LASTACTIVITY, DateTime.Now.ToUTCString() } + { TableSpec.FIELD_LASTACTIVITY, DateTime.Now.ToUTCString() }, + { TableSpec.FIELD_LASTURL, (lastUrl != null) ? lastUrl : this.lastUrl }, } ); }); @@ -128,6 +149,8 @@ namespace FLocal.Common.dataobjects { { TableSpec.FIELD_SESSIONKEY, key }, { TableSpec.FIELD_ACCOUNTID, account.id.ToString() }, { TableSpec.FIELD_LASTACTIVITY, DateTime.Now.ToUTCString() }, + { TableSpec.FIELD_LASTURL, "" }, + { TableSpec.FIELD_ISDELETED, "0" }, } ); }); @@ -135,8 +158,20 @@ namespace FLocal.Common.dataobjects { } public void delete() { - Config.Transactional(transaction => Config.instance.mainConnection.delete(transaction, TableSpec.instance, this.id.ToString())); - this.deleteFromRegistry(); + try { + Config.Transactional(transaction => { + Config.instance.mainConnection.update( + transaction, + TableSpec.instance, + this.id.ToString(), + new Dictionary() { + { TableSpec.FIELD_ISDELETED, "1" }, + } + ); + }); + } finally { + this.ReLoad(); + } } public XElement exportToXml(UserContext context) { @@ -149,7 +184,33 @@ namespace FLocal.Common.dataobjects { } public static Session LoadByKey(string sessionKey) { - return LoadById(SessionKey.Parse(sessionKey)); + Session result = LoadById(SessionKey.Parse(sessionKey)); + if(result.isDeleted) throw new NotFoundInDBException(TableSpec.instance, sessionKey); + return result; + } + + public static Session GetLastSession(Account account) { + var ids = Config.instance.mainConnection.LoadIdsByConditions( + TableSpec.instance, + new ComparisonCondition( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_ACCOUNTID), + ComparisonType.EQUAL, + account.id.ToString() + ), + Diapasone.first, + new JoinSpec[0], + new SortSpec[] { + new SortSpec( + TableSpec.instance.getColumnSpec(TableSpec.FIELD_LASTACTIVITY), + false + ) + } + ); + if(ids.Count < 1) { + throw new NotFoundInDBException(TableSpec.instance.getColumnSpec(TableSpec.FIELD_ACCOUNTID), account.id.ToString()); + } + + return Session.LoadById(SessionKey.Parse(ids[0])); } } diff --git a/Core/DB/Diapasone.cs b/Core/DB/Diapasone.cs index 6646816..6ecd903 100644 --- a/Core/DB/Diapasone.cs +++ b/Core/DB/Diapasone.cs @@ -24,5 +24,11 @@ namespace FLocal.Core.DB { } } + public static Diapasone first { + get { + return new Diapasone(0, 1); + } + } + } } diff --git a/IISMainHandler/WebContext.cs b/IISMainHandler/WebContext.cs index e23c584..4948463 100644 --- a/IISMainHandler/WebContext.cs +++ b/IISMainHandler/WebContext.cs @@ -92,7 +92,7 @@ namespace FLocal.IISHandler { var session = Session.LoadByKey(sessionCookie.Value); var tmp = session.account; sessionCookie.Expires = DateTime.Now.AddDays(3); - session.updateLastActivity(); + session.updateLastActivity(this.httprequest.RequestType == "GET" ? this.httprequest.Path : null); this.httpresponse.AppendCookie(sessionCookie); this.session = session; } catch(NotFoundInDBException) { diff --git a/IISMainHandler/handlers/response/UserInfoHandler.cs b/IISMainHandler/handlers/response/UserInfoHandler.cs index a2bbbea..0c3094a 100644 --- a/IISMainHandler/handlers/response/UserInfoHandler.cs +++ b/IISMainHandler/handlers/response/UserInfoHandler.cs @@ -37,9 +37,14 @@ namespace FLocal.IISHandler.handlers.response { } catch(NotFoundInDBException) { } } + Session lastSession = null; + if(account != null && !account.isDetailedStatusHidden) { + lastSession = Session.GetLastSession(account); + } return new XElement[] { user.exportToXmlForViewing(context), (account == null) ? null : new XElement("accountId", account.id.ToString()), //for PM history, PM send etc + (lastSession == null) ? null : new XElement("lastActivity", lastSession.lastActivity.ToXml()) }; } diff --git a/IISMainHandler/handlers/response/WhoIsOnlineHandler.cs b/IISMainHandler/handlers/response/WhoIsOnlineHandler.cs index 43c4822..b21c0b7 100644 --- a/IISMainHandler/handlers/response/WhoIsOnlineHandler.cs +++ b/IISMainHandler/handlers/response/WhoIsOnlineHandler.cs @@ -16,7 +16,7 @@ namespace FLocal.IISHandler.handlers.response { override protected string templateName { get { - return "UserList.xslt"; + return "WhoIsOnline.xslt"; } } @@ -25,16 +25,31 @@ namespace FLocal.IISHandler.handlers.response { IEnumerable sessions = from stringId in Config.instance.mainConnection.LoadIdsByConditions( Session.TableSpec.instance, - new Core.DB.conditions.ComparisonCondition( - Session.TableSpec.instance.getColumnSpec(Session.TableSpec.FIELD_LASTACTIVITY), - Core.DB.conditions.ComparisonType.GREATEROREQUAL, - DateTime.Now.Subtract(Config.instance.ActivityThreshold).ToUTCString() + new ComplexCondition( + ConditionsJoinType.AND, + new ComparisonCondition( + Session.TableSpec.instance.getColumnSpec(Session.TableSpec.FIELD_LASTACTIVITY), + Core.DB.conditions.ComparisonType.GREATEROREQUAL, + DateTime.Now.Subtract(Config.instance.ActivityThreshold).ToUTCString() + ), + new ComparisonCondition( + Session.TableSpec.instance.getColumnSpec(Session.TableSpec.FIELD_ISDELETED), + Core.DB.conditions.ComparisonType.EQUAL, + "0" + ) ), pageOuter ) select Session.LoadByKey(stringId); return new XElement[] { - new XElement("users", - from session in sessions select session.account.user.exportToXmlForViewing(context) + new XElement("users", + from session in sessions + let account = session.account + where !account.isStatusHidden + select account.user.exportToXmlForViewing( + context, + new XElement("lastActivity", session.lastActivity.ToXml()), + !account.isDetailedStatusHidden ? new XElement("lastUrl", session.lastUrl) : null + ) ) }; } diff --git a/templates/Full/UserInfo.xslt b/templates/Full/UserInfo.xslt index 6f6010e..f0b4c59 100644 --- a/templates/Full/UserInfo.xslt +++ b/templates/Full/UserInfo.xslt @@ -144,7 +144,7 @@ Последний раз онлайн - Not implemented + diff --git a/templates/Full/WhoIsOnline.xslt b/templates/Full/WhoIsOnline.xslt new file mode 100644 index 0000000..8d73b20 --- /dev/null +++ b/templates/Full/WhoIsOnline.xslt @@ -0,0 +1,59 @@ + + + + Пользователи + + + + + +
+ + + + + + + +
+ + Пользователь + + + + Последняя активность + + + + Последняя посещённая страница + +
+
+
+ + + + + + lighttable + + + darktable + + + + + + + + + + + + + + + + + +
\ No newline at end of file