Example #1
0
        public static bool Export(string connectionString, string filename, string username)
        {
            var context = new UserStorageContext(connectionString);
            var user = context.Users.FirstOrDefault(u => u.Name == username);
            if (user == null)
            {
                Console.WriteLine(String.Format("Export: user {0} not found", username));
                return false;
            }

            var userDataModel = new UserDataModel(context, user);
            try
            {
                filename = filename ?? @"userdata.json";
                using (var stream = File.Create(filename))
                using (var writer = new StreamWriter(stream))
                {
                    writer.WriteLine(userDataModel.JsonUserData);
                    writer.Flush();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Export: write failed; ex: ", ex.Message);
                return false;
            }
            return true;
        }
Example #2
0
 // OBSOLETE! Stamping of CompletedOn field is being done on each client to get proper timezone and immediate response.
 // should only be called if newItem.Complete value is true
 public static bool ProcessUpdateCompletedOn(UserStorageContext userContext, Item oldItem, Item newItem)
 {
     var wasComplete = oldItem.GetFieldValue(FieldNames.Complete);
     if (wasComplete == null || !wasComplete.Value.Equals("true", StringComparison.OrdinalIgnoreCase))
     {   // timestamp the CompletedOn field
         newItem.GetFieldValue(FieldNames.CompletedOn, true).Value = DateTime.UtcNow.ToString();
     }
     return false;
 }
Example #3
0
        // OBSOLETE! Stamping of CompletedOn field is being done on each client to get proper timezone and immediate response.
        // should only be called if newItem.Complete value is true
        public static bool ProcessUpdateCompletedOn(UserStorageContext userContext, Item oldItem, Item newItem)
        {
            var wasComplete = oldItem.GetFieldValue(FieldNames.Complete);

            if (wasComplete == null || !wasComplete.Value.Equals("true", StringComparison.OrdinalIgnoreCase))
            {   // timestamp the CompletedOn field
                newItem.GetFieldValue(FieldNames.CompletedOn, true).Value = DateTime.UtcNow.ToString();
            }
            return(false);
        }
Example #4
0
 // Factory method to create a new item processor based on the item type
 public static ItemProcessor Create(User user, UserStorageContext storage, Guid itemTypeID)
 {
     if (itemTypeID == SystemItemTypes.Task)
         return new TaskProcessor(user, storage);
     if (itemTypeID == SystemItemTypes.Appointment)
         return new AppointmentProcessor(user, storage);
     if (itemTypeID == SystemItemTypes.Grocery)
         return new GroceryProcessor(user, storage);
     if (itemTypeID == SystemItemTypes.Contact)
         return new ContactProcessor(user, storage);
     return null;
 }
Example #5
0
 public GoogleClient(User user, UserStorageContext storage)
 {
     // for using existing access token with renewal
     this.user = user;
     this.storage = storage;
     if (user.UserCredentials == null || user.UserCredentials.Count == 0)
     {   // ensure UserCredentials are present
         this.user = storage.GetUser(user.ID, true);
     }
     UserCredential googleConsent = this.user.GetCredential(UserCredential.GoogleConsent);
     if (googleConsent != null)
     {
         this.googleAuthenticator = CreateGoogleAuthenticator(GetAccessToken);
     }
 }
Example #6
0
        public GoogleClient(User user, UserStorageContext storage)
        {   // for using existing access token with renewal
            this.user    = user;
            this.storage = storage;
            if (user.UserCredentials == null || user.UserCredentials.Count == 0)
            {   // ensure UserCredentials are present
                this.user = storage.GetUser(user.ID, true);
            }
            UserCredential googleConsent = this.user.GetCredential(UserCredential.GoogleConsent);

            if (googleConsent != null)
            {
                this.googleAuthenticator = CreateGoogleAuthenticator(GetAccessToken);
            }
        }
Example #7
0
        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;
        }
Example #8
0
        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;
        }
