int SynchronizeCalendar(DateTime utcModifiedAfter) { int itemsUpdated = 0; try { var modifiedEvents = GetModifiedCalendarEvents(utcModifiedAfter); foreach (Event e in modifiedEvents) { Guid itemID = new Guid(e.ExtendedProperties.Private[ExtensionItemID]); Item item = storage.GetItem(user, itemID); if (item != null) { // Name, DueDate, EndDate, and Description (support Location?) item.Name = e.Summary; item.GetFieldValue(FieldNames.DueDate).Value = e.Start.DateTime; item.GetFieldValue(FieldNames.EndDate).Value = e.End.DateTime; FieldValue fvDescription = item.GetFieldValue(FieldNames.Description, (e.Description != null)); if (fvDescription != null) { fvDescription.Value = e.Description; } itemsUpdated++; } } if (itemsUpdated > 0) { storage.SaveChanges(); } } catch (Exception e) { TraceLog.TraceException("Could not get modified Calendar events", e); } return(itemsUpdated); }
// get or create an reference to the given entity in the UserFolder EntityRefs list public Item GetEntityRef(User user, ServerEntity entity) { Item entityRefsList = GetEntityRefsList(user); if (entityRefsList == null) { return(null); } var entityID = entity.ID.ToString(); try { // get existing reference to given entity if (storage.Items.Include("FieldValues").Any(i => i.UserID == user.ID && i.FolderID == entityRefsList.FolderID && i.ParentID == entityRefsList.ID && i.FieldValues.Any(fv => fv.FieldName == FieldNames.EntityRef && fv.Value == entityID))) { return(storage.Items.Include("FieldValues").Single(i => i.UserID == user.ID && i.FolderID == entityRefsList.FolderID && i.ParentID == entityRefsList.ID && i.FieldValues.Any(fv => fv.FieldName == FieldNames.EntityRef && fv.Value == entityID))); } else { // create new reference to given entity DateTime now = DateTime.UtcNow; var entityRefItemID = Guid.NewGuid(); var entityRefItem = new Item() { ID = entityRefItemID, Name = entity.Name, FolderID = entityRefsList.FolderID, UserID = user.ID, ItemTypeID = SystemItemTypes.Reference, ParentID = entityRefsList.ID, Created = now, LastModified = now, FieldValues = new List <FieldValue>() { new FieldValue() { ItemID = entityRefItemID, FieldName = FieldNames.EntityRef, Value = entityID }, new FieldValue() { ItemID = entityRefItemID, FieldName = FieldNames.EntityType, Value = entity.GetType().Name }, } }; storage.Items.Add(entityRefItem); storage.SaveChanges(); TraceLog.TraceInfo(String.Format("Created entity ref item {0} for user {1}", entity.Name, user.Name)); return(entityRefItem); } } catch (Exception ex) { TraceLog.TraceException(String.Format("Created entity ref item {0} for user {1}", entity.Name, user.Name), ex); return(null); } }
public static bool DeleteItemChildrenRecursively(UserStorageContext storageContext, Item item) { var children = storageContext.Items.Where(i => i.ParentID == item.ID).ToList(); bool commit = false; foreach (var c in children) { DeleteItemChildrenRecursively(storageContext, c); storageContext.Items.Remove(c); commit = true; } // commit deletion of all children at the same layer together if (commit) { storageContext.SaveChanges(); } return commit; }
public static bool DeleteItemReferences(User currentUser, UserStorageContext storageContext, Item item) { string itemID = item.ID.ToString(); var itemRefs = storageContext.Items.Include("FieldValues"). Where(i => i.UserID == currentUser.ID && i.ItemTypeID == SystemItemTypes.Reference && i.FieldValues.Any(fv => fv.FieldName == FieldNames.EntityRef && fv.Value == itemID)).ToList(); bool commit = false; foreach (var itemRef in itemRefs) { storageContext.Items.Remove(itemRef); commit = true; } // commit deletion of References if (commit) { storageContext.SaveChanges(); } return commit; }
// for getting initial access and renewal tokens via OAuth handshake IAuthorizationState GetGoogleTokens(WebServerClient client) { // check if authorization request already is in progress IAuthorizationState state = client.ProcessUserAuthorization(new HttpRequestInfo(System.Web.HttpContext.Current.Request)); if (state != null && (!string.IsNullOrEmpty(state.AccessToken) || !string.IsNullOrEmpty(state.RefreshToken))) { // store refresh token string username = System.Web.HttpContext.Current.User.Identity.Name; UserStorageContext storage = Storage.NewUserContext; User user = storage.Users.Include("UserCredentials").Single <User>(u => u.Name == username); user.AddCredential(UserCredential.GoogleConsent, state.AccessToken, state.AccessTokenExpirationUtc, state.RefreshToken); storage.SaveChanges(); return(state); } // otherwise make a new authorization request OutgoingWebResponse response = client.PrepareRequestUserAuthorization(GoogleClient.Scopes); response.Headers["Location"] += "&access_type=offline&approval_prompt=force"; response.Send(); // will throw a ThreadAbortException to prevent sending another response return(null); }
public static bool Import(string connectionString, string filename, string username) { var context = new UserStorageContext(connectionString); var user = context.Users. Include("ItemTypes.Fields"). Include("Tags"). FirstOrDefault(u => u.Name == username); if (user == null) { Console.WriteLine(String.Format("Import: user {0} not found", username)); return false; } // get the folders List<Folder> folders = context.Folders. Include("FolderUsers"). Include("Items.ItemTags"). Include("Items.FieldValues"). Where(f => f.UserID == user.ID && f.ItemTypeID != SystemItemTypes.System). ToList(); var userDataModel = new UserDataModel(context, user); try { User jsonUser = null; filename = filename ?? @"userdata.json"; // read the file and deserialize the data into a User class using (var stream = System.IO.File.Open(filename, FileMode.Open, FileAccess.Read)) using (var reader = new StreamReader(stream)) { var json = reader.ReadToEnd(); jsonUser = JsonSerializer.Deserialize<User>(json); } // reorder the folders by item type ID - this is to get locations before contacts before tasks // this heuristic relies on that order so that a task's location and contact references will be live in the DB before the task is imported // likewise, it needs the locations to be live in the DB before a contact (which may point to a location) is imported var jsonFolders = new List<Folder>(); foreach (var jsonFolder in jsonUser.Folders.Where(f => f.ItemTypeID == SystemItemTypes.Location)) jsonFolders.Add(jsonFolder); foreach (var jsonFolder in jsonUser.Folders.Where(f => f.ItemTypeID == SystemItemTypes.Contact)) jsonFolders.Add(jsonFolder); foreach (var jsonFolder in jsonUser.Folders.Where(f => f.ItemTypeID == SystemItemTypes.Grocery)) jsonFolders.Add(jsonFolder); foreach (var jsonFolder in jsonUser.Folders.Where(f => f.ItemTypeID == SystemItemTypes.ListItem)) jsonFolders.Add(jsonFolder); foreach (var jsonFolder in jsonUser.Folders.Where(f => f.ItemTypeID == SystemItemTypes.Task)) jsonFolders.Add(jsonFolder); foreach (var jsonFolder in jsonUser.Folders.Where(f => f.ItemTypeID == SystemItemTypes.Appointment)) jsonFolders.Add(jsonFolder); // process the serialized user folders foreach (var jsonFolder in jsonFolders) { // skip the $PhoneClient folder (currently import does not support merging $PhoneClient) // the difficulty is in merge semantics for individual items which have substructure (like PhoneSettings), // as well as ListMetadata for lists/folders that have the same names, but different ID's, from the lists in the DB // (e.g. Tasks, Groceries) if (jsonFolder.Name == SystemEntities.PhoneClient || jsonFolder.Name == SystemEntities.Client || jsonFolder.Name == SystemEntities.WebClient) continue; // reset some of the fields in the serialized structure to the database values jsonFolder.UserID = user.ID; // find the folder by name var folder = folders.FirstOrDefault(f => f.Name == jsonFolder.Name); if (folder == null) { // folder not found - add it (including all its children) using a new ID (in case the old one still exists in the DB) jsonFolder.ID = Guid.NewGuid(); folder = context.Folders.Add(jsonFolder); context.SaveChanges(); Console.WriteLine("Added folder " + folder.Name); } else { // folder found - don't add it, but process all the children and add as appropriate to the found folder Console.WriteLine("Found folder " + folder.Name); var rootChildren = jsonFolder.Items.Where(i => i.ParentID == null).ToList(); ImportItems(context, folder, jsonFolder, rootChildren, null, 1); } } context.SaveChanges(); Console.WriteLine(); } catch (Exception ex) { Console.WriteLine("DataImporter: import failed; ex: ", ex.Message); return false; } return true; }
static void ImportItems(UserStorageContext context, Folder folder, Folder jsonFolder, List<Item> jsonItems, Guid? parentID, int level) { // process each of the items passed in foreach (var jsonItem in jsonItems) { // reset some of the fields in the serialized structure to the database values jsonItem.UserID = folder.UserID; jsonItem.FolderID = folder.ID; // get the children of the current item from the serialized folder var jsonChildren = jsonFolder.Items.Where(i => i.ParentID == jsonItem.ID).ToList(); if (jsonChildren.Count > 0 || jsonItem.IsList) { // process the item as a list - find the database list by name var list = folder.Items.FirstOrDefault(i => i.Name == jsonItem.Name && i.ParentID == parentID); if (list != null) { // list found in database - change the ID of the serialized list to match the database for (int i = 0; i < level; i++) Console.Write(" "); Console.Write(jsonItem.IsList ? "Found list: " : "Found item: "); Console.WriteLine(jsonItem.Name); jsonItem.ID = list.ID; } else { // list not found in database - add the list to the DB using a new ID (in case the old one still exists in the DB) var id = Guid.NewGuid(); NewID[jsonItem.ID] = id; jsonItem.ID = id; list = context.Items.Add(jsonItem); context.SaveChanges(); for (int i = 0; i < level; i++) Console.Write(" "); Console.Write(jsonItem.IsList ? "Added list: " : "Added item: "); Console.WriteLine(jsonItem.Name); } // fix the parent ID's for all the children foreach (var i in jsonChildren) i.ParentID = jsonItem.ID; // recursively import this list's children ImportItems(context, folder, jsonFolder, jsonChildren, jsonItem.ID, level + 1); // fix any fieldvalues that are pointing to old guids foreach (var fv in jsonItem.FieldValues) { Guid guid; if (Guid.TryParse(fv.Value, out guid)) { Guid newID; if (NewID.TryGetValue(new Guid(fv.Value), out newID)) fv.Value = newID.ToString(); } } context.SaveChanges(); } else { // this is a singleton (not a list) - add it to the DB using a new ID (in case the old one still exists in the DB) var id = Guid.NewGuid(); NewID[jsonItem.ID] = id; // if this is a reference, fix the ref ID if (jsonItem.ItemTypeID == SystemItemTypes.Reference) { var refID = jsonItem.GetFieldValue(FieldNames.EntityRef); if (refID != null && !String.IsNullOrEmpty(refID.Value)) { Guid newID; if (NewID.TryGetValue(new Guid(refID.Value), out newID)) refID.Value = newID.ToString(); } } jsonItem.ID = id; context.Items.Add(jsonItem); context.SaveChanges(); for (int i = 0; i < level; i++) Console.Write(" "); Console.WriteLine("Added item " + jsonItem.Name); } } }
// update constants in User database to current version defined in EntityConstants public bool VersionConstants(string me) { try { bool updateDB = false; if (Versions.Any(v => v.VersionType == DatabaseVersion.Constants && v.VersionString == UserConstants.ConstantsVersion) == false) { // no database - create and lock the new version entry TraceLog.TraceInfo(String.Format("User database version {0} not found", UserConstants.ConstantsVersion)); // remove an existing database version (there should never be more than one) foreach (var existingVersion in Versions.Where(v => v.VersionType == DatabaseVersion.Constants).ToList()) { Versions.Remove(existingVersion); } SaveChanges(); // create the new version entry DatabaseVersion ver = new DatabaseVersion() { VersionType = DatabaseVersion.Constants, VersionString = UserConstants.ConstantsVersion, Status = me }; Versions.Add(ver); SaveChanges(); updateDB = true; } else { var dbVersion = Versions.Single(v => v.VersionType == DatabaseVersion.Constants && v.VersionString == UserConstants.ConstantsVersion); if (dbVersion.Status == DatabaseVersion.Corrupted) { // try to update the database again - take a lock TraceLog.TraceInfo("User database corrupted"); dbVersion.Status = me; SaveChanges(); updateDB = true; } } if (updateDB == false) { TraceLog.TraceInfo(String.Format("User database version {0} is up to date", UserConstants.ConstantsVersion)); return(true); } } catch (Exception ex) { TraceLog.TraceException("Could not find database version", ex); return(false); } // update the default database values DatabaseVersion version = null; UserStorageContext versionContext = Storage.NewUserContext; try { // verify that this unit of execution owns the update lock for the database version version = versionContext.Versions.Single(v => v.VersionType == DatabaseVersion.Constants && v.VersionString == UserConstants.ConstantsVersion); if (version.Status != me) { return(true); } TraceLog.TraceInfo(String.Format("{0} updating User datatbase to version {1}", me, UserConstants.ConstantsVersion)); // update existing action types, add new action types foreach (var entity in UserConstants.DefaultActionTypes()) { if (ActionTypes.Any(e => e.ActionTypeID == entity.ActionTypeID)) { ActionTypes.Single(e => e.ActionTypeID == entity.ActionTypeID).Copy(entity); } else { ActionTypes.Add(entity); } } SaveChanges(); TraceLog.TraceInfo("Replaced action types"); // update existing colors, add new colors foreach (var entity in UserConstants.DefaultColors()) { if (Colors.Any(e => e.ColorID == entity.ColorID)) { Colors.Single(e => e.ColorID == entity.ColorID).Copy(entity); } else { Colors.Add(entity); } } SaveChanges(); TraceLog.TraceInfo("Replaced colors"); // update existing permissions, add new permissions foreach (var entity in UserConstants.DefaultPermissions()) { if (Permissions.Any(e => e.PermissionID == entity.PermissionID)) { Permissions.Single(e => e.PermissionID == entity.PermissionID).Copy(entity); } else { Permissions.Add(entity); } } SaveChanges(); TraceLog.TraceInfo("Replaced permissions"); // update existing priorities, add new priorities foreach (var entity in UserConstants.DefaultPriorities()) { if (Priorities.Any(e => e.PriorityID == entity.PriorityID)) { Priorities.Single(e => e.PriorityID == entity.PriorityID).Copy(entity); } else { Priorities.Add(entity); } } SaveChanges(); TraceLog.TraceInfo("Replaced priorities"); // update existing or add new built-in users foreach (var user in UserConstants.DefaultUsers()) { if (Users.Any(u => u.ID == user.ID)) { var existing = Users.Single(u => u.ID == user.ID); existing.Name = user.Name; existing.Email = user.Email; existing.CreateDate = user.CreateDate; } else { Users.Add(user); } } SaveChanges(); TraceLog.TraceInfo("Replaced users"); // update existing or add new built-in itemtypes and fields foreach (var itemType in UserConstants.DefaultItemTypes()) { if (ItemTypes.Any(it => it.ID == itemType.ID)) { var existing = ItemTypes.Include("Fields").Single(it => it.ID == itemType.ID); existing.Copy(itemType); if (itemType.Fields == null) { continue; } foreach (var field in itemType.Fields) { if (existing.Fields.Any(f => f.ID == field.ID)) { var existingField = existing.Fields.Single(f => f.ID == field.ID); existingField.Copy(field); } else { existing.Fields.Add(field); } } } else { ItemTypes.Add(itemType); } } SaveChanges(); TraceLog.TraceInfo("Replaced item types and fields"); // save the new version number version.Status = DatabaseVersion.OK; versionContext.SaveChanges(); return(true); } catch (Exception ex) { TraceLog.TraceException("VersionConstants failed", ex); // mark the version as corrupted version.Status = DatabaseVersion.Corrupted; versionContext.SaveChanges(); return(false); } }