/* * * (c) Copyright Ascensio System Limited 2010-2018 * * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. * * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html * * You can contact Ascensio System SIA by email at sales@onlyoffice.com * * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. * * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains * relevant author attributions when distributing the software. If the display of the logo in its graphic * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * */ using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Web; using ASC.Api.Core; using ASC.Calendar.Core.Dao; using ASC.Calendar.ExternalCalendars; using ASC.Calendar.iCalParser; using ASC.Common.Logging; using ASC.Common.Utils; using ASC.Core; using ASC.Core.Common; using ASC.Core.Common.EF; using ASC.Security.Cryptography; using ASC.Web.Core.Calendars; using ASC.Web.Core.WhiteLabel; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; namespace ASC.Calendar.BusinessObjects { public class DataProvider { /* private IDbManager db; private const string DBId = "calendar"; private const string _calendarTable = "calendar_calendars cal"; private const string _calendarItemTable = "calendar_calendar_item cal_itm"; private const string _calendarUserTable = "calendar_calendar_user cal_usr"; private const string _eventTable = "calendar_events evt"; private const string _todoTable = "calendar_todos td"; private const string _eventItemTable = "calendar_event_item evt_itm";*/ public CalendarDbContext CalendarDb { get; } public int Tenant { get { return ApiContext.Tenant.TenantId; } } public ApiContext ApiContext { get; } public string UserId { get { return SecurityContext.CurrentAccount.ID.ToString(); } } public SecurityContext SecurityContext { get; } public AuthContext AuthContext { get; } public TimeZoneConverter TimeZoneConverter { get; } public ILog Log { get; } public DataProvider(DbContextManager calendarDbContext, ApiContext apiContext, SecurityContext securityContext, AuthContext authContext, TimeZoneConverter timeZoneConverter, IOptionsMonitor option) { CalendarDb = calendarDbContext.Get("calendar"); ApiContext = apiContext; SecurityContext = securityContext; AuthContext = authContext; TimeZoneConverter = timeZoneConverter; Log = option.Get("ASC.CalendarDataProvider"); } /* public List GetUserViewSettings(Guid userId, List calendarIds) { var cc = new ColumnCollection(); var extCalId = cc.RegistryColumn("ext_calendar_id"); var usrId = cc.RegistryColumn("user_id"); var hideEvents = cc.RegistryColumn("hide_events"); var isAccepted = cc.RegistryColumn("is_accepted"); var textColor = cc.RegistryColumn("text_color"); var background = cc.RegistryColumn("background_color"); var alertType = cc.RegistryColumn("alert_type"); var calId = cc.RegistryColumn("convert(calendar_id using utf8)"); var calName = cc.RegistryColumn("name"); var timeZone = cc.RegistryColumn("time_zone"); var query = new SqlQuery("calendar_calendar_user") .Select(cc.SelectQuery) .Where((Exp.In(extCalId.Name, calendarIds) | Exp.In(calId.Name, calendarIds)) & Exp.Eq(usrId.Name, userId)); var data = db.ExecuteList(query); var options = new List(); foreach (var r in data) { options.Add(new UserViewSettings() { CalendarId = Convert.ToInt32(r[calId.Ind]) == 0 ? Convert.ToString(r[extCalId.Ind]) : Convert.ToString(r[calId.Ind]), UserId = usrId.Parse(r), IsHideEvents = hideEvents.Parse(r), IsAccepted = isAccepted.Parse(r), TextColor = textColor.Parse(r), BackgroundColor = background.Parse(r), EventAlertType = (EventAlertType) alertType.Parse(r), Name = calName.Parse(r), TimeZone = timeZone.Parse(r) }); } return options; } public List LoadTodoCalendarsForUser(Guid userId) { var groups = UserManager.GetUserGroups(userId).Select(g => g.ID).ToList(); groups.AddRange( UserManager.GetUserGroups(userId, Core.Users.Constants.SysGroupCategoryId).Select(g => g.ID)); var currentTenantId = TenantManager.GetCurrentTenant().TenantId; var queryGetCalIds = new SqlQuery(_calendarTable) .Select("cal.id") .Where("cal.owner_id", userId) .Where("cal.is_todo", 1) .Where("cal.tenant", currentTenantId); var calIds = db.ExecuteList(queryGetCalIds).Select(r => r[0]); var cals = GetCalendarsByIds(calIds.ToArray()); return cals; } public void RemoveTodo(int todoId) { using (var tr = db.BeginTransaction()) { var tenant = TenantManager.GetCurrentTenant().TenantId; db.ExecuteNonQuery(new SqlDelete("calendar_todos").Where("id", todoId).Where("tenant", tenant)); tr.Commit(); } } public List LoadCalendarsForUser(Guid userId, out int newCalendarsCount) { var groups = UserManager.GetUserGroups(userId).Select(g => g.ID).ToList(); groups.AddRange( UserManager.GetUserGroups(userId, Core.Users.Constants.SysGroupCategoryId).Select(g => g.ID)); var currentTenantId = TenantManager.GetCurrentTenant().TenantId; var queryGetCalIds = new SqlQuery(_calendarItemTable) .Select("cal_itm.calendar_id") .InnerJoin(_calendarTable, Exp.EqColumns("cal.id", "cal_itm.calendar_id")) .Where("cal.tenant", currentTenantId) .Where(Exp.Eq("cal_itm.item_id", userId) | (Exp.In("cal_itm.item_id", groups.ToArray()) & Exp.Eq("cal_itm.is_group", true))) .Union(new SqlQuery(_calendarTable) .Select("cal.id") .Where("cal.owner_id", userId) .Where("cal.tenant", currentTenantId)); var calIds = db.ExecuteList(queryGetCalIds).Select(r => r[0]); var cals = GetCalendarsByIds(calIds.ToArray()); //filter by is_accepted field newCalendarsCount = cals.RemoveAll( c => (!c.OwnerId.Equals(userId) && !c.ViewSettings.Exists(v => v.UserId.Equals(userId) && v.IsAccepted)) || (c.IsiCalStream() && c.ViewSettings.Exists(v => v.UserId.Equals(userId) && !v.IsAccepted))); return cals; } public List LoadiCalStreamsForUser(Guid userId) { var queryGetCalIds = new SqlQuery(_calendarTable) .Select("cal.id") .Where("cal.tenant", TenantManager.GetCurrentTenant().TenantId) .Where("cal.owner_id", userId) .Where(!Exp.Eq("cal.ical_url", null)); var calIds = db.ExecuteList(queryGetCalIds).Select(r => r[0]); var calendars = GetCalendarsByIds(calIds.ToArray()); return calendars; } public List LoadSubscriptionsForUser(Guid userId) { var groups = UserManager.GetUserGroups(userId).Select(g => g.ID).ToList(); groups.AddRange(UserManager.GetUserGroups(userId, Core.Users.Constants.SysGroupCategoryId).Select(g => g.ID)); var calIds = db.ExecuteList(new SqlQuery(_calendarItemTable).Select("cal_itm.calendar_id") .InnerJoin(_calendarTable, Exp.EqColumns("cal.id", "cal_itm.calendar_id")) .Where("cal.tenant", TenantManager.GetCurrentTenant().TenantId) .Where(Exp.Eq("cal_itm.item_id", userId) | (Exp.In("cal_itm.item_id", groups.ToArray()) & Exp.Eq("cal_itm.is_group", true))) ).Select(r => r[0]); var calendars = GetCalendarsByIds(calIds.ToArray()); return calendars; } public TimeZoneInfo GetTimeZoneForSharedEventsCalendar(Guid userId) { var q = new SqlQuery(_calendarUserTable) .Select("time_zone") .Where("ext_calendar_id", SharedEventsCalendar.CalendarId) .Where("user_id", userId); var data = db.ExecuteList(q); if (data.Count > 0) return data.Select(r => TimeZoneConverter.GetTimeZone(Convert.ToString(r[0]))).First(); return TimeZoneInfo.FindSystemTimeZoneById(TenantManager.GetCurrentTenant().TimeZone); } public TimeZoneInfo GetTimeZoneForCalendar(Guid userId, int caledarId) { return db.ExecuteList(new SqlQuery(_calendarTable).Select("cal.time_zone", "cal_usr.time_zone") .LeftOuterJoin(_calendarUserTable, Exp.EqColumns("cal.id", "cal_usr.calendar_id") & Exp.Eq("cal_usr.user_id", userId)) .Where(Exp.Eq("cal.id", caledarId))) .Select(r => (r[1] == null || r[1] == DBNull.Value) ? TimeZoneConverter.GetTimeZone(Convert.ToString(r[0])) : TimeZoneConverter.GetTimeZone(Convert.ToString(r[1]))).First(); } public List GetCalendarIdByCaldavGuid(string caldavGuid) { var data = db.ExecuteList(new SqlQuery(_calendarTable).Select("id", "owner_id", "tenant").Where("caldav_guid", caldavGuid)); return data; } public Event GetEventIdByUid(string uid, int calendarId) { var sql = new SqlQuery("calendar_events") .Select("id") .Where(Exp.Like("uid", uid)) .Where("calendar_id", calendarId); var eventId = db.ExecuteScalar(sql); return eventId == 0 ? null : GetEventById(eventId); } public Event GetEventIdOnlyByUid(string uid) { var sql = new SqlQuery("calendar_events") .Select("id") .Where(Exp.Like("uid", uid)); var eventId = db.ExecuteScalar(sql); return eventId == 0 ? null : GetEventById(eventId); }*/ public List GetCalendarsByIds(int[] calIds) { var data = from cc in CalendarDb.CalendarCalendars join calUsr in CalendarDb.CalendarCalendarUser on cc.Id equals calUsr.CalendarId into UserCalendar from uc in UserCalendar.DefaultIfEmpty() where calIds.Contains(cc.Id) select new { calId = cc.Id, calName = cc.Name, calDescription = cc.Description, calTenant = cc.Tenant, calTextColor = cc.TextColor, calBackground = cc.BackgroundColor, calOwner = cc.OwnerId, calAlertType = cc.AlertType, calTimeZone = cc.TimeZone, iCalUrl = cc.IcalUrl, calDavGuid = cc.CaldavGuid, isTodo = cc.IsTodo, usrId = uc.UserId, usrHideEvents = uc.HideEvents, usrIsAccepted = uc.IsAccepted, usrTextColor = uc.TextColor, usrBackground = uc.BackgroundColor, usrAlertType = uc.AlertType, usrCalName = uc.Name, usrTimeZone = uc.TimeZone }; var sharingData = CalendarDb.CalendarCalendarItem.Where(p => calIds.Contains(p.CalendarId)).ToList(); var calendars = new List(); foreach (var r in data) { var calendar = calendars.Find( c => string.Equals(c.Id, r.calId.ToString(), StringComparison.InvariantCultureIgnoreCase)); if (calendar == null) { calendar = new Calendar(AuthContext, TimeZoneConverter) { Id = r.calId.ToString(), Name = r.calName, Description = r.calDescription, TenantId = r.calTenant, OwnerId = Guid.Parse(r.calOwner), EventAlertType = (EventAlertType)r.calAlertType, TimeZone = TimeZoneConverter.GetTimeZone(r.calTimeZone), iCalUrl = r.iCalUrl, calDavGuid = r.calDavGuid, IsTodo = Convert.ToInt32(r.isTodo) }; calendar.Context.HtmlTextColor = r.calTextColor; calendar.Context.HtmlBackgroundColor = r.calBackground; if (!String.IsNullOrEmpty(calendar.iCalUrl)) { calendar.Context.CanChangeTimeZone = false; calendar.Context.CanChangeAlertType = false; } calendars.Add(calendar); foreach (var row in sharingData) { var _calId = row.CalendarId.ToString(); if (String.Equals(_calId, calendar.Id, StringComparison.InvariantCultureIgnoreCase)) { calendar.SharingOptions.PublicItems.Add(new SharingOptions.PublicItem { Id = Guid.Parse(row.ItemId), IsGroup = Convert.ToBoolean(row.IsGroup) }); } } } var uvs = new UserViewSettings { CalendarId = calendar.Id, UserId = Guid.Parse(r.usrId), IsHideEvents = Convert.ToBoolean(r.usrHideEvents), IsAccepted = Convert.ToBoolean(r.usrIsAccepted), TextColor = r.usrTextColor.ToString(), BackgroundColor = r.usrBackground.ToString(), EventAlertType = (EventAlertType)r.usrAlertType, Name = r.usrCalName.ToString(), TimeZone = TimeZoneConverter.GetTimeZone(r.usrTimeZone) }; calendar.ViewSettings.Add(uvs); } return calendars; } public Calendar GetCalendarById(int calendarId) { var calendars = GetCalendarsByIds(new int[] { calendarId }); if (calendars.Count > 0) return calendars[0]; return null; } /*public Calendar CreateCalendar(Guid ownerId, string name, string description, string textColor, string backgroundColor, TimeZoneInfo timeZone, EventAlertType eventAlertType, string iCalUrl, List publicItems, List viewSettings, Guid calDavGuid, int isTodo = 0) { int calendarId; using (var tr = db.BeginTransaction()) { calendarId = db.ExecuteScalar(new SqlInsert("calendar_calendars") .InColumnValue("id", 0) .InColumnValue("tenant", TenantManager .GetCurrentTenant().TenantId) .InColumnValue("owner_id", ownerId) .InColumnValue("name", name) .InColumnValue("description", description) .InColumnValue("text_color", textColor) .InColumnValue("background_color", backgroundColor) .InColumnValue("alert_type", (int) eventAlertType) .InColumnValue("time_zone", timeZone.Id) .InColumnValue("ical_url", iCalUrl) .InColumnValue("caldav_guid", calDavGuid) .InColumnValue("is_todo", isTodo) .Identity(0, 0, true)); if (publicItems != null) { foreach (var item in publicItems) { db.ExecuteNonQuery(new SqlInsert("calendar_calendar_item") .InColumnValue("calendar_id", calendarId) .InColumnValue("item_id", item.Id) .InColumnValue("is_group", item.IsGroup)); } } if (viewSettings != null) { foreach (var view in viewSettings) { db.ExecuteNonQuery(new SqlInsert("calendar_calendar_user") .InColumnValue("calendar_id", calendarId) .InColumnValue("user_id", view.UserId) .InColumnValue("hide_events", view.IsHideEvents) .InColumnValue("is_accepted", view.IsAccepted) .InColumnValue("text_color", view.TextColor) .InColumnValue("background_color", view.BackgroundColor) .InColumnValue("alert_type", (int) view.EventAlertType) .InColumnValue("name", view.Name ?? "") .InColumnValue("time_zone", view.TimeZone != null ? view.TimeZone.Id : null) ); } } tr.Commit(); } return GetCalendarById(calendarId); } public Calendar UpdateCalendarGuid(int calendarId, Guid calDavGuid) { using (var tr = db.BeginTransaction()) { db.ExecuteNonQuery(new SqlUpdate("calendar_calendars") .Set("caldav_guid", calDavGuid) .Where("id", calendarId)); tr.Commit(); } return GetCalendarById(calendarId); } public Calendar UpdateCalendar(int calendarId, string name, string description, List publicItems, List viewSettings) { using (var tr = db.BeginTransaction()) { db.ExecuteNonQuery(new SqlUpdate("calendar_calendars") .Set("name", name) .Set("description", description) .Where("id", calendarId)); //sharing var sqlQuery = new SqlQuery("calendar_calendar_item") .Select("item_id", "is_group") .Where(Exp.Eq("calendar_id", calendarId)); var existsItems = db.ExecuteList(sqlQuery).ConvertAll(row => new SharingOptions.PublicItem { Id = new Guid((string)row[0]), IsGroup = Convert.ToBoolean(row[1]) }); foreach (var existCalendar in existsItems) { db.ExecuteNonQuery(new SqlDelete("calendar_calendar_item") .Where("calendar_id", calendarId) .Where("item_id", existCalendar.Id) .Where("is_group", existCalendar.IsGroup)); } foreach (var item in publicItems) { db.ExecuteNonQuery(new SqlInsert("calendar_calendar_item") .InColumnValue("calendar_id", calendarId) .InColumnValue("item_id", item.Id) .InColumnValue("is_group", item.IsGroup)); } //view sqlQuery = new SqlQuery("calendar_calendar_user") .Select("ext_calendar_id", "user_id") .Where(Exp.Eq("calendar_id", calendarId)); var existsUsers = db.ExecuteList(sqlQuery).Select(row => new { ExtCalendarId = (string)row[0], Id = (string)row[1] }).ToList(); foreach (var user in existsUsers) { db.ExecuteNonQuery(new SqlDelete("calendar_calendar_user") .Where("calendar_id", calendarId) .Where("ext_calendar_id", user.ExtCalendarId) .Where("user_id", user.Id)); } foreach (var view in viewSettings) { db.ExecuteNonQuery(new SqlInsert("calendar_calendar_user") .InColumnValue("calendar_id", calendarId) .InColumnValue("user_id", view.UserId) .InColumnValue("hide_events", view.IsHideEvents) .InColumnValue("is_accepted", view.IsAccepted) .InColumnValue("text_color", view.TextColor) .InColumnValue("background_color", view.BackgroundColor) .InColumnValue("alert_type", (int) view.EventAlertType) .InColumnValue("name", view.Name ?? "") .InColumnValue("time_zone", view.TimeZone != null ? view.TimeZone.Id : null) ); } //update notifications var cc = new ColumnCollection(); var eId = cc.RegistryColumn("e.id"); var eStartDate = cc.RegistryColumn("e.start_date"); var eAlertType = cc.RegistryColumn("e.alert_type"); var eRRule = cc.RegistryColumn("e.rrule"); var eIsAllDay = cc.RegistryColumn("e.all_day_long"); var eventsData = db.ExecuteList( new SqlQuery("calendar_events e") .Select(cc.SelectQuery) .Where("e.calendar_id", calendarId) .Where("e.tenant", TenantManager.GetCurrentTenant().TenantId)); foreach (var r in eventsData) { UpdateEventNotifications(eId.Parse(r), calendarId, eStartDate.Parse(r), (EventAlertType) eAlertType.Parse(r), eRRule.Parse(r), null, publicItems, eIsAllDay.Parse(r)); } tr.Commit(); } return GetCalendarById(calendarId); } public void UpdateCalendarUserView(List viewSettings) { using (var tr = db.BeginTransaction()) { foreach (var s in viewSettings) UpdateCalendarUserView(s); tr.Commit(); } } public void UpdateCalendarUserView(UserViewSettings viewSettings) { var cc = new ColumnCollection(); var eId = cc.RegistryColumn("e.id"); var eStartDate = cc.RegistryColumn("e.start_date"); var eAlertType = cc.RegistryColumn("e.alert_type"); var eRRule = cc.RegistryColumn("e.rrule"); var eCalId = cc.RegistryColumn("e.calendar_id"); var eIsAllDay = cc.RegistryColumn("e.all_day_long"); int calendarId; if (int.TryParse(viewSettings.CalendarId, out calendarId)) { db.ExecuteNonQuery(new SqlInsert("calendar_calendar_user", true) .InColumnValue("calendar_id", calendarId) .InColumnValue("user_id", viewSettings.UserId) .InColumnValue("hide_events", viewSettings.IsHideEvents) .InColumnValue("text_color", viewSettings.TextColor) .InColumnValue("background_color", viewSettings.BackgroundColor) .InColumnValue("is_accepted", viewSettings.IsAccepted) .InColumnValue("alert_type", (int) viewSettings.EventAlertType) .InColumnValue("name", viewSettings.Name ?? "") .InColumnValue("time_zone", viewSettings.TimeZone != null ? viewSettings.TimeZone.Id : null) ); //update notifications var eventsData = db.ExecuteList( new SqlQuery("calendar_events e") .Select(cc.SelectQuery) .Where("e.calendar_id", calendarId) .Where("e.tenant", TenantManager.GetCurrentTenant().TenantId)); foreach (var r in eventsData) { UpdateEventNotifications(eId.Parse(r), calendarId, eStartDate.Parse(r), (EventAlertType) eAlertType.Parse(r), eRRule.Parse(r), null, null, eIsAllDay.Parse(r)); } } else { db.ExecuteNonQuery(new SqlInsert("calendar_calendar_user", true) .InColumnValue("ext_calendar_id", viewSettings.CalendarId) .InColumnValue("user_id", viewSettings.UserId) .InColumnValue("hide_events", viewSettings.IsHideEvents) .InColumnValue("text_color", viewSettings.TextColor) .InColumnValue("background_color", viewSettings.BackgroundColor) .InColumnValue("alert_type", (int) viewSettings.EventAlertType) .InColumnValue("is_accepted", viewSettings.IsAccepted) .InColumnValue("name", viewSettings.Name ?? "") .InColumnValue("time_zone", viewSettings.TimeZone != null ? viewSettings.TimeZone.Id : null) ); if (String.Equals(viewSettings.CalendarId, SharedEventsCalendar.CalendarId, StringComparison.InvariantCultureIgnoreCase)) { //update notifications var groups = UserManager.GetUserGroups(viewSettings.UserId).Select(g => g.ID).ToList(); groups.AddRange( UserManager.GetUserGroups(viewSettings.UserId, Core.Users.Constants.SysGroupCategoryId) .Select(g => g.ID)); var q = new SqlQuery("calendar_events e") .Select(cc.SelectQuery) .InnerJoin("calendar_event_item ei", Exp.EqColumns("ei.event_id", eId.Name)) .Where("e.tenant", TenantManager.GetCurrentTenant().TenantId) .Where((Exp.Eq("ei.is_group", false) & Exp.Eq("ei.item_id", viewSettings.UserId)) | (Exp.Eq("ei.is_group", true) & Exp.In("ei.item_id", groups.ToArray()))); var eventsData = db.ExecuteList(q); foreach (var r in eventsData) { UpdateEventNotifications(eId.Parse(r), eCalId.Parse(r), eStartDate.Parse(r), (EventAlertType) eAlertType.Parse(r), eRRule.Parse(r), null, null, eIsAllDay.Parse(r)); } } } } public void RemoveCalendar(int calendarId) { using (var tr = db.BeginTransaction()) { try { var dataCaldavGuid = db.ExecuteList(new SqlQuery("calendar_calendars").Select("caldav_guid").Where("id", calendarId)) .Select(r => r[0]) .ToArray(); var caldavGuid = dataCaldavGuid[0] != null ? Guid.Parse(dataCaldavGuid[0].ToString()) : Guid.Empty; if (caldavGuid != Guid.Empty) { var myUri = HttpContext.Current.Request.GetUrlRewriter(); var caldavHost = myUri.Host; LogManager.GetLogger("ASC.Calendar").Info("RADICALE REWRITE URL: " + myUri); var currentUserName = UserManager.GetUsers(AuthContext.CurrentAccount.ID).Email.ToLower() + "@" + caldavHost; var _email = UserManager.GetUsers(AuthContext.CurrentAccount.ID).Email; string currentAccountPaswd = AuthManager.GetUserPasswordHash(TenantManager.GetCurrentTenant().TenantId, UserManager.GetUserByEmail(_email).ID); var encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(UserManager.GetUsers(AuthContext.CurrentAccount.ID).Email.ToLower() + ":" + currentAccountPaswd)); var caldavTask = new Task(() => RemoveCaldavCalendar(currentUserName, _email, currentAccountPaswd, encoded, caldavGuid.ToString(), myUri)); caldavTask.Start(); } } catch (Exception ex) { LogManager.GetLogger("ASC.Calendar").Error(ex); } db.ExecuteNonQuery(new SqlDelete("calendar_calendars").Where("id", calendarId)); db.ExecuteNonQuery(new SqlDelete("calendar_calendar_user").Where("calendar_id", calendarId)); db.ExecuteNonQuery(new SqlDelete("calendar_calendar_item").Where("calendar_id", calendarId)); var tenant = TenantManager.GetCurrentTenant().TenantId; var data = db.ExecuteList(new SqlQuery("calendar_events") .Select("id") .Where("calendar_id", calendarId) .Where("tenant", tenant)) .Select(r => r[0]) .ToArray(); db.ExecuteNonQuery(new SqlDelete("calendar_events").Where("calendar_id", calendarId).Where("tenant", tenant)); db.ExecuteNonQuery(new SqlDelete("calendar_event_item").Where(Exp.In("event_id", data))); db.ExecuteNonQuery(new SqlDelete("calendar_event_user").Where(Exp.In("event_id", data))); db.ExecuteNonQuery(new SqlDelete("calendar_notifications").Where(Exp.In("event_id", data))); db.ExecuteNonQuery(new SqlDelete("calendar_event_history").Where("tenant", tenant).Where(Exp.In("event_id", data))); tr.Commit(); } } public void RemoveCaldavCalendar(string currentUserName, string email, string currentAccountPaswd, string encoded, string calDavGuid, Uri myUri, bool isShared = false) { var calDavServerUrl = myUri.Scheme + "://" + myUri.Host + "/caldav"; var calDavUrl = calDavServerUrl.Insert(calDavServerUrl.IndexOf("://") + 3, HttpUtility.UrlEncode(currentUserName) + ":" + HttpUtility.UrlEncode(currentAccountPaswd) + "@"); var requestUrl = calDavUrl + "/" + HttpUtility.UrlEncode(currentUserName) + "/" + (isShared ? calDavGuid + "-shared" : calDavGuid); try { var webRequest = (HttpWebRequest)WebRequest.Create(requestUrl); webRequest.Method = "DELETE"; webRequest.ContentType = "text/xml; charset=utf-8"; webRequest.Headers.Add("Authorization", "Basic " + encoded); using (var webResponse = webRequest.GetResponse()) using (var reader = new StreamReader(webResponse.GetResponseStream())){} } catch (Exception ex) { LogManager.GetLogger("ASC.Calendar").Error(ex); } } public void RemoveExternalCalendarData(string calendarId) { using (var tr = db.BeginTransaction()) { db.ExecuteNonQuery(new SqlDelete("calendar_calendar_user").Where("ext_calendar_id",calendarId)); tr.Commit(); } } public Todo GetTodoByUid(string todoUid) { var sql = new SqlQuery("calendar_todos t") .Select("t.id") .InnerJoin("calendar_calendars c", Exp.EqColumns("c.id", "t.calendar_id")) .Where("t.tenant", TenantManager.GetCurrentTenant().TenantId) .Where(Exp.Like("t.uid", todoUid)) .Where("t.owner_id", AuthContext.CurrentAccount.ID) .Where("c.owner_id", AuthContext.CurrentAccount.ID) .Where("c.ical_url", null); var todoId = db.ExecuteScalar(sql); return todoId == 0 ? null : GetTodoById(todoId); } public Todo GetTodoIdByUid(string uid, int calendarId) { var sql = new SqlQuery("calendar_todos") .Select("id") .Where(Exp.Like("uid", uid)) .Where("calendar_id", calendarId); var todoId = db.ExecuteScalar(sql); return todoId == 0 ? null : GetTodoById(todoId); } public Todo UpdateTodo(string id, int calendarId, Guid ownerId, string name, string description, DateTime utcStartDate, string uid, DateTime completed) { int todoId; using (var tr = db.BeginTransaction()) { todoId = db.ExecuteScalar(new SqlUpdate("calendar_todos") .Set("name", name) .Set("description", description) .Set("calendar_id", calendarId) .Set("owner_id", ownerId) .Set("start_date", utcStartDate == DateTime.MinValue ? null : utcStartDate.ToString("yyyy-MM-dd HH:mm:ss")) .Set("uid", GetEventUid(uid)) .Set("completed", completed == DateTime.MinValue ? null : completed.ToString("yyyy-MM-dd HH:mm:ss")) .Where(Exp.Eq("id", id))); tr.Commit(); } return GetTodoById(int.Parse(id)); } public Todo CreateTodo(int calendarId, Guid ownerId, string name, string description, DateTime utcStartDate, string uid, DateTime completed) { int todoId; using (var tr = db.BeginTransaction()) { todoId = db.ExecuteScalar(new SqlInsert("calendar_todos") .InColumnValue("id", 0) .InColumnValue("tenant", TenantManager.GetCurrentTenant ().TenantId) .InColumnValue("name", name) .InColumnValue("description", description) .InColumnValue("calendar_id", calendarId) .InColumnValue("owner_id", ownerId) .InColumnValue("start_date", utcStartDate == DateTime.MinValue ? null : utcStartDate.ToString("yyyy-MM-dd HH:mm:ss")) .InColumnValue("uid", GetEventUid(uid)) .InColumnValue("completed", completed == DateTime.MinValue ? null : completed.ToString("yyyy-MM-dd HH:mm:ss")) .Identity(0, 0, true)); tr.Commit(); } return GetTodoById(todoId); } public Todo GetTodoById(int todoId) { var todos = GetTodosByIds(new object[] { todoId }, AuthContext.CurrentAccount.ID); if (todos.Count > 0) return todos[0]; return null; } public List GetTodosByIds(object[] todoIds, Guid userId, int tenantId = -1) { var cc = new ColumnCollection(); var tdId = cc.RegistryColumn("td.id"); var tdName = cc.RegistryColumn("td.name"); var tdDescription = cc.RegistryColumn("td.description"); var tdTenant = cc.RegistryColumn("td.tenant"); var tdCalId = cc.RegistryColumn("td.calendar_id"); var tdStartDate = cc.RegistryColumn("td.start_date"); var tdCompleted = cc.RegistryColumn("td.completed"); var tdOwner = cc.RegistryColumn("td.owner_id"); var tdUid = cc.RegistryColumn("td.uid"); var data = new List(); if (todoIds.Length > 0) { if (tenantId != -1) { data = db.ExecuteList(new SqlQuery(_todoTable) .Select(cc.SelectQuery) .Where(Exp.In(tdId.Name, todoIds)) .Where("tenant", tenantId)); } else { data = db.ExecuteList(new SqlQuery(_todoTable) .Select(cc.SelectQuery) .Where(Exp.In(tdId.Name, todoIds))); } } //parsing var todos = new List(); foreach (var r in data) { var td = todos.Find( e => String.Equals(e.Id, tdId.Parse(r), StringComparison.InvariantCultureIgnoreCase)); if (td == null) { td = new Todo() { Id = tdId.Parse(r), Name = tdName.Parse(r), Description = tdDescription.Parse(r), TenantId = tdTenant.Parse(r), CalendarId = tdCalId.Parse(r), UtcStartDate = tdStartDate.Parse(r), Completed = tdCompleted.Parse(r), OwnerId = tdOwner.Parse(r), Uid = tdUid.Parse(r) }; todos.Add(td); } } return todos; } public List LoadTodos(int calendarId, Guid userId, int tenantId, DateTime utcStartDate, DateTime utcEndDate) { var sqlQuery = new SqlQuery(_todoTable) .Select("td.id") .Where( Exp.Eq("td.calendar_id", calendarId) & Exp.Eq("td.tenant", tenantId) ); var tdIds = db.ExecuteList(sqlQuery).Select(r => r[0]); return GetTodosByIds(tdIds.ToArray(), userId, tenantId); } internal List LoadSharedEvents(Guid userId, int tenantId, DateTime utcStartDate, DateTime utcEndDate) { var groups = UserManager.GetUserGroups(userId).Select(g => g.ID).ToList(); groups.AddRange(UserManager.GetUserGroups(userId, Core.Users.Constants.SysGroupCategoryId).Select(g => g.ID)); var evIds = db.ExecuteList( new SqlQuery(_eventTable).Select("evt.id") .InnerJoin(_eventItemTable, Exp.EqColumns("evt_itm.event_id", "evt.id")) .Where("evt.tenant", tenantId) .Where( (Exp.Eq("evt_itm.item_id", userId) | (Exp.In("evt_itm.item_id", groups.ToArray()) & Exp.Eq("evt_itm.is_group", true))) & Exp.Eq("evt.tenant", tenantId) & ((Exp.Ge("evt.start_date", utcStartDate) & Exp.Le("evt.start_date", utcEndDate) & Exp.Eq("evt.rrule", "") | !Exp.Eq("evt.rrule", ""))) & !Exp.Eq("evt.owner_id", userId) & !Exp.Exists(new SqlQuery("calendar_event_user evt_usr").Select("evt_usr.event_id") .Where(Exp.EqColumns("evt_usr.event_id", "evt.id") & Exp.Eq("evt_usr.user_id", userId) & Exp.Eq("evt_usr.is_unsubscribe", true))) )).Select(r => r[0]); return GetEventsByIds(evIds.ToArray(), userId, tenantId); } public List LoadEvents(int calendarId, Guid userId, int tenantId, DateTime utcStartDate, DateTime utcEndDate) { var sqlQuery = new SqlQuery(_eventTable) .Select("evt.id") .Where( Exp.Eq("evt.calendar_id", calendarId) & Exp.Eq("evt.tenant", tenantId) & ( !Exp.Eq("evt.rrule", "") | (Exp.Eq("evt.rrule", "") & ( (Exp.Ge("evt.start_date", utcStartDate) & Exp.Le("evt.end_date", utcEndDate)) | (Exp.Le("evt.start_date", utcStartDate) & Exp.Ge("evt.end_date", utcStartDate)) | (Exp.Le("evt.start_date", utcEndDate) & Exp.Ge("evt.end_date", utcEndDate)) ) ) ) ); var evIds = db.ExecuteList(sqlQuery).Select(r => r[0]); return GetEventsByIds(evIds.ToArray(), userId, tenantId); } public Event GetEventById(int eventId) { var events = GetEventsByIds(new object[] { eventId }, AuthContext.CurrentAccount.ID); if (events.Count > 0) return events[0]; return null; } public List GetEventsByIds(object[] evtIds, Guid userId, int tenantId = -1) { var cc = new ColumnCollection(); var eId = cc.RegistryColumn("evt.id"); var eName = cc.RegistryColumn("evt.name"); var eDescription = cc.RegistryColumn("evt.description"); var eTenant = cc.RegistryColumn("evt.tenant"); var eCalId = cc.RegistryColumn("evt.calendar_id"); var eStartDate = cc.RegistryColumn("evt.start_date"); var eEndDate = cc.RegistryColumn("evt.end_date"); var eUpdateDate = cc.RegistryColumn("evt.update_date"); var eIsAllDay = cc.RegistryColumn("evt.all_day_long"); var eRRule = cc.RegistryColumn("evt.rrule"); var eOwner = cc.RegistryColumn("evt.owner_id"); var usrAlertType = cc.RegistryColumn("evt_usr.alert_type"); var eAlertType = cc.RegistryColumn("evt.alert_type"); var eUid = cc.RegistryColumn("evt.uid"); var eStatus = cc.RegistryColumn("evt.status"); var data = new List(); if (evtIds.Length > 0) { if (tenantId != -1) { data = db.ExecuteList(new SqlQuery(_eventTable) .LeftOuterJoin("calendar_event_user evt_usr", Exp.EqColumns(eId.Name, "evt_usr.event_id") & Exp.Eq("evt_usr.user_id", userId)) .Select(cc.SelectQuery) .Where(Exp.In(eId.Name, evtIds)) .Where("tenant", tenantId)); } else { data = db.ExecuteList(new SqlQuery(_eventTable) .LeftOuterJoin("calendar_event_user evt_usr", Exp.EqColumns(eId.Name, "evt_usr.event_id") & Exp.Eq("evt_usr.user_id", userId)) .Select(cc.SelectQuery) .Where(Exp.In(eId.Name, evtIds))); } } var cc1 = new ColumnCollection(); var evId = cc1.RegistryColumn("evt_itm.event_id"); var itemId = cc1.RegistryColumn("evt_itm.item_id"); var itemIsGroup = cc1.RegistryColumn("evt_itm.is_group"); var sharingData = new List(); if (evtIds.Length > 0) { sharingData = db.ExecuteList(new SqlQuery(_eventItemTable).Select(cc1.SelectQuery) .Where(Exp.In(evId.Name, evtIds))); } //parsing var events = new List(); foreach (var r in data) { var ev = events.Find( e => String.Equals(e.Id, eId.Parse(r), StringComparison.InvariantCultureIgnoreCase)); if (ev == null) { ev = new Event { Id = eId.Parse(r), Name = eName.Parse(r), Description = eDescription.Parse(r), TenantId = eTenant.Parse(r), CalendarId = eCalId.Parse(r), UtcStartDate = eStartDate.Parse(r), UtcEndDate = eEndDate.Parse(r), UtcUpdateDate = eUpdateDate.Parse(r), AllDayLong = eIsAllDay.Parse(r), OwnerId = eOwner.Parse(r), AlertType = (usrAlertType.IsNull(r)) ? (EventAlertType) eAlertType.Parse(r) : (EventAlertType) usrAlertType.Parse(r), RecurrenceRule = eRRule.Parse(r), Uid = eUid.Parse(r), Status = (EventStatus) eStatus.Parse(r) }; events.Add(ev); } foreach (var row in sharingData) { if (String.Equals(evId.Parse(row), ev.Id, StringComparison.InvariantCultureIgnoreCase)) { ev.SharingOptions.PublicItems.Add(new SharingOptions.PublicItem { Id = itemId.Parse(row), IsGroup = itemIsGroup.Parse(row) }); } } } return events; } public Event GetEventByUid(string eventUid) { var sql = new SqlQuery("calendar_events e") .Select("e.id") .InnerJoin("calendar_calendars c", Exp.EqColumns("c.id", "e.calendar_id")) .Where("e.tenant", TenantManager.GetCurrentTenant().TenantId) .Where("e.uid", eventUid) .Where("e.owner_id", AuthContext.CurrentAccount.ID) .Where("c.owner_id", AuthContext.CurrentAccount.ID) .Where("c.ical_url", null); var eventId = db.ExecuteScalar(sql); return eventId == 0 ? null : GetEventById(eventId); } public Event GetEventOnlyByUid(string eventUid) { var sql = new SqlQuery("calendar_events e") .Select("e.id") .Where("e.tenant", TenantManager.GetCurrentTenant().TenantId) .Where("e.uid", eventUid); var eventId = db.ExecuteScalar(sql); return eventId == 0 ? null : GetEventById(eventId); } public void SetEventUid(int eventId, string uid) { using (var tr = db.BeginTransaction()) { db.ExecuteNonQuery(new SqlUpdate("calendar_events") .Set("uid", uid) .Where(Exp.Eq("id", eventId))); tr.Commit(); } } public void UnsubscribeFromEvent(int eventID, Guid userId) { using (var tr = db.BeginTransaction()) { if (db.ExecuteNonQuery(new SqlDelete("calendar_event_item").Where(Exp.Eq("event_id", eventID) & Exp.Eq("item_id", userId) & Exp.Eq("is_group", false))) == 0) { db.ExecuteNonQuery(new SqlInsert("calendar_event_user", true).InColumnValue("event_id", eventID) .InColumnValue("user_id", userId) .InColumnValue("is_unsubscribe", true)); } db.ExecuteNonQuery(new SqlDelete("calendar_notifications").Where(Exp.Eq("event_id", eventID) & Exp.Eq("user_id", userId))); tr.Commit(); } } public void RemoveEvent(int eventId) { using (var tr = db.BeginTransaction()) { var tenant = TenantManager.GetCurrentTenant().TenantId; db.ExecuteNonQuery(new SqlDelete("calendar_events").Where("id", eventId).Where("tenant", tenant)); db.ExecuteNonQuery(new SqlDelete("calendar_event_item").Where("event_id", eventId)); db.ExecuteNonQuery(new SqlDelete("calendar_event_user").Where("event_id", eventId)); db.ExecuteNonQuery(new SqlDelete("calendar_notifications").Where("event_id", eventId)); db.ExecuteNonQuery(new SqlDelete("calendar_event_history").Where("tenant", tenant).Where("event_id", eventId)); tr.Commit(); } } public Event CreateEvent(int calendarId, Guid ownerId, string name, string description, DateTime utcStartDate, DateTime utcEndDate, RecurrenceRule rrule, EventAlertType alertType, bool isAllDayLong, List publicItems, string uid, EventStatus status, DateTime createDate) { int eventId; using (var tr = db.BeginTransaction()) { eventId = db.ExecuteScalar(new SqlInsert("calendar_events") .InColumnValue("id", 0) .InColumnValue("tenant", TenantManager.GetCurrentTenant ().TenantId) .InColumnValue("name", name) .InColumnValue("description", description) .InColumnValue("calendar_id", calendarId) .InColumnValue("owner_id", ownerId) .InColumnValue("start_date", utcStartDate.ToString( "yyyy-MM-dd HH:mm:ss")) .InColumnValue("end_date", utcEndDate.ToString("yyyy-MM-dd HH:mm:ss")) .InColumnValue("update_date", createDate.ToString("yyyy-MM-dd HH:mm:ss")) .InColumnValue("all_day_long", isAllDayLong) .InColumnValue("rrule", rrule.ToString()) .InColumnValue("alert_type", (int) alertType) .InColumnValue("uid", GetEventUid(uid)) .InColumnValue("status", (int) status) .Identity(0, 0, true)); foreach (var item in publicItems) { db.ExecuteNonQuery(new SqlInsert("calendar_event_item") .InColumnValue("event_id", eventId) .InColumnValue("item_id", item.Id) .InColumnValue("is_group", item.IsGroup)); } //update notifications UpdateEventNotifications(eventId, calendarId, utcStartDate, alertType, rrule, publicItems, null, isAllDayLong); tr.Commit(); } return GetEventById(eventId); } public Event UpdateEvent(int eventId, int calendarId, Guid ownerId, string name, string description, DateTime utcStartDate, DateTime utcEndDate, RecurrenceRule rrule, EventAlertType alertType, bool isAllDayLong, List publicItems, EventStatus status, DateTime createDate ) { using (var tr = db.BeginTransaction()) { var query = new SqlUpdate("calendar_events") .Set("name", name) .Set("description", description) .Set("calendar_id", calendarId) .Set("owner_id", ownerId) .Set("start_date", utcStartDate.ToString("yyyy-MM-dd HH:mm:ss")) .Set("end_date", utcEndDate.ToString("yyyy-MM-dd HH:mm:ss")) .Set("update_date", createDate.ToString("yyyy-MM-dd HH:mm:ss")) .Set("all_day_long", isAllDayLong) .Set("rrule", rrule.ToString()) .Set("status", (int) status) .Where(Exp.Eq("id", eventId)); if (ownerId.Equals(AuthContext.CurrentAccount.ID)) query = query.Set("alert_type", (int) alertType); else db.ExecuteNonQuery(new SqlInsert("calendar_event_user", true) .InColumnValue("event_id", eventId) .InColumnValue("user_id", AuthContext.CurrentAccount.ID) .InColumnValue("alert_type", alertType)); db.ExecuteNonQuery(query); var userIds = db.ExecuteList(new SqlQuery("calendar_event_user") .Select("user_id") .Where("event_id", eventId)) .Select(r => new Guid(Convert.ToString(r[0]))); foreach (var usrId in userIds) { if (!publicItems.Exists(i => (i.IsGroup && UserManager.IsUserInGroup(usrId, i.Id)) || (!i.IsGroup && i.Id.Equals(usrId)))) { db.ExecuteNonQuery(new SqlDelete("calendar_event_user") .Where(Exp.Eq("user_id", usrId) & Exp.Eq("event_id", eventId))); } } db.ExecuteNonQuery(new SqlDelete("calendar_event_item").Where("event_id", eventId)); foreach (var item in publicItems) { db.ExecuteNonQuery(new SqlInsert("calendar_event_item") .InColumnValue("event_id", eventId) .InColumnValue("item_id", item.Id) .InColumnValue("is_group", item.IsGroup)); } //update notifications var baseAlertType = db.ExecuteList(new SqlQuery("calendar_events").Select("alert_type").Where("id", eventId)) .Select(r => (EventAlertType) Convert.ToInt32(r[0])).First(); UpdateEventNotifications(eventId, calendarId, utcStartDate, baseAlertType, rrule, publicItems, null, isAllDayLong); tr.Commit(); } return GetEventById(eventId); } public EventHistory GetEventHistory(string eventUid) { var sql = new SqlQuery("calendar_event_history h") .Select("h.calendar_id") .Select("h.event_uid") .Select("h.event_id") .Select("h.ics") .InnerJoin("calendar_events e", Exp.EqColumns("e.uid", "h.event_uid")) .InnerJoin("calendar_calendars c", Exp.EqColumns("c.id", "h.calendar_id")) .Where("h.tenant", TenantManager.GetCurrentTenant().TenantId) .Where("h.event_uid", eventUid) .Where("e.owner_id", AuthContext.CurrentAccount.ID) .Where("c.owner_id", AuthContext.CurrentAccount.ID) .Where("c.ical_url", null); var items = db.ExecuteList(sql).ConvertAll(ToEventHistory); return items.Count > 0 ? items[0] : null; } public List GetEventsHistory(int[] eventIds) { var sql = new SqlQuery("calendar_event_history") .Select("calendar_id") .Select("event_uid") .Select("event_id") .Select("ics") .Where("tenant", TenantManager.GetCurrentTenant().TenantId) .Where(Exp.In("event_id", eventIds)); return db.ExecuteList(sql).ConvertAll(ToEventHistory); } public EventHistory GetEventHistory(int eventId) { var items = GetEventsHistory(new [] { eventId }); return items.Count > 0 ? items[0] : null; } public EventHistory AddEventHistory(int calendarId, string eventUid, int eventId, string ics) { var icsCalendars = DDayICalParser.DeserializeCalendar(ics); var icsCalendar = icsCalendars == null ? null : icsCalendars.FirstOrDefault(); var icsEvents = icsCalendar == null ? null : icsCalendar.Events; var icsEvent = icsEvents == null ? null : icsEvents.FirstOrDefault(); if (icsEvent == null) return null; EventHistory history; using (var tr = db.BeginTransaction()) { ISqlInstruction sql; history = GetEventHistory(eventId); if (history == null) { history = new EventHistory(calendarId, eventUid, eventId, ics); sql = new SqlInsert("calendar_event_history") .InColumnValue("tenant", TenantManager.GetCurrentTenant().TenantId) .InColumnValue("calendar_id", calendarId) .InColumnValue("event_uid", eventUid) .InColumnValue("event_id", eventId) .InColumnValue("ics", history.Ics); } else { var exist = history.History .Where(x => x.Method == icsCalendar.Method) .Select(x => x.Events.FirstOrDefault()) .Any(x => x.Uid == icsEvent.Uid && x.Sequence == icsEvent.Sequence && DDayICalParser.ToUtc(x.DtStamp) == DDayICalParser.ToUtc(icsEvent.DtStamp)); if (exist) return history; history.Ics = history.Ics + Environment.NewLine + ics; sql = new SqlUpdate("calendar_event_history") .Set("ics", history.Ics) .Where("tenant", TenantManager.GetCurrentTenant().TenantId) .Where("calendar_id", calendarId) .Where("event_uid", eventUid); } db.ExecuteNonQuery(sql); tr.Commit(); } return history; } public void RemoveEventHistory(int calendarId, string eventUid) { var sql = new SqlDelete("calendar_event_history") .Where("tenant", TenantManager.GetCurrentTenant().TenantId) .Where("calendar_id", calendarId) .Where("event_uid", eventUid); db.ExecuteNonQuery(sql); } public void RemoveEventHistory(int eventId) { var sql = new SqlDelete("calendar_event_history") .Where("tenant", TenantManager.GetCurrentTenant().TenantId) .Where("event_id", eventId); db.ExecuteNonQuery(sql); } private static EventHistory ToEventHistory(object[] row) { return new EventHistory(Convert.ToInt32(row[0]), Convert.ToString(row[1]), Convert.ToInt32(row[2]), Convert.ToString(row[3])); } public static string GetEventUid(string uid, string id = null) { if (!string.IsNullOrEmpty(uid)) return uid; return string.Format("{0}@onlyoffice.com", string.IsNullOrEmpty(id) ? Guid.NewGuid().ToString() : id); } #region Event Notifications internal static int GetBeforeMinutes(EventAlertType eventAlertType) { switch (eventAlertType) { case EventAlertType.Day: return -24 * 60; case EventAlertType.FifteenMinutes: return -15; case EventAlertType.FiveMinutes: return -5; case EventAlertType.HalfHour: return -30; case EventAlertType.Hour: return -60; case EventAlertType.TwoHours: return -120; } return 0; } private DateTime GetNextAlertDate(DateTime utcStartDate, RecurrenceRule rrule, EventAlertType eventAlertType, TimeZoneInfo timeZone, bool isAllDayLong) { if (eventAlertType == EventAlertType.Never) return DateTime.MinValue; var offset = timeZone.GetOffset(); var localFromDate = DateTime.UtcNow.Add(offset); var localStartDate = isAllDayLong ? utcStartDate : utcStartDate.Add(offset); var dates = rrule.GetDates(localStartDate, localFromDate, 3); for (var i = 0; i < dates.Count; i++) { dates[i] = dates[i].Subtract(offset); } foreach (var d in dates) { var dd = d.AddMinutes(GetBeforeMinutes(eventAlertType)); if (dd > DateTime.UtcNow) return dd; } return DateTime.MinValue; } private class UserAlertType { public Guid UserId { get; set; } public EventAlertType AlertType { get; set; } public TimeZoneInfo TimeZone { get; set; } public UserAlertType(Guid userId, EventAlertType alertType, TimeZoneInfo timeZone) { UserId = userId; AlertType = alertType; TimeZone = timeZone; } } private void UpdateEventNotifications(int eventId, int calendarId, DateTime eventUtcStartDate, EventAlertType baseEventAlertType, RecurrenceRule rrule, IEnumerable eventPublicItems, IEnumerable calendarPublicItems, bool isAllDayLong) { var cc = new ColumnCollection(); var userIdCol = cc.RegistryColumn("user_id"); var alertTypeCol = cc.RegistryColumn("alert_type"); var isUnsubscribeCol = cc.RegistryColumn("is_unsubscribe"); var eventUsersData = db.ExecuteList(new SqlQuery("calendar_event_user").Select(cc.SelectQuery).Where(Exp.Eq("event_id", eventId))); var calendarData = db.ExecuteList(new SqlQuery("calendar_calendars").Select("alert_type", "owner_id", "time_zone").Where(Exp.Eq("id", calendarId))); var calendarAlertType = calendarData.Select(r => (EventAlertType)Convert.ToInt32(r[0])).First(); var calendarOwner = calendarData.Select(r => new Guid(Convert.ToString(r[1]))).First(); var calendarTimeZone = calendarData.Select(r => TimeZoneConverter.GetTimeZone(Convert.ToString(r[2]))).First(); var eventUsers = new List(); #region shared event's data if (eventPublicItems == null) { eventPublicItems = new List(db.ExecuteList(new SqlQuery("calendar_event_item").Select("item_id", "is_group").Where(Exp.Eq("event_id", eventId))) .Select(r => new SharingOptions.PublicItem { Id = new Guid(Convert.ToString(r[0])), IsGroup = Convert.ToBoolean(r[1]) })); } foreach (var item in eventPublicItems) { if (item.IsGroup) eventUsers.AddRange(UserManager.GetUsersByGroup(item.Id).Select(u => new UserAlertType(u.ID, baseEventAlertType, calendarTimeZone))); else eventUsers.Add(new UserAlertType(item.Id, baseEventAlertType, calendarTimeZone)); } //remove calendar owner eventUsers.RemoveAll(u => u.UserId.Equals(calendarOwner)); //remove unsubscribed and exec personal alert_type if (eventUsers.Count > 0) { foreach (var r in eventUsersData) { if (isUnsubscribeCol.Parse(r)) eventUsers.RemoveAll(u => u.UserId.Equals(userIdCol.Parse(r))); else eventUsers.ForEach(u => { if (u.UserId.Equals(userIdCol.Parse(r))) u.AlertType = (EventAlertType)alertTypeCol.Parse(r); }); } } //remove and exec sharing calendar options if (eventUsers.Count > 0) { var extCalendarAlertTypes = db.ExecuteList(new SqlQuery("calendar_calendar_user cu") .Select("cu.user_id", "cu.alert_type", "cu.is_accepted", "cu.time_zone") .Where(Exp.Eq("cu.ext_calendar_id", SharedEventsCalendar.CalendarId) & Exp.In("cu.user_id", eventUsers.Select(u => u.UserId).ToArray()))); foreach (var r in extCalendarAlertTypes) { if (!Convert.ToBoolean(r[2])) { //remove unsubscribed from shared events calendar eventUsers.RemoveAll(u => u.UserId.Equals(new Guid(Convert.ToString(r[0])))); continue; } eventUsers.ForEach(u => { if (u.UserId.Equals(new Guid(Convert.ToString(r[0])))) u.TimeZone = ((r[3] == null || r[3] == DBNull.Value) ? calendarTimeZone : TimeZoneConverter.GetTimeZone(Convert.ToString(r[3]))); if (u.AlertType == EventAlertType.Default && u.UserId.Equals(new Guid(Convert.ToString(r[0])))) u.AlertType = (EventAlertType)Convert.ToInt32(r[1]); }); } eventUsers.ForEach(u => { if (u.AlertType == EventAlertType.Default) u.AlertType = EventAlertType.Hour; }); } #endregion #region calendar's data if (calendarPublicItems == null) { calendarPublicItems = new List(db.ExecuteList(new SqlQuery("calendar_calendar_item").Select("item_id", "is_group").Where(Exp.Eq("calendar_id", calendarId))) .Select(r => new SharingOptions.PublicItem { Id = new Guid(Convert.ToString(r[0])), IsGroup = Convert.ToBoolean(r[1]) })); } //calendar users var calendarUsers = new List(); foreach (var item in eventPublicItems) { if (item.IsGroup) calendarUsers.AddRange(UserManager.GetUsersByGroup(item.Id).Select(u => new UserAlertType(u.ID, baseEventAlertType, calendarTimeZone))); else calendarUsers.Add(new UserAlertType(item.Id, baseEventAlertType, calendarTimeZone)); } calendarUsers.Add(new UserAlertType(calendarOwner, baseEventAlertType, calendarTimeZone)); //remove event's users calendarUsers.RemoveAll(u => eventUsers.Exists(eu => eu.UserId.Equals(u.UserId))); //calendar options if (calendarUsers.Count > 0) { //set personal alert_type foreach (var r in eventUsersData) { eventUsers.ForEach(u => { if (u.UserId.Equals(new Guid(Convert.ToString(r[0])))) u.AlertType = (EventAlertType)(Convert.ToInt32(r[1])); }); } var calendarAlertTypes = db.ExecuteList(new SqlQuery("calendar_calendar_user") .Select("user_id", "alert_type", "is_accepted", "time_zone") .Where(Exp.Eq("calendar_id", calendarId) & Exp.In("user_id", calendarUsers.Select(u => u.UserId).ToArray()))); foreach (var r in calendarAlertTypes) { if (!Convert.ToBoolean(r[2])) { //remove unsubscribed calendarUsers.RemoveAll(u => u.UserId.Equals(new Guid(Convert.ToString(r[0])))); continue; } calendarUsers.ForEach(u => { if (u.UserId.Equals(new Guid(Convert.ToString(r[0])))) u.TimeZone = ((r[3] == null || r[3] == DBNull.Value) ? calendarTimeZone : TimeZoneConverter.GetTimeZone(Convert.ToString(r[3]))); if (u.AlertType == EventAlertType.Default && u.UserId.Equals(new Guid(Convert.ToString(r[0])))) u.AlertType = (EventAlertType)Convert.ToInt32(r[1]); }); } calendarUsers.ForEach(u => { if (u.AlertType == EventAlertType.Default) u.AlertType = calendarAlertType; }); } #endregion //clear notifications db.ExecuteNonQuery(new SqlDelete("calendar_notifications").Where("event_id", eventId)); eventUsers.AddRange(calendarUsers); foreach (var u in eventUsers) { //todo: recount var alertDate = GetNextAlertDate(eventUtcStartDate, rrule, u.AlertType, u.TimeZone, isAllDayLong); if (!alertDate.Equals(DateTime.MinValue)) { db.ExecuteNonQuery(new SqlInsert("calendar_notifications", true).InColumnValue("user_id", u.UserId) .InColumnValue("event_id", eventId) .InColumnValue("rrule", rrule.ToString()) .InColumnValue("alert_type", (int)u.AlertType) .InColumnValue("tenant", TenantManager.GetCurrentTenant().TenantId) .InColumnValue("notify_date", alertDate) .InColumnValue("time_zone", u.TimeZone.Id)); } } } public List ExtractAndRecountNotifications(DateTime utcDate) { List data; using (var tr = db.BeginTransaction()) { var cc = new ColumnCollection(); var userIdCol = cc.RegistryColumn("user_id"); var tenantCol = cc.RegistryColumn("tenant"); var eventIdCol = cc.RegistryColumn("event_id"); var notifyDateCol = cc.RegistryColumn("notify_date"); var rruleCol = cc.RegistryColumn("rrule"); var alertTypeCol = cc.RegistryColumn("alert_type"); var timeZoneCol = cc.RegistryColumn("time_zone"); data = new List(db.ExecuteList(new SqlQuery("calendar_notifications").Select(cc.SelectQuery) .Where(Exp.Le(notifyDateCol.Name, utcDate))) .Select(r => new EventNotificationData { UserId = userIdCol.Parse(r), TenantId = tenantCol.Parse(r), EventId = eventIdCol.Parse(r), NotifyUtcDate = notifyDateCol.Parse(r), RRule = rruleCol.Parse(r), AlertType = (EventAlertType)alertTypeCol.Parse(r), TimeZone = timeZoneCol.Parse(r) })); var events = GetEventsByIds(data.Select(d => (object)d.EventId).Distinct().ToArray(), Guid.Empty); data.ForEach(d => d.Event = events.Find(e => String.Equals(e.Id, d.EventId.ToString(CultureInfo.InvariantCulture), StringComparison.InvariantCultureIgnoreCase))); foreach (var d in data) { if (d.RRule.Freq == Frequency.Never) db.ExecuteNonQuery(new SqlDelete("calendar_notifications").Where(Exp.Eq("user_id", d.UserId) & Exp.Eq("event_id", d.EventId))); else { var alertDate = GetNextAlertDate(d.Event.UtcStartDate, d.RRule, d.AlertType, d.TimeZone, d.Event.AllDayLong); if (!alertDate.Equals(DateTime.MinValue)) { db.ExecuteNonQuery(new SqlInsert("calendar_notifications", true).InColumnValue("user_id", d.UserId) .InColumnValue("event_id", d.EventId) .InColumnValue("rrule", d.RRule.ToString()) .InColumnValue("alert_type", (int)d.AlertType) .InColumnValue("tenant", d.TenantId) .InColumnValue("notify_date", alertDate) .InColumnValue("time_zone", d.TimeZone.Id)); } else db.ExecuteNonQuery(new SqlDelete("calendar_notifications").Where(Exp.Eq("user_id", d.UserId) & Exp.Eq("event_id", d.EventId))); } } tr.Commit(); } return data; } #endregion public void Dispose() { if (HttpContext.Current == null && db != null) { db.Dispose(); } }*/ } public static class CalendarDataProviderExtention { public static IServiceCollection AddCalendarDataProviderService(this IServiceCollection services) { services.AddScoped(); return services; } } }