Example #9
0
 // Factory method to create a new item processor based on the item type
 public static ItemProcessor Create(User user, UserStorageContext storage, Guid itemTypeID)
 {
     if (itemTypeID == SystemItemTypes.Task)
     {
         return(new TaskProcessor(user, storage));
     }
     if (itemTypeID == SystemItemTypes.Appointment)
     {
         return(new AppointmentProcessor(user, storage));
     }
     if (itemTypeID == SystemItemTypes.Grocery)
     {
         return(new GroceryProcessor(user, storage));
     }
     if (itemTypeID == SystemItemTypes.Contact)
     {
         return(new ContactProcessor(user, storage));
     }
     return(null);
 }
Example #10
0
 /// <summary>
 /// Delete all workflow instances associated with this entity ID (the entity is already deleted)
 /// </summary>
 /// <param name="userContext"></param>
 /// <param name="suggestionsContext"></param>
 /// <param name="entity"></param>
 public static void DeleteWorkflows(UserStorageContext userContext, SuggestionsStorageContext suggestionsContext, Guid entityID)
 {
     try
     {
         // get all the workflow instances for this Item
         var wis = suggestionsContext.WorkflowInstances.Where(w => w.EntityID == entityID).ToList();
         if (wis.Count > 0)
         {
             // loop over the workflow instances and dispatch the new message
             foreach (var instance in wis)
             {
                 suggestionsContext.WorkflowInstances.Remove(instance);
             }
             suggestionsContext.SaveChanges();
         }
     }
     catch (Exception ex)
     {
         TraceLog.TraceException("DeleteWorkflows failed", ex);
     }
 }
Example #11
0
        public static bool DataVersionCheck(out string status)
        {
            if (versionCheckStatus == null)
            {
                versionCheckStatus = string.Empty;
                UserStorageContext userStorage = Storage.NewUserContext;
                var dbSchemaVersion            = userStorage.Versions.FirstOrDefault(v => v.VersionType == DatabaseVersion.Schema);
                var dbConstantsVersion         = userStorage.Versions.FirstOrDefault(v => v.VersionType == DatabaseVersion.Constants);
                if (dbSchemaVersion == null || dbSchemaVersion.VersionString != UserConstants.SchemaVersion)
                {
                    versionCheckStatus += string.Format("UserSchema version mismatch: Code='{0}' Database='{1}' <br/>",
                                                        UserConstants.SchemaVersion,
                                                        dbSchemaVersion == null ? "<none>" : dbSchemaVersion.VersionString);
                }
                if (dbConstantsVersion == null || dbConstantsVersion.VersionString != UserConstants.ConstantsVersion)
                {
                    versionCheckStatus += string.Format("UserConstants version mismatch: Code='{0}' Database='{1}' <br/>",
                                                        UserConstants.ConstantsVersion,
                                                        dbConstantsVersion == null ? "<none>" : dbConstantsVersion.VersionString);
                }

                SuggestionsStorageContext workflowStorage = Storage.NewSuggestionsContext;
                dbSchemaVersion    = workflowStorage.Versions.FirstOrDefault(v => v.VersionType == DatabaseVersion.Schema);
                dbConstantsVersion = workflowStorage.Versions.FirstOrDefault(v => v.VersionType == DatabaseVersion.Constants);
                if (dbSchemaVersion == null || dbSchemaVersion.VersionString != WorkflowConstants.SchemaVersion)
                {
                    versionCheckStatus += string.Format("WorkflowSchema version mismatch: Code='{0}' Database='{1}' <br/>",
                                                        WorkflowConstants.SchemaVersion,
                                                        dbSchemaVersion == null ? "<none>" : dbSchemaVersion.VersionString);
                }
                if (dbConstantsVersion == null || dbConstantsVersion.VersionString != WorkflowConstants.ConstantsVersion)
                {
                    versionCheckStatus += string.Format("WorkflowConstants version mismatch: Code='{0}' Database='{1}' <br/>",
                                                        WorkflowConstants.ConstantsVersion,
                                                        dbConstantsVersion == null ? "<none>" : dbConstantsVersion.VersionString);
                }
            }
            status = versionCheckStatus;
            return(versionCheckStatus.Length == 0);
        }
