public string AddEditUser(User user, bool customTransaction, bool updateUserLastUpdated, bool customID)
        {
            if (user == null)
            {
                return("User cannot be null.");
            }

            if (String.IsNullOrWhiteSpace(user.FullName))
            {
                return("The user's fullname cannot be empty.");
            }

            if (DefaultUser.DefaultUserName.ToUpper().Equals(user.FullName.ToUpper()))
            {
                return(String.Format("The user's name cannot be {0}.", DefaultUser.DefaultUserName));
            }

            if (user.PasswordChanged && (String.IsNullOrWhiteSpace(user.NewPassword) || user.NewPassword.Length > VARCHAR_StandardSize))
            {
                return("The user's password cannot be empty.");
            }


            if (user.Description != null && user.Description.Length > VARCHAR_StandardSize)
            {
                return("The user's description is too long.");
            }

            SqliteDataReader reader = null;
            SqliteConnection conn   = null;

            try
            {
                SqliteTransaction transaction = null;
                if (customTransaction)
                {
                    if (_tempConn == null)
                    {
                        _tempConn = new SqliteConnection(@"data source=" + this.UsersFile);
                        _tempConn.Open();
                        _customTransaction = _tempConn.BeginTransaction();
                    }
                    conn = _tempConn;
                }
                else
                {
                    conn = new SqliteConnection(@"data source=" + this.UsersFile);
                    conn.Open();
                    transaction = conn.BeginTransaction();
                }

                SqliteCommand cmd = new SqliteCommand(conn);
                cmd.Parameters.Add(new SqliteParameter("@userID", user.ID));

                string description   = user.Description;
                string fullName      = user.FullName;
                byte   securityLevel = user.SecurityLevel;
                if (user.ID > 0)
                {
                    if (!customID)
                    {
                        cmd.CommandText = "SELECT id FROM User WHERE id = @userID";
                        reader          = cmd.ExecuteReader();
                        if (!reader.HasRows)
                        {
                            return("Couldn't find a user with the ID " + user.ID);
                        }
                        reader.Close();
                    }

                    cmd.Parameters.Add(new SqliteParameter("@id", user.ID));
                    //force the admin properties to stay the same
                    if (user.ID == DefaultAdminUser.DefaultAdminID)
                    {
                        description   = DefaultAdminUser.DefaultAdminDescription;
                        fullName      = DefaultAdminUser.DefaultAdminName;
                        securityLevel = DefaultAdminUser.DefaultAdminSecurityLevel;
                    }
                }
                cmd.Parameters.Add(new SqliteParameter("@description", description));

                cmd.Parameters.Add(new SqliteParameter("@fullname", fullName));

                byte[] password = user.Password;
                if (!customID && user.PasswordChanged)
                {
                    if (String.IsNullOrWhiteSpace(user.NewPassword))
                    {
                        return("The password cannot be blank.");
                    }
                    password = User.GenerateSHA256(user.NewPassword);
                    cmd.Parameters.Add(new SqliteParameter("password", password));
                }
                else if (customID)
                {
                    cmd.Parameters.Add(new SqliteParameter("password", user.Password));
                }
                cmd.Parameters.Add(new SqliteParameter("@securityLevel", securityLevel));

                if (user.ID > 0 && !customID)
                {
                    cmd.CommandText = "UPDATE User SET description = @description, fullname = @fullname, securityLevel = @securityLevel";
                    if (user.PasswordChanged)
                    {
                        cmd.CommandText += ", password = @password";
                    }
                }
                else
                {
                    cmd.CommandText = "INSERT INTO User(";
                    if (customID)
                    {
                        cmd.CommandText += "id,";
                    }
                    cmd.CommandText += "description, fullname, password, securityLevel";
                }

                for (int i = 0; i < DBUserShared.FingerCount; ++i)
                {
                    if (user.ID > 0 && !customID)
                    {
                        cmd.CommandText += String.Format(" ,fingerprint{0} = @fingerprint{0}", i);
                    }
                    else
                    {
                        cmd.CommandText += String.Format(" ,fingerprint{0}", i);
                    }
                    cmd.Parameters.Add(new SqliteParameter(String.Format("@fingerprint{0}", i), DBNull.Value));
                }

                foreach (FingerPrint fingerprint in user.FingerPrints)
                {
                    string fp = String.Format("@fingerprint{0}", fingerprint.PrintNumber);
                    if (cmd.Parameters.Contains(fp) && fingerprint.Print != null && fingerprint.Print.Length != 0)
                    {
                        cmd.Parameters[fp].Value = DBUserShared.AES_Encrypt(fingerprint.Print);
                    }
                }

                if (user.ID > 0 && !customID)
                {
                    cmd.CommandText += " WHERE ID = @id";
                }
                else
                {
                    cmd.CommandText += ") VALUES(";
                    if (customID)
                    {
                        cmd.CommandText += "@userID,";
                    }
                    cmd.CommandText += "@description, @fullname, @password, @securityLevel";

                    for (int i = 0; i < DBUserShared.FingerCount; ++i)
                    {
                        cmd.CommandText += String.Format(" ,@fingerprint{0}", i);
                    }
                    cmd.CommandText += ")";
                }

                cmd.ExecuteNonQuery();

                if (user.ID < 0 && !customID)
                {
                    cmd.CommandText = "SELECT last_insert_rowid()";
                    reader          = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        user.ID = int.Parse(reader[0].ToString());
                        cmd.Parameters["@userID"].Value = user.ID;
                    }
                    reader.Close();
                }

                if (updateUserLastUpdated)
                {
                    cmd.CommandText = "DELETE FROM UserLastUpdated";
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = "INSERT INTO UserLastUpdated(Value) VALUES(@value)";
                    cmd.Parameters.Add(new SqliteParameter("@value", DateTime.Now));
                    cmd.ExecuteNonQuery();
                }

                if (!customTransaction)
                {
                    transaction.Commit();
                }
                return("");
            }
            catch (Exception ex)
            {
                return("Failed to add or edit user: " + ex.Message);
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                    reader = null;
                }
                if (!customTransaction)
                {
                    if (conn != null)
                    {
                        conn.Close();
                        conn = null;
                    }
                }
            }
        }