Example #12
0
        // 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);
        }
Example #13
0
        /// <summary>
        /// Start a workflow of a certain type, passing it an entity and some instance data to start
        /// </summary>
        /// <param name="userContext"></param>
        /// <param name="suggestionsContext"></param>
        /// <param name="type">String representing the workflow type</param>
        /// <param name="entity">Entity to associate with the workflow</param>
        /// <param name="instanceData">Instance data to pass into the workflow</param>
        public static void StartWorkflow(UserStorageContext userContext, SuggestionsStorageContext suggestionsContext, string type, ServerEntity entity, string instanceData)
        {
            WorkflowInstance instance = null;
            try
            {
                Workflow workflow = null;

                // get the workflow definition out of the database
                try
                {
                    var wt = suggestionsContext.WorkflowTypes.Single(t => t.Type == type);
                    workflow = JsonSerializer.Deserialize<Workflow>(wt.Definition);
                }
                catch (Exception ex)
                {
                    TraceLog.TraceException("Could not find or deserialize workflow definition", ex);
                    return;
                }

                // don't start a workflow with no states
                if (workflow.States.Count == 0)
                    return;

                // store the database contexts
                workflow.UserContext = userContext;
                workflow.SuggestionsContext = suggestionsContext;

                // create the new workflow instance and store in the workflow DB
                DateTime now = DateTime.Now;
                instance = new WorkflowInstance()
                {
                    ID = Guid.NewGuid(),
                    EntityID = entity.ID,
                    EntityName = entity.Name,
                    WorkflowType = type,
                    State = workflow.States[0].Name,
                    InstanceData = instanceData ?? "{}",
                    Created = now,
                    LastModified = now,
                    LockedBy = WorkflowHost.Me,
                };
                suggestionsContext.WorkflowInstances.Add(instance);
                suggestionsContext.SaveChanges();

                TraceLog.TraceInfo("Starting workflow " + type);

                // invoke the workflow and process steps until workflow is blocked for user input or is done
                workflow.Run(instance, entity);

                // unlock the workflowinstance
                instance.LockedBy = null;
                suggestionsContext.SaveChanges();
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("StartWorkflow failed", ex);
                if (instance != null && instance.LockedBy == WorkflowHost.Me)
                {
                    // unlock the workflowinstance
                    instance.LockedBy = null;
                    suggestionsContext.SaveChanges();
                }
            }
        }
Example #14
0
 public AppointmentProcessor(User user, UserStorageContext storage)
 {
     this.user    = user;
     this.storage = storage;
 }
Example #15
0
        /// <summary>
        /// Start workflows associated with a change in one or more of the entity's fields
        /// </summary>
        /// <param name="userContext"></param>
        /// <param name="suggestionsContext"></param>
        /// <param name="entity"></param>
        /// <param name="oldEntity"></param>
        public static void StartTriggerWorkflows(UserStorageContext userContext, SuggestionsStorageContext suggestionsContext, ServerEntity entity, ServerEntity oldEntity)
        {
            if (entity == null || oldEntity == null)
                return;

            // only Item property triggers are supported at this time
            Item item = entity as Item;
            Item oldItem = oldEntity as Item;
            if (item != null)
            {
                // go through field by field, and if a field has changed, trigger the appropriate workflow
                ItemType itemType = userContext.ItemTypes.Include("Fields").Single(it => it.ID == item.ItemTypeID);

                foreach (var field in itemType.Fields)
                {
                    object newValue = item.GetFieldValue(field);
                    object oldValue = item.GetFieldValue(field);

                    // skip fields that haven't changed
                    if (newValue == null || newValue.Equals(oldValue))
                        continue;

                    // do field-specific processing for select fields
                    switch (field.Name)
                    {
                        case FieldNames.Name:
                            //disable for now
                            //RestartWorkflow(userContext, suggestionsContext, item, WorkflowNames.NewTask);
                            break;
                    }
                }
            }
        }
Example #16
0
        /// <summary>
        /// Restart the workflows associated with an entity
        /// </summary>
        /// <param name="userContext"></param>
        /// <param name="suggestionsContext"></param>
        /// <param name="entity"></param>
        /// <param name="workflowType"></param>
        public static void RestartWorkflow(UserStorageContext userContext, SuggestionsStorageContext suggestionsContext, ServerEntity entity, string workflowType)
        {
            if (entity == null || workflowType == null)
                return;

            try
            {
                // kill all existing workflows associated with this Item
                // TODO: also need to mark the suggestions associated with this workflow as stale so that they don't
                // show up for the item again.
                var runningWFs = suggestionsContext.WorkflowInstances.Where(wi => wi.EntityID == entity.ID).ToList();
                if (runningWFs.Count > 0)
                {
                    foreach (var wf in runningWFs)
                        suggestionsContext.WorkflowInstances.Remove(wf);
                    suggestionsContext.SaveChanges();
                }
                StartWorkflow(userContext, suggestionsContext, workflowType, entity, null);
            }
            catch (Exception)
            {
                StartWorkflow(userContext, suggestionsContext, workflowType, entity, null);
            }
        }
Example #17
0
        /// <summary>
        /// Start NewUser/NewFolder/NewItem workflows based on the entity type
        /// </summary>
        /// <param name="userContext"></param>
        /// <param name="suggestionsContext"></param>
        /// <param name="entity"></param>
        public static void StartNewWorkflows(UserStorageContext userContext, SuggestionsStorageContext suggestionsContext, ServerEntity entity)
        {
            if (entity == null)
                return;

            // figure out what kind of entity this is
            Item item = entity as Item;
            Folder folder = entity as Folder;
            User user = entity as User;

            // verify there are no workflow instances associated with this item yet
            var wis = suggestionsContext.WorkflowInstances.Where(wi => wi.EntityID == entity.ID).ToList();
            if (wis.Count > 0)
                return;

            if (item != null && item.IsList == false)
            {
                if (item.ItemTypeID == SystemItemTypes.Task)
                    StartWorkflow(userContext, suggestionsContext, WorkflowNames.NewTask, item, null);
                // the Contact and Grocery new item processing happens in ItemProcessor now
                //if (item.ItemTypeID == SystemItemTypes.Contact)
                //    StartWorkflow(userContext, suggestionsContext, WorkflowNames.NewContact, item, null);
                //if (item.ItemTypeID == SystemItemTypes.Grocery)
                //    Workflow.StartWorkflow(userContext, suggestionsContext, WorkflowNames.NewGrocery, item, null);
            }

            if (folder != null)
            {
            }

            if (user != null)
            {
                StartWorkflow(userContext, suggestionsContext, WorkflowNames.NewUser, user, null);
            }
        }
Example #18
0
 public ClientUserFolder(UserStorageContext storage)
 {
     this.storage = storage;
 }
Example #19
0
        /// <summary>
        /// Process the operation based on the underlying entity type and the operation type
        /// </summary>
        /// <param name="userContext"></param>
        /// <param name="suggestionsContext"></param>
        /// <param name="operation"></param>
        /// <returns>true if processed, false if the instance was locked and the operation needs to be replayed</returns>
        public static bool ProcessOperation(UserStorageContext userContext, SuggestionsStorageContext suggestionsContext, Operation operation)
        {
            if (operation == null)
                return true;

            if (userContext == null)
                userContext = Storage.NewUserContext;
            if (suggestionsContext == null)
                suggestionsContext = Storage.NewSuggestionsContext;

            Guid entityID = operation.EntityID;
            string entityType = operation.EntityType.Trim();
            string operationType = operation.OperationType.Trim();
            TraceLog.Session = operation.Session;

            // try to get a strongly-typed entity (item, folder, user...)
            ServerEntity entity = null, oldEntity = null;
            bool process = true;

            // extract the underlying entity unless this is a delete operation (in which case it's already deleted)
            if (operationType != "DELETE")
            {
                try
                {
                    switch (entityType)
                    {
                        case "Item":
                            Item item = userContext.Items.Include("FieldValues").Single(i => i.ID == entityID);
                            Item oldItem = JsonSerializer.Deserialize<Item>(operation.OldBody);
                            entity = item;
                            oldEntity = oldItem;
                            break;
                        case "Folder":
                            Folder folder = userContext.Folders.Single(i => i.ID == entityID);
                            entity = folder;
                            break;
                        case "User":
                            User user = userContext.Users.Single(i => i.ID == entityID);
                            entity = user;
                            break;
                        case "Suggestion":
                            // if the entity passed in is a suggestion, this is a "meta" request - get the underlying Entity's
                            // ID and type
                            Suggestion suggestion = suggestionsContext.Suggestions.Single(s => s.ID == entityID);
                            entityID = suggestion.EntityID;
                            entityType = suggestion.EntityType;
                            switch (entityType)
                            {
                                case "Item":
                                    entity = userContext.Items.Include("FieldValues").Single(i => i.ID == entityID);
                                    break;
                                case "Folder":
                                    entity = userContext.Folders.Single(i => i.ID == entityID);
                                    break;
                                case "User":
                                    entity = userContext.Users.Single(i => i.ID == entityID);
                                    break;
                            }
                            operationType = "SUGGESTION";
                            break;
                        default:
                            TraceLog.TraceError("Invalid Entity Type " + entityType);
                            process = false;
                            break;
                    }
                }
                catch (Exception ex)
                {
                    TraceLog.TraceException(String.Format("Could not retrieve {0}", entityType), ex);
                    process = false;
                }
            }

            // launch new workflows based on the changes to the item
            if (process)
            {
                switch (operationType)
                {
                    case "DELETE":
                        DeleteWorkflows(userContext, suggestionsContext, entityID);
                        return true;
                    case "POST":
                        StartNewWorkflows(userContext, suggestionsContext, entity);
                        return ExecuteWorkflows(userContext, suggestionsContext, entity);
                    case "PUT":
                        StartTriggerWorkflows(userContext, suggestionsContext, entity, oldEntity);
                        return ExecuteWorkflows(userContext, suggestionsContext, entity);
                    case "SUGGESTION":
                        return ExecuteWorkflows(userContext, suggestionsContext, entity);
                    default:
                        TraceLog.TraceError("Invalid Operation Type " + operationType);
                        return true;
                }
            }

            return true;
        }
Example #20
0
 public ClientUserFolder(UserStorageContext storage)
 {
     this.storage = storage;
 }
Example #21
0
 public ServerUserFolder(UserStorageContext storage)
 {
     this.storage = storage;
 }
Example #22
0
        // 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);
            }
        }
Example #23
0
 public UserDataModel(BaseResource resource)
 {
     this.storageContext = resource.StorageContext;
     this.currentUser = resource.CurrentUser;
 }
Example #24
0
        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;
        }
Example #25
0
        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);
                }
            }
        }
Example #26
0
 public ServerUserFolder(UserStorageContext storage)
 {
     this.storage = storage;
 }
Example #27
0
        /// <summary>
        /// Execute the workflow instances associated with this entity
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="userContext"></param>
        /// <param name="suggestionsContext"></param>
        /// <returns>true if processing happened (and the operation doesn't need to be processed again), 
        /// false if one the workflow instances was locked (causes the message to be reprocessed)</returns>
        public static bool ExecuteWorkflows(UserStorageContext userContext, SuggestionsStorageContext suggestionsContext, ServerEntity entity)
        {
            if (entity == null)
                return true;

            List<WorkflowInstance> wis = null;

            try
            {
                // get all the workflow instances for this Item
                wis = suggestionsContext.WorkflowInstances.Where(w => w.EntityID == entity.ID).ToList();
                if (wis.Count > 0)
                {
                    // if the instance is locked by someone else, stop processing
                    // otherwise lock each of the workflow instances
                    foreach (var instance in wis)
                    {
                        if (instance.LockedBy != null && instance.LockedBy != Me)
                            return false;
                        instance.LockedBy = Me;
                    }
                    suggestionsContext.SaveChanges();

                    // reacquire the lock list and verify they were all locked by Me (if not, stop processing)
                    // projecting locks and not workflow instances to ensure that the database's lock values are returned (not from EF's cache)
                    var locks = suggestionsContext.WorkflowInstances.Where(w => w.EntityID == entity.ID).Select(w => w.LockedBy).ToList();
                    foreach (var lockedby in locks)
                        if (lockedby != Me)
                            return false;

                    // loop over the workflow instances and dispatch the new message
                    foreach (var instance in wis)
                    {
                        Workflow workflow = null;
                        try
                        {
                            var wt = suggestionsContext.WorkflowTypes.Single(t => t.Type == instance.WorkflowType);
                            workflow = JsonSerializer.Deserialize<Workflow>(wt.Definition);
                        }
                        catch (Exception ex)
                        {
                            TraceLog.TraceException("Could not find or deserialize workflow definition", ex);
                            continue;
                        }

                        // set the database contexts
                        workflow.UserContext = userContext;
                        workflow.SuggestionsContext = suggestionsContext;

                        // invoke the workflow and process steps until workflow is blocked for user input or is done
                        workflow.Run(instance, entity);
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("ExecuteWorkflows failed", ex);
                return true;
            }
            finally
            {
                // find and unlock all remaining workflow instances that relate to this entity
                // note that a new context is used for this - to avoid caching problems where the current thread
                // believes it is the owner but the database says otherwise.
                var context = Storage.NewSuggestionsContext;
                wis = context.WorkflowInstances.Where(w => w.EntityID == entity.ID).ToList();
                if (wis.Count > 0)
                {
                    // unlock each of the workflow instances
                    foreach (var instance in wis)
                        if (instance.LockedBy == Me)
                            instance.LockedBy = null;
                    context.SaveChanges();
                }
            }
        }
Example #28
0
 public UserDataModel(UserStorageContext storage, User user)
 {
     this.storageContext = storage;
     this.currentUser = user;
 }
Example #29
0
 public UserDataModel(BaseController controller)
 {
     this.storageContext = controller.StorageContext;
     this.currentUser = controller.CurrentUser;
 }
Example #30
0
 public AppointmentProcessor(User user, UserStorageContext storage)
 {
     this.user = user;
     this.storage = storage;
 }
Example #31
0
 public TaskProcessor(User user, UserStorageContext storage)
 {
     this.user = user;
     this.storage = storage;
 }
Example #32
0
 public TaskProcessor(User user, UserStorageContext storage)
 {
     this.user    = user;
     this.storage = storage;
 }
Example #33
0
 static User LookupUserByName(string username, bool includeCredentials = false, UserStorageContext storage = null)
 {
     username = username.ToLower();
     if (storage == null) { storage = Storage.NewUserContext; }
     if (storage.Users.Any<User>(u => u.Name == username))
     {
         if (includeCredentials)
         {
             return storage.Users.Include("UserCredentials").Single<User>(u => u.Name == username);
         }
         else
         {
             return storage.Users.Single<User>(u => u.Name == username);
         }
     }
     return null;
 }
Example #34
0
 /// <summary>
 /// Invoke the workflows for an operation depending on the environment.  
 /// If in Azure, enqueue a message; otherwise, invoke the workflow host directly.
 /// </summary>
 /// <param name="userContext"></param>
 /// <param name="suggestionsContext"></param>
 /// <param name="operation"></param>
 public static void InvokeWorkflowForOperation(UserStorageContext userContext, SuggestionsStorageContext suggestionsContext, Operation operation)
 {
     if (HostEnvironment.IsAzure)
         MessageQueue.EnqueueMessage(operation.ID);
     else
         ProcessOperation(userContext, suggestionsContext, operation);
 }