예제 #1
0
        internal static void CheckArrayParameter(ref string[] param, bool checkForNull, bool checkIfEmpty, bool checkForCommas, int maxSize, string paramName)
        {
            if (param == null)
            {
                throw new ArgumentNullException(paramName);
            }

            if (param.Length < 1)
            {
                throw new ArgumentException(string.Format(CultureInfo.InstalledUICulture, "The array parameter '{0}' should not be empty.", paramName), paramName);
            }

            Hashtable values = new Hashtable(param.Length);

            for (int i = param.Length - 1; i >= 0; i--)
            {
                SecUtility.CheckParameter(ref param[i], checkForNull, checkIfEmpty, checkForCommas, maxSize,
                                          paramName + "[ " + i.ToString(CultureInfo.InvariantCulture) + " ]");
                if (values.Contains(param[i]))
                {
                    throw new ArgumentException(string.Format(CultureInfo.InstalledUICulture, "The array '{0}' should not contain duplicate values.", paramName), paramName);
                }
                else
                {
                    values.Add(param[i], param[i]);
                }
            }
        }
        private SessionRow GetSession(string id, DataServiceContext context)
        {
            Debug.Assert(context != null);
            Debug.Assert(id != null && id.Length <= Configuration.MaxStringPropertySizeInChars);

            try
            {
                DataServiceQuery <SessionRow> queryObj = context.CreateQuery <SessionRow>(_tableName);
                var query = (from session in queryObj
                             where session.PartitionKey == SecUtility.CombineToKey(_applicationName, id)
                             select session).AsTableServiceQuery();
                IEnumerable <SessionRow> sessions = query.Execute();

                // enumerate the result and store it in a list
                List <SessionRow> sessionList = new List <SessionRow>(sessions);
                if (sessionList != null && sessionList.Count() == 1)
                {
                    return(sessionList.First());
                }
                else if (sessionList != null && sessionList.Count() > 1)
                {
                    throw new ProviderException("Multiple sessions with the same name!");
                }
                else
                {
                    return(null);
                }
            }
            catch (Exception e)
            {
                throw new ProviderException("Error accessing storage.", e);
            }
        }
        public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
        {
            Debug.Assert(context != null);
            SecUtility.CheckParameter(ref id, true, true, false, Configuration.MaxStringPropertySizeInChars, "id");
            if (timeout < 0)
            {
                throw new ArgumentException("Parameter timeout must be a non-negative integer!");
            }

            try
            {
                TableServiceContext svc     = CreateDataServiceContext();
                SessionRow          session = new SessionRow(id, _applicationName);

                session.Lock        = 0; // no lock
                session.Initialized = false;
                session.Id          = id;
                session.Timeout     = timeout;
                session.ExpiresUtc  = DateTime.UtcNow.AddMinutes(timeout);
                svc.AddObject(_tableName, session);
                svc.SaveChangesWithRetries();
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error accessing the data store.", e);
            }
        }
예제 #4
0
        private RoleRow GetUserInRole(DataServiceContext svc, string rolename, string username)
        {
            SecUtility.CheckParameter(ref username, true, true, true, Constants.MaxTableUsernameLength, "username");
            SecUtility.CheckParameter(ref rolename, true, true, true, MaxTableRoleNameLength, "rolename");

            try
            {
                DataServiceQuery <RoleRow> queryObj = svc.CreateQuery <RoleRow>(_tableName);

                var query = (from user in queryObj
                             where user.PartitionKey == SecUtility.CombineToKey(_applicationName, username) &&
                             user.RowKey == SecUtility.Escape(rolename)
                             select user).AsTableServiceQuery();
                try
                {
                    IEnumerable <RoleRow> userRows = query.Execute();
                    return(userRows.FirstOrDefault());
                }
                catch (InvalidOperationException e)
                {
                    if (e.InnerException is DataServiceClientException && (e.InnerException as DataServiceClientException).StatusCode == (int)HttpStatusCode.NotFound)
                    {
                        return(null);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
            catch (Exception e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
        public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
        {
            Debug.Assert(context != null);
            Debug.Assert(lockId != null);
            Debug.Assert(_blobProvider != null);
            SecUtility.CheckParameter(ref id, true, true, false, Configuration.MaxStringPropertySizeInChars, "id");

            try
            {
                sqlTableServiceContext svc     = CreateDataServiceContext();
                SessionRow             session = GetSession(id, svc);
                if (session == null)
                {
                    Debug.Assert(false);
                    return;
                }
                if (session.Lock != (int)lockId)
                {
                    Debug.Assert(false);
                    return;
                }
                svc.DeleteObject(session);
                svc.SaveChangesWithRetries();
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error accessing the data store!", e);
            }

            // delete associated blobs
            try
            {
                IEnumerable <sqlListBlobItem> e = _blobProvider.ListBlobs(GetBlobNamePrefix(id));
                if (e == null)
                {
                    return;
                }
                IEnumerator <sqlListBlobItem> props = e.GetEnumerator();
                if (props == null)
                {
                    return;
                }
                while (props.MoveNext())
                {
                    if (props.Current != null)
                    {
                        if (!_blobProvider.DeleteBlob(props.Current.Uri.ToString()))
                        {
                            // ignore this; it is possible that another thread could try to delete the blob
                            // at the same time
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw new ProviderException("Error accessing blob storage.", e);
            }
        }
예제 #6
0
        public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge,
                                                      out object lockId, out SessionStateActions actions)
        {
            Debug.Assert(context != null);
            SecUtility.CheckParameter(ref id, true, true, false, Configuration.MaxStringPropertySizeInChars, "id");

            return(GetSession(context, id, out locked, out lockAge, out lockId, out actions, false));
        }
        // applicationName + userName is partitionKey
        // roleName is rowKey
        public RoleRow(string applicationName, string roleName, string userName)
            : base()
        {
            SecUtility.CheckParameter(ref applicationName, true, true, true, Constants.MaxTableApplicationNameLength, "applicationName");
            SecUtility.CheckParameter(ref roleName, true, true, true, TableStorageRoleProvider.MaxTableRoleNameLength, "roleName");
            SecUtility.CheckParameter(ref userName, true, false, true, Constants.MaxTableUsernameLength, "userName");

            ApplicationName = applicationName;
            RoleName        = roleName;
            UserName        = userName;
        }
예제 #8
0
        public override bool IsUserInRole(string username, string roleName)
        {
            SecUtility.CheckParameter(ref roleName, true, true, true, MaxTableRoleNameLength, "rolename");
            SecUtility.CheckParameter(ref username, true, false, true, Constants.MaxTableUsernameLength, "username");
            if (username.Length < 1)
            {
                return(false);
            }

            try
            {
                TableStorageDataServiceContext svc      = CreateDataServiceContext();
                DataServiceQuery <RoleRow>     queryObj = svc.CreateQuery <RoleRow>(_tableName);

                IEnumerable <RoleRow> query = from user in queryObj
                                              where (user.PartitionKey == SecUtility.CombineToKey(_applicationName, username) ||
                                                     user.PartitionKey == SecUtility.CombineToKey(_applicationName, string.Empty)) &&
                                              user.RowKey == SecUtility.Escape(roleName)
                                              select user;

                TableStorageDataServiceQuery <RoleRow> q = new TableStorageDataServiceQuery <RoleRow>(query as DataServiceQuery <RoleRow>, _tableRetry);
                IEnumerable <RoleRow> userRows           = q.ExecuteWithRetries();

                if (userRows == null)
                {
                    throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "The role {0} does not exist.", roleName));
                }
                List <RoleRow> l = new List <RoleRow>(userRows);
                if (l.Count == 0)
                {
                    throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "The role {0} does not exist.", roleName));
                }
                RoleRow row;
                if (IsStaleRole(l, out row))
                {
                    throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "The role {0} does not exist.", roleName));
                }
                if (l.Count > 2)
                {
                    throw new ProviderException("User name appears twice in the same role!");
                }
                if (l.Count == 1)
                {
                    Debug.Assert(string.IsNullOrEmpty(l.ElementAt(0).UserName));
                    return(false);
                }
                return(true);
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
예제 #9
0
        public override void ResetItemTimeout(HttpContext context, string id)
        {
            Debug.Assert(context != null);
            SecUtility.CheckParameter(ref id, true, true, false, Configuration.MaxStringPropertySizeInChars, "id");

            _providerRetry(() => {
                TableServiceContext svc = CreateDataServiceContext();
                SessionRow session      = GetSession(id, svc);
                session.ExpiresUtc      = DateTime.UtcNow.AddMinutes(session.Timeout);
                svc.UpdateObject(session);
                svc.SaveChangesWithRetries();
            });
        }
예제 #10
0
        // remember that there is no is no rollback functionality for the table storage service right now
        // be cautious when using this function
        // if a role does not exist, we stop deleting roles, if a user in a role does not exist, we continue deleting
        // in case of error conditions, the behavior of this function is different than the SQL role provider
        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            SecUtility.CheckArrayParameter(ref roleNames, true, true, true, MaxTableRoleNameLength, "roleNames");
            SecUtility.CheckArrayParameter(ref usernames, true, true, true, Constants.MaxTableUsernameLength, "usernames");

            RoleRow row;

            try
            {
                TableStorageDataServiceContext svc = CreateDataServiceContext();
                foreach (string role in roleNames)
                {
                    if (!RoleExists(role))
                    {
                        throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "The role {0} does not exist!", role));
                    }
                    foreach (string user in usernames)
                    {
                        row = GetUserInRole(svc, role, user);
                        if (row == null)
                        {
                            Log.Write(EventKind.Warning, string.Format(CultureInfo.InstalledUICulture, "The user {0} does not exist in the role {1}.", user, role));
                            continue;
                        }
                        try
                        {
                            svc.DeleteObject(row);
                            svc.SaveChangesWithRetries();
                        }
                        catch (Exception e)
                        {
                            HttpStatusCode status;
                            if (TableStorageHelpers.EvaluateException(e, out status) && (status == HttpStatusCode.NoContent || status == HttpStatusCode.NotFound))
                            {
                                Log.Write(EventKind.Warning, string.Format(CultureInfo.InstalledUICulture, "The user {0} does not exist in the role {1}.", user, role));
                                svc.Detach(row);
                            }
                            else
                            {
                                throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "Error deleting user {0} from role {1}.", user, role));
                            }
                        }
                    }
                }
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
예제 #11
0
        // Because of limited transactional support in the table storage offering, this function gives limited guarantees
        // for inserting all users into all roles.
        // We do not recommend using this function because of missing transactional support.
        public override void AddUsersToRoles(string[] usernames, string[] roleNames)
        {
            SecUtility.CheckArrayParameter(ref roleNames, true, true, true, MaxTableRoleNameLength, "roleNames");
            SecUtility.CheckArrayParameter(ref usernames, true, true, true, Constants.MaxTableUsernameLength, "usernames");

            RoleRow row;

            try
            {
                TableStorageDataServiceContext svc = CreateDataServiceContext();
                foreach (string role in roleNames)
                {
                    if (!RoleExists(role))
                    {
                        throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "The role {0} does not exist!", role));
                    }
                    foreach (string user in usernames)
                    {
                        row = new RoleRow(_applicationName, role, user);
                        try
                        {
                            svc.AddObject(_tableName, row);
                            svc.SaveChangesWithRetries();
                        }
                        catch (InvalidOperationException e)
                        {
                            HttpStatusCode status;
                            if (TableStorageHelpers.EvaluateException(e, out status) && status == HttpStatusCode.Conflict)
                            {
                                // this element already exists or was created in a failed retry
                                // this is not a fatal error; continue adding elements
                                Log.Write(EventKind.Warning, string.Format(CultureInfo.InstalledUICulture, "The user {0} already exists in the role {1}.", user, role));
                                svc.Detach(row);
                            }
                            else
                            {
                                throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "Error adding user {0} to role {1}", user, role));
                            }
                        }
                    }
                }
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
예제 #12
0
        // application name + session id is partitionKey
        public SessionRow(string sessionId, string applicationName)
            : base()
        {
            SecUtility.CheckParameter(ref sessionId, true, true, true, Configuration.MaxStringPropertySizeInChars, "sessionId");
            SecUtility.CheckParameter(ref applicationName, true, true, true, Constants.MaxTableApplicationNameLength, "applicationName");

            PartitionKey = SecUtility.CombineToKey(applicationName, sessionId);
            RowKey       = string.Empty;

            Id = sessionId;
            ApplicationName = applicationName;
            ExpiresUtc      = Configuration.MinSupportedDateTime;
            LockDateUtc     = Configuration.MinSupportedDateTime;
            CreatedUtc      = Configuration.MinSupportedDateTime;
            Timeout         = 0;
            BlobName        = string.Empty;
        }
예제 #13
0
        public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
        {
            Debug.Assert(context != null);
            Debug.Assert(lockId != null);
            SecUtility.CheckParameter(ref id, true, true, false, Configuration.MaxStringPropertySizeInChars, "id");

            try
            {
                TableServiceContext svc     = CreateDataServiceContext();
                SessionRow          session = GetSession(id, svc);
                ReleaseItemExclusive(svc, session, lockId);
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error accessing the data store!", e);
            }
        }
예제 #14
0
        public override string[] GetRolesForUser(string username)
        {
            SecUtility.CheckParameter(ref username, true, false, true, Constants.MaxTableUsernameLength, "username");
            if (username.Length < 1)
            {
                return(new string[0]);
            }

            try
            {
                TableStorageDataServiceContext svc      = CreateDataServiceContext();
                DataServiceQuery <RoleRow>     queryObj = svc.CreateQuery <RoleRow>(_tableName);

                IEnumerable <RoleRow> query = from user in queryObj
                                              where user.PartitionKey == SecUtility.CombineToKey(_applicationName, username) ||
                                              user.PartitionKey == SecUtility.CombineToKey(_applicationName, string.Empty)
                                              select user;
                TableStorageDataServiceQuery <RoleRow> q = new TableStorageDataServiceQuery <RoleRow>(query as DataServiceQuery <RoleRow>, _tableRetry);
                IEnumerable <RoleRow> userRows           = q.ExecuteAllWithRetries();

                if (userRows == null)
                {
                    return(new string[0]);
                }
                List <RoleRow> l = new List <RoleRow>(userRows);
                if (l.Count == 0)
                {
                    return(new string[0]);
                }
                List <string> ret = new List <string>();
                foreach (RoleRow user in l)
                {
                    if (!string.IsNullOrEmpty(user.UserName) && !IsStaleRole(l, user.RoleName))
                    {
                        ret.Add(user.RoleName);
                    }
                }
                return(ret.ToArray());
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
예제 #15
0
        public override string[] GetUsersInRole(string roleName)
        {
            SecUtility.CheckParameter(ref roleName, true, true, true, MaxTableRoleNameLength, "rolename");

            try
            {
                TableStorageDataServiceContext svc      = CreateDataServiceContext();
                DataServiceQuery <RoleRow>     queryObj = svc.CreateQuery <RoleRow>(_tableName);

                IEnumerable <RoleRow> query = from user in queryObj
                                              where user.PartitionKey.CompareTo(SecUtility.EscapedFirst(_applicationName)) >= 0 &&
                                              user.PartitionKey.CompareTo(SecUtility.NextComparisonString(SecUtility.EscapedFirst(_applicationName))) < 0 &&
                                              user.RowKey == SecUtility.Escape(roleName)
                                              select user;
                TableStorageDataServiceQuery <RoleRow> q = new TableStorageDataServiceQuery <RoleRow>(query as DataServiceQuery <RoleRow>, _tableRetry);
                IEnumerable <RoleRow> userRows           = q.ExecuteAllWithRetries();

                if (userRows == null)
                {
                    // role does not exist; we are supposed to throw an exception here
                    throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "The role {0} does not exist!", roleName));
                }
                List <RoleRow> l = new List <RoleRow>(userRows);
                if (l.Count == 0 || IsStaleRole(l, roleName))
                {
                    throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "The role {0} does not exist!", roleName));
                }
                List <string> ret = new List <string>();
                foreach (RoleRow user in l)
                {
                    if (!string.IsNullOrEmpty(user.UserName))
                    {
                        ret.Add(user.UserName);
                    }
                }
                return(ret.ToArray());
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
예제 #16
0
        public override bool RoleExists(string roleName)
        {
            SecUtility.CheckParameter(ref roleName, true, true, true, MaxTableRoleNameLength, "rolename");
            try
            {
                TableStorageDataServiceContext svc      = CreateDataServiceContext();
                DataServiceQuery <RoleRow>     queryObj = svc.CreateQuery <RoleRow>(_tableName);

                IEnumerable <RoleRow> query = from role in queryObj
                                              where role.PartitionKey == SecUtility.CombineToKey(_applicationName, string.Empty) &&
                                              role.RowKey == SecUtility.Escape(roleName)
                                              select role;

                TableStorageDataServiceQuery <RoleRow> q = new TableStorageDataServiceQuery <RoleRow>(query as DataServiceQuery <RoleRow>, _tableRetry);
                try
                {
                    // this query addresses exactly one result
                    // we thus should get an exception if there is no element
                    q.ExecuteWithRetries();
                    return(true);
                }
                catch (DataServiceQueryException e)
                {
                    HttpStatusCode s;
                    if (TableStorageHelpers.EvaluateException(e, out s) && s == HttpStatusCode.NotFound)
                    {
                        return(false);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
예제 #17
0
        public override string[] GetAllRoles()
        {
            try
            {
                DataServiceContext         svc      = CreateDataServiceContext();
                DataServiceQuery <RoleRow> queryObj = svc.CreateQuery <RoleRow>(_tableName);

                IEnumerable <RoleRow> query = from role in queryObj
                                              where role.PartitionKey == SecUtility.CombineToKey(_applicationName, string.Empty)
                                              select role;
                TableStorageDataServiceQuery <RoleRow> q = new TableStorageDataServiceQuery <RoleRow>(query as DataServiceQuery <RoleRow>, _tableRetry);
                IEnumerable <RoleRow> userRows           = q.ExecuteAllWithRetries();

                if (userRows == null)
                {
                    return(new string[0]);
                }
                List <RoleRow> l = new List <RoleRow>(userRows);
                if (l.Count == 0)
                {
                    return(new string[0]);
                }
                List <string> ret = new List <string>();
                foreach (RoleRow role in l)
                {
                    Debug.Assert(role.UserName != null);
                    if (string.IsNullOrEmpty(role.UserName))
                    {
                        ret.Add(role.RoleName);
                    }
                }
                return(ret.ToArray());
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
예제 #18
0
        public override void CreateRole(string roleName)
        {
            SecUtility.CheckParameter(ref roleName, true, true, true, MaxTableRoleNameLength, "rolename");

            try
            {
                TableServiceContext svc     = CreateDataServiceContext();
                RoleRow             newRole = new RoleRow(_applicationName, roleName, string.Empty);
                svc.AddObject(_tableName, newRole);
                svc.SaveChangesWithRetries();
            }
            catch (InvalidOperationException e)
            {
                // when retry policies are used we cannot distinguish between a conflict and success
                // so, in the case of a conflict, we just retrun success here
                if (e.InnerException is DataServiceClientException && (e.InnerException as DataServiceClientException).StatusCode == (int)HttpStatusCode.Conflict)
                {
                    return;
                    // the role already exists
                }
                throw new ProviderException("Error accessing role table.", e);
            }
        }
예제 #19
0
        private RoleRow GetUserInRole(DataServiceContext svc, string rolename, string username)
        {
            SecUtility.CheckParameter(ref username, true, true, true, Constants.MaxTableUsernameLength, "username");
            SecUtility.CheckParameter(ref rolename, true, true, true, MaxTableRoleNameLength, "rolename");

            try
            {
                DataServiceQuery <RoleRow> queryObj = svc.CreateQuery <RoleRow>(_tableName);

                IEnumerable <RoleRow> query = from user in queryObj
                                              where user.PartitionKey == SecUtility.CombineToKey(_applicationName, username) &&
                                              user.RowKey == SecUtility.Escape(rolename)
                                              select user;
                TableStorageDataServiceQuery <RoleRow> q = new TableStorageDataServiceQuery <RoleRow>(query as DataServiceQuery <RoleRow>, _tableRetry);
                try
                {
                    IEnumerable <RoleRow> userRows = q.ExecuteAllWithRetries();
                    return(userRows.First());
                }
                catch (DataServiceQueryException e)
                {
                    HttpStatusCode s;
                    if (TableStorageHelpers.EvaluateException(e, out s) && s == HttpStatusCode.NotFound)
                    {
                        return(null);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
예제 #20
0
        public override bool RoleExists(string roleName)
        {
            SecUtility.CheckParameter(ref roleName, true, true, true, MaxTableRoleNameLength, "rolename");
            try
            {
                TableServiceContext        svc      = CreateDataServiceContext();
                DataServiceQuery <RoleRow> queryObj = svc.CreateQuery <RoleRow>(_tableName);

                var query = (from role in queryObj
                             where role.PartitionKey == SecUtility.CombineToKey(_applicationName, string.Empty) &&
                             role.RowKey == SecUtility.Escape(roleName)
                             select role).AsTableServiceQuery();

                try
                {
                    // this query addresses exactly one result
                    // we thus should get an exception if there is no element
                    return(query.Execute().Any());
                }
                catch (InvalidOperationException e)
                {
                    if ((e.InnerException is DataServiceClientException && (e.InnerException as DataServiceClientException).StatusCode == (int)HttpStatusCode.NotFound) ||
                        (e.InnerException.InnerException is DataServiceClientException && (e.InnerException.InnerException as DataServiceClientException).StatusCode == (int)HttpStatusCode.NotFound))
                    {
                        return(false);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
예제 #21
0
        public override void SetAndReleaseItemExclusive(HttpContext context, string id,
                                                        SessionStateStoreData item, object lockId, bool newItem)
        {
            Debug.Assert(context != null);
            SecUtility.CheckParameter(ref id, true, true, false, Configuration.MaxStringPropertySizeInChars, "id");

            _providerRetry(() =>
            {
                TableServiceContext svc = CreateDataServiceContext();
                SessionRow session;

                if (!newItem)
                {
                    session = GetSession(id, svc);
                    if (session == null || session.Lock != (int)lockId)
                    {
                        Debug.Assert(false);
                        return;
                    }
                }
                else
                {
                    session             = new SessionRow(id, _applicationName);
                    session.Lock        = 1;
                    session.LockDateUtc = DateTime.UtcNow;
                }
                session.Initialized = true;
                Debug.Assert(session.Timeout >= 0);
                session.Timeout    = item.Timeout;
                session.ExpiresUtc = DateTime.UtcNow.AddMinutes(session.Timeout);
                session.Locked     = false;

                // yes, we always create a new blob here
                session.BlobName = GetBlobNamePrefix(id) + Guid.NewGuid().ToString("N");


                // Serialize the session and write the blob
                byte[] items, statics;
                SerializeSession(item, out items, out statics);
                string serializedItems   = Convert.ToBase64String(items);
                string serializedStatics = Convert.ToBase64String(statics);
                MemoryStream output      = new MemoryStream();
                StreamWriter writer      = new StreamWriter(output);

                try
                {
                    writer.WriteLine(serializedItems);
                    writer.WriteLine(serializedStatics);
                    writer.Flush();
                    // for us, it shouldn't matter whether newItem is set to true or false
                    // because we always create the entire blob and cannot append to an
                    // existing one
                    _blobProvider.UploadStream(session.BlobName, output);
                    writer.Close();
                    output.Close();
                }
                catch (Exception e)
                {
                    if (!newItem)
                    {
                        ReleaseItemExclusive(svc, session, lockId);
                    }
                    throw new ProviderException("Error accessing the data store.", e);
                }
                finally
                {
                    if (writer != null)
                    {
                        writer.Close();
                    }
                    if (output != null)
                    {
                        output.Close();
                    }
                }

                if (newItem)
                {
                    svc.AddObject(_tableName, session);
                    svc.SaveChangesWithRetries();
                }
                else
                {
                    // Unlock the session and save changes
                    ReleaseItemExclusive(svc, session, lockId);
                }
            });
        }
예제 #22
0
        public override void Initialize(string name, NameValueCollection config)
        {
            // Verify that config isn't null
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            // Assign the provider a default name if it doesn't have one
            if (String.IsNullOrEmpty(name))
            {
                name = "TableServiceSessionStateProvider";
            }

            // Add a default "description" attribute to config if the
            // attribute doesn't exist or is empty
            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "Session state provider using table storage");
            }

            // Call the base class's Initialize method
            base.Initialize(name, config);

            bool allowInsecureRemoteEndpoints = Configuration.GetBooleanValue(config, "allowInsecureRemoteEndpoints", false);

            // structure storage-related properties
            _applicationName = Configuration.GetStringValueWithGlobalDefault(config, "applicationName",
                                                                             Configuration.DefaultProviderApplicationNameConfigurationString,
                                                                             Configuration.DefaultProviderApplicationName, false);
            _tableName = Configuration.GetStringValueWithGlobalDefault(config, "sessionTableName",
                                                                       Configuration.DefaultSessionTableNameConfigurationString,
                                                                       Configuration.DefaultSessionTableName, false);
            _containerName = Configuration.GetStringValueWithGlobalDefault(config, "containerName",
                                                                           Configuration.DefaultSessionContainerNameConfigurationString,
                                                                           Configuration.DefaultSessionContainerName, false);

            if (!SecUtility.IsValidContainerName(_containerName))
            {
                throw new ProviderException("The provider configuration for the TableStorageSessionStateProvider does not contain a valid container name. " +
                                            "Please refer to the documentation for the concrete rules for valid container names." +
                                            "The current container name is: " + _containerName);
            }

            config.Remove("allowInsecureRemoteEndpoints");
            config.Remove("containerName");
            config.Remove("applicationName");
            config.Remove("sessionTableName");

            // Throw an exception if unrecognized attributes remain
            if (config.Count > 0)
            {
                string attr = config.GetKey(0);
                if (!String.IsNullOrEmpty(attr))
                {
                    throw new ProviderException
                              ("Unrecognized attribute: " + attr);
                }
            }

            CloudStorageAccount account = null;

            try
            {
                account = Configuration.GetStorageAccount(Configuration.DefaultStorageConfigurationString);
                SecUtility.CheckAllowInsecureEndpoints(allowInsecureRemoteEndpoints, account.Credentials, account.TableEndpoint);
                SecUtility.CheckAllowInsecureEndpoints(allowInsecureRemoteEndpoints, account.Credentials, account.BlobEndpoint);

                _tableStorage             = account.CreateCloudTableClient();
                _tableStorage.RetryPolicy = _tableRetry;

                lock (thisLock)
                {
                    _tableStorage.CreateTableIfNotExist <SessionRow>(_tableName);
                }

                _blobProvider = new BlobProvider(account.Credentials, account.BlobEndpoint, _containerName);
            }
            catch (SecurityException)
            {
                throw;
            }
            // catch InvalidOperationException as well as StorageException
            catch (Exception e)
            {
                string exceptionDescription = Configuration.GetInitExceptionDescription(account.Credentials, account.TableEndpoint, account.BlobEndpoint);
                string tableName            = (_tableName == null) ? "no session table name specified" : _tableName;
                string containerName        = (_containerName == null) ? "no container name specified" : _containerName;
                Log.Write(EventKind.Error, "Initialization of data service structures (tables and/or blobs) failed!" +
                          exceptionDescription + Environment.NewLine +
                          "Configured blob container: " + containerName + Environment.NewLine +
                          "Configured table name: " + tableName + Environment.NewLine +
                          e.Message + Environment.NewLine + e.StackTrace);
                throw new ProviderException("Initialization of data service structures (tables and/or blobs) failed!" +
                                            "The most probable reason for this is that " +
                                            "the storage endpoints are not configured correctly. Please look at the configuration settings " +
                                            "in your .cscfg and Web.config files. More information about this error " +
                                            "can be found in the logs when running inside the hosting environment or in the output " +
                                            "window of Visual Studio.", e);
            }
            Debug.Assert(_blobProvider != null);
        }
예제 #23
0
        // RoleProvider methods
        public override void Initialize(string name, NameValueCollection config)
        {
            // Verify that config isn't null
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            // Assign the provider a default name if it doesn't have one
            if (String.IsNullOrEmpty(name))
            {
                name = "TableStorageRoleProvider";
            }

            // Add a default "description" attribute to config if the
            // attribute doesn't exist or is empty
            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "Table storage-based role provider");
            }

            // Call the base class's Initialize method
            base.Initialize(name, config);

            bool allowInsecureRemoteEndpoints = Configuration.GetBooleanValue(config, "allowInsecureRemoteEndpoints", false);

            // structure storage-related properties
            ApplicationName = Configuration.GetStringValueWithGlobalDefault(config, "applicationName",
                                                                            Configuration.DefaultProviderApplicationNameConfigurationString,
                                                                            Configuration.DefaultProviderApplicationName, false);
            _accountName = Configuration.GetStringValue(config, "accountName", null, true);
            _sharedKey   = Configuration.GetStringValue(config, "sharedKey", null, true);
            _tableName   = Configuration.GetStringValueWithGlobalDefault(config, "roleTableName",
                                                                         Configuration.DefaultRoleTableNameConfigurationString,
                                                                         Configuration.DefaultRoleTableName, false);
            _membershipTableName = Configuration.GetStringValueWithGlobalDefault(config, "membershipTableName",
                                                                                 Configuration.DefaultMembershipTableNameConfigurationString,
                                                                                 Configuration.DefaultMembershipTableName, false);
            _tableServiceBaseUri = Configuration.GetStringValue(config, "tableServiceBaseUri", null, true);

            // remove required attributes
            config.Remove("allowInsecureRemoteEndpoints");
            config.Remove("applicationName");
            config.Remove("accountName");
            config.Remove("sharedKey");
            config.Remove("roleTableName");
            config.Remove("membershipTableName");
            config.Remove("tableServiceBaseUri");


            // Throw an exception if unrecognized attributes remain
            if (config.Count > 0)
            {
                string attr = config.GetKey(0);
                if (!String.IsNullOrEmpty(attr))
                {
                    throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "Unrecognized attribute: {0}", attr));
                }
            }

            StorageAccountInfo info = null;

            try
            {
                info = StorageAccountInfo.GetDefaultTableStorageAccountFromConfiguration(true);
                if (_tableServiceBaseUri != null)
                {
                    info.BaseUri = new Uri(_tableServiceBaseUri);
                }
                if (_accountName != null)
                {
                    info.AccountName = _accountName;
                }
                if (_sharedKey != null)
                {
                    info.Base64Key = _sharedKey;
                }
                info.CheckComplete();
                SecUtility.CheckAllowInsecureEndpoints(allowInsecureRemoteEndpoints, info);
                _tableStorage             = TableStorage.Create(info);
                _tableStorage.RetryPolicy = _tableRetry;
                _tableStorage.TryCreateTable(_tableName);
            }
            catch (SecurityException)
            {
                throw;
            }
            // catch InvalidOperationException as well as StorageException
            catch (Exception e)
            {
                string exceptionDescription = Configuration.GetInitExceptionDescription(info, "table storage configuration");
                string tableName            = (_tableName == null) ? "no role table name specified" : _tableName;
                Log.Write(EventKind.Error, "Could not create or find role table: " + tableName + "!" + Environment.NewLine +
                          exceptionDescription + Environment.NewLine +
                          e.Message + Environment.NewLine + e.StackTrace);
                throw new ProviderException("Could not create or find role table. The most probable reason for this is that " +
                                            "the storage endpoints are not configured correctly. Please look at the configuration settings " +
                                            "in your .cscfg and Web.config files. More information about this error " +
                                            "can be found in the logs when running inside the hosting environment or in the output " +
                                            "window of Visual Studio.", e);
            }
        }
        public override void Initialize(string name, NameValueCollection config)
        {
            // Verify that config isn't null
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            // Assign the provider a default name if it doesn't have one
            if (String.IsNullOrEmpty(name))
            {
                name = "TableServiceSessionStateProvider";
            }

            // Add a default "description" attribute to config if the
            // attribute doesn't exist or is empty
            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "Session state provider using table storage");
            }

            // Call the base class's Initialize method
            base.Initialize(name, config);

            bool allowInsecureRemoteEndpoints = Configuration.GetBooleanValue(config, "allowInsecureRemoteEndpoints", false);

            // structure storage-related properties
            _applicationName = Configuration.GetStringValueWithGlobalDefault(config, "applicationName",
                                                                             Configuration.DefaultProviderApplicationNameConfigurationString,
                                                                             Configuration.DefaultProviderApplicationName, false);
            _accountName = Configuration.GetStringValue(config, "accountName", null, true);
            _sharedKey   = Configuration.GetStringValue(config, "sharedKey", null, true);
            _tableName   = Configuration.GetStringValueWithGlobalDefault(config, "sessionTableName",
                                                                         Configuration.DefaultSessionTableNameConfigurationString,
                                                                         Configuration.DefaultSessionTableName, false);
            _tableServiceBaseUri = Configuration.GetStringValue(config, "tableServiceBaseUri", null, true);
            _containerName       = Configuration.GetStringValueWithGlobalDefault(config, "containerName",
                                                                                 Configuration.DefaultSessionContainerNameConfigurationString,
                                                                                 Configuration.DefaultSessionContainerName, false);
            if (!SecUtility.IsValidContainerName(_containerName))
            {
                throw new ProviderException("The provider configuration for the TableStorageSessionStateProvider does not contain a valid container name. " +
                                            "Please refer to the documentation for the concrete rules for valid container names." +
                                            "The current container name is: " + _containerName);
            }
            _blobServiceBaseUri = Configuration.GetStringValue(config, "blobServiceBaseUri", null, true);

            config.Remove("allowInsecureRemoteEndpoints");
            config.Remove("accountName");
            config.Remove("sharedKey");
            config.Remove("containerName");
            config.Remove("applicationName");
            config.Remove("blobServiceBaseUri");
            config.Remove("tableServiceBaseUri");
            config.Remove("sessionTableName");

            // Throw an exception if unrecognized attributes remain
            if (config.Count > 0)
            {
                string attr = config.GetKey(0);
                if (!String.IsNullOrEmpty(attr))
                {
                    throw new ProviderException
                              ("Unrecognized attribute: " + attr);
                }
            }

            //StorageCredentialsAccountAndKey tableInfo = null;
            //StorageCredentialsAccountAndKey blobInfo = null;
            string tableBaseUri = null;
            string blobBaseUri  = null;

            try
            {
                var sharedKey   = Configuration.TryGetAppSetting(Configuration.DefaultAccountSharedKeyConfigurationString);
                var accountName = Configuration.TryGetAppSetting(Configuration.DefaultAccountNameConfigurationString);

                tableBaseUri = Configuration.TryGetAppSetting(Configuration.DefaultTableStorageEndpointConfigurationString);
                blobBaseUri  = Configuration.TryGetAppSetting(Configuration.DefaultBlobStorageEndpointConfigurationString);

                if (_tableServiceBaseUri != null)
                {
                    tableBaseUri = _tableServiceBaseUri;
                }
                if (_blobServiceBaseUri != null)
                {
                    blobBaseUri = _blobServiceBaseUri;
                }
                if (_accountName != null)
                {
                    accountName = _accountName;
                }
                if (_sharedKey != null)
                {
                    sharedKey = _sharedKey;
                }

                if (String.IsNullOrEmpty(sharedKey) || String.IsNullOrEmpty(accountName) || String.IsNullOrEmpty(tableBaseUri) || String.IsNullOrEmpty(blobBaseUri))
                {
                    throw new ConfigurationErrorsException("Account information incomplete!");
                }

                //tableInfo = new StorageCredentialsAccountAndKey(accountName, sharedKey);
                //blobInfo = new StorageCredentialsAccountAndKey(accountName, sharedKey);
                //SecUtility.CheckAllowInsecureEndpoints(allowInsecureRemoteEndpoints, tableInfo, new Uri(tableBaseUri));
                //SecUtility.CheckAllowInsecureEndpoints(allowInsecureRemoteEndpoints, blobInfo, new Uri(blobBaseUri));
                _tableStorage = new sqlTableClient(tableBaseUri);//, tableInfo);
                //_tableStorage.RetryPolicy = _tableRetry;
                if (_tableStorage.CreateTableIfNotExist(_tableName))
                {
                    var ctx      = _tableStorage.GetDataServiceContext();
                    var dummyRow = new SessionRow("fake", "dummy");
                    ctx.AddObject(_tableName, dummyRow);
                    ctx.SaveChangesWithRetries();
                    ctx.DeleteObject(dummyRow);
                    ctx.SaveChangesWithRetries();
                }
                //_blobProvider = new BlobProvider(blobInfo, new Uri(blobBaseUri), _containerName);
                _blobProvider = new BlobProvider(new Uri(blobBaseUri), _containerName);
            }
            catch (SecurityException)
            {
                throw;
            }
            // catch InvalidOperationException as well as StorageException
            catch (Exception e)
            {
                //string exceptionDescription = Configuration.GetInitExceptionDescription(tableInfo, new Uri(tableBaseUri), blobInfo, new Uri(blobBaseUri));
                string exceptionDescription = Configuration.GetInitExceptionDescription(new Uri(tableBaseUri), new Uri(blobBaseUri));
                string tableName            = (_tableName == null) ? "no session table name specified" : _tableName;
                string containerName        = (_containerName == null) ? "no container name specified" : _containerName;
                Log.Write(EventKind.Error, "Initialization of data service structures (tables and/or blobs) failed!" +
                          exceptionDescription + Environment.NewLine +
                          "Configured blob container: " + containerName + Environment.NewLine +
                          "Configured table name: " + tableName + Environment.NewLine +
                          e.Message + Environment.NewLine + e.StackTrace);
                throw new ProviderException("Initialization of data service structures (tables and/or blobs) failed!" +
                                            "The most probable reason for this is that " +
                                            "the storage endpoints are not configured correctly. Please look at the configuration settings " +
                                            "in your .cscfg and Web.config files. More information about this error " +
                                            "can be found in the logs when running inside the hosting environment or in the output " +
                                            "window of Visual Studio.", e);
            }
            Debug.Assert(_blobProvider != null);
        }
예제 #25
0
        // the username to match can be in a format that varies between providers
        // for this implementation, a syntax similar to the one used in the SQL provider is applied
        // "user%" will return all users in a role that start with the string "user"
        // the % sign can only appear at the end of the usernameToMatch parameter
        // because the current version of the table storage service does not support StartsWith in LINQ queries,
        // calling this function can cause significant network trafic when '%' is used in the usernameToMach
        // parameter
        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            SecUtility.CheckParameter(ref roleName, true, true, true, MaxTableRoleNameLength, "rolename");
            SecUtility.CheckParameter(ref usernameToMatch, true, true, false, Constants.MaxTableUsernameLength, "usernameToMatch");

            bool startswith = false;

            if (usernameToMatch.Contains('%'))
            {
                if (usernameToMatch.IndexOf('%') != usernameToMatch.Length - 1)
                {
                    throw new ArgumentException("The TableStorageRoleProvider only supports search strings that contain '%' as the last character!");
                }
                usernameToMatch = usernameToMatch.Substring(0, usernameToMatch.Length - 1);
                startswith      = true;
            }

            try
            {
                TableStorageDataServiceContext svc      = CreateDataServiceContext();
                DataServiceQuery <RoleRow>     queryObj = svc.CreateQuery <RoleRow>(_tableName);

                IEnumerable <RoleRow> query;

                if (startswith && string.IsNullOrEmpty(usernameToMatch))
                {
                    // get all users in the role
                    query = from userRole in queryObj
                            where userRole.PartitionKey.CompareTo(SecUtility.EscapedFirst(_applicationName)) >= 0 &&
                            userRole.PartitionKey.CompareTo(SecUtility.NextComparisonString(SecUtility.EscapedFirst(_applicationName))) < 0 &&
                            userRole.RowKey == SecUtility.Escape(roleName)
                            select userRole;
                }
                else if (startswith)
                {
                    // get all users in the role that start with the specified string (we cannot restrict the query more because StartsWith is not supported)
                    // we cannot include the username to search for in the key, because the key might e escaped
                    query = from userRole in queryObj
                            where userRole.PartitionKey.CompareTo(SecUtility.EscapedFirst(_applicationName)) >= 0 &&
                            userRole.PartitionKey.CompareTo(SecUtility.NextComparisonString(SecUtility.EscapedFirst(_applicationName))) < 0 &&
                            userRole.RowKey == SecUtility.Escape(roleName) &&
                            (userRole.UserName.CompareTo(usernameToMatch) >= 0 || userRole.UserName == string.Empty)
                            select userRole;
                }
                else
                {
                    // get a specific user
                    query = from userRole in queryObj
                            where (userRole.PartitionKey == SecUtility.CombineToKey(_applicationName, usernameToMatch) ||
                                   userRole.PartitionKey == SecUtility.CombineToKey(_applicationName, string.Empty)) &&
                            userRole.RowKey == SecUtility.Escape(roleName)
                            select userRole;
                }

                TableStorageDataServiceQuery <RoleRow> q = new TableStorageDataServiceQuery <RoleRow>(query as DataServiceQuery <RoleRow>, _tableRetry);
                IEnumerable <RoleRow> userRows           = q.ExecuteAllWithRetries();

                if (userRows == null)
                {
                    throw new ProviderException("The role does not exist!");
                }
                List <RoleRow> l = new List <RoleRow>(userRows);
                if (l.Count == 0)
                {
                    // the role does not exist
                    throw new ProviderException("The role does not exist!");
                }
                RoleRow role;
                if (IsStaleRole(l, out role))
                {
                    throw new ProviderException("The role does not exist!");
                }
                List <string> ret = new List <string>();
                foreach (RoleRow row in l)
                {
                    if (row != role)
                    {
                        if (startswith && !string.IsNullOrEmpty(usernameToMatch) && !row.UserName.StartsWith(usernameToMatch, StringComparison.Ordinal))
                        {
                            continue;
                        }
                        ret.Add(row.UserName);
                    }
                }
                return(ret.ToArray());
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
예제 #26
0
        // we don't use the retry policy itself in this function because out parameters are not well handled by
        // retry policies
        private SessionStateStoreData GetSession(HttpContext context, string id, out bool locked, out TimeSpan lockAge,
                                                 out object lockId, out SessionStateActions actions,
                                                 bool exclusive)
        {
            Debug.Assert(context != null);
            SecUtility.CheckParameter(ref id, true, true, false, Configuration.MaxStringPropertySizeInChars, "id");

            SessionRow session = null;

            int  curRetry = 0;
            bool retry    = false;

            // Assign default values to out parameters
            locked  = false;
            lockId  = null;
            lockAge = TimeSpan.Zero;
            actions = SessionStateActions.None;

            do
            {
                retry = false;
                try
                {
                    TableServiceContext svc = CreateDataServiceContext();
                    session = GetSession(id, svc);

                    // Assign default values to out parameters
                    locked  = false;
                    lockId  = null;
                    lockAge = TimeSpan.Zero;
                    actions = SessionStateActions.None;

                    // if the blob does not exist, we return null
                    // ASP.NET will call the corresponding method for creating the session
                    if (session == null)
                    {
                        return(null);
                    }
                    if (session.Initialized == false)
                    {
                        Debug.Assert(session.Locked == false);
                        actions             = SessionStateActions.InitializeItem;
                        session.Initialized = true;
                    }
                    session.ExpiresUtc = DateTime.UtcNow.AddMinutes(session.Timeout);
                    if (exclusive)
                    {
                        if (!session.Locked)
                        {
                            if (session.Lock == Int32.MaxValue)
                            {
                                session.Lock = 0;
                            }
                            else
                            {
                                session.Lock++;
                            }
                            session.LockDateUtc = DateTime.UtcNow;
                        }
                        lockId         = session.Lock;
                        locked         = session.Locked;
                        session.Locked = true;
                    }
                    lockAge = DateTime.UtcNow.Subtract(session.LockDateUtc);
                    lockId  = session.Lock;

                    if (locked == true)
                    {
                        return(null);
                    }

                    // let's try to write this back to the data store
                    // in between, someone else could have written something to the store for the same session
                    // we retry a number of times; if all fails, we throw an exception
                    svc.UpdateObject(session);
                    svc.SaveChangesWithRetries();
                }
                catch (InvalidOperationException e)
                {
                    // precondition fails indicates problems with the status code
                    if (e.InnerException is DataServiceClientException && (e.InnerException as DataServiceClientException).StatusCode == (int)HttpStatusCode.PreconditionFailed)
                    {
                        retry = true;
                    }
                    else
                    {
                        throw new ProviderException("Error accessing the data store.", e);
                    }
                }
            } while (retry && curRetry++ < NumRetries);

            // ok, now we have successfully written back our state
            // we can now read the blob
            // note that we do not need to care about read/write locking when accessing the
            // blob because each time we write a new session we create a new blob with a different name

            SessionStateStoreData result = null;
            MemoryStream          stream = null;
            StreamReader          reader = null;
            BlobProperties        properties;

            try
            {
                try
                {
                    stream = _blobProvider.GetBlobContent(session.BlobName, out properties);
                }
                catch (Exception e)
                {
                    throw new ProviderException("Couldn't read session blob!", e);
                }

                reader = new StreamReader(stream);
                if (actions == SessionStateActions.InitializeItem)
                {
                    // Return an empty SessionStateStoreData
                    result = new SessionStateStoreData(new SessionStateItemCollection(),
                                                       SessionStateUtility.GetSessionStaticObjects(context), session.Timeout);
                }
                else
                {
                    // Read Items, StaticObjects, and Timeout from the file
                    byte[] items   = Convert.FromBase64String(reader.ReadLine());
                    byte[] statics = Convert.FromBase64String(reader.ReadLine());
                    int    timeout = session.Timeout;
                    // Deserialize the session
                    result = DeserializeSession(items, statics, timeout);
                }
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
                if (reader != null)
                {
                    reader.Close();
                }
            }
            return(result);
        }
예제 #27
0
        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            SecUtility.CheckParameter(ref roleName, true, true, true, MaxTableRoleNameLength, "rolename");

            try
            {
                TableStorageDataServiceContext svc      = CreateDataServiceContext();
                DataServiceQuery <RoleRow>     queryObj = svc.CreateQuery <RoleRow>(_tableName);

                IEnumerable <RoleRow> query = from userRole in queryObj
                                              where userRole.PartitionKey.CompareTo(SecUtility.EscapedFirst(_applicationName)) >= 0 &&
                                              userRole.PartitionKey.CompareTo(SecUtility.NextComparisonString(SecUtility.EscapedFirst(_applicationName))) < 0 &&
                                              userRole.RowKey == SecUtility.Escape(roleName)
                                              select userRole;
                TableStorageDataServiceQuery <RoleRow> q = new TableStorageDataServiceQuery <RoleRow>(query as DataServiceQuery <RoleRow>, _tableRetry);
                IEnumerable <RoleRow> userRows           = q.ExecuteAllWithRetries();

                if (userRows == null)
                {
                    return(false);
                }
                List <RoleRow> l = new List <RoleRow>(userRows);
                if (l.Count == 0)
                {
                    // the role does not exist
                    return(false);
                }
                RoleRow role;
                if (IsStaleRole(l, out role))
                {
                    return(false);
                }
                if (l.Count > 1 && throwOnPopulatedRole)
                {
                    throw new ProviderException("Cannot delete populated role.");
                }
                svc.DeleteObject(role);
                svc.SaveChangesWithRetries();
                // lets try to remove all remaining elements in the role
                foreach (RoleRow row in l)
                {
                    if (row != role)
                    {
                        try
                        {
                            svc.DeleteObject(row);
                            svc.SaveChangesWithRetries();
                        }
                        catch (InvalidOperationException ex)
                        {
                            HttpStatusCode status;
                            if (TableStorageHelpers.EvaluateException(ex, out status) && (status == HttpStatusCode.NoContent || status == HttpStatusCode.NotFound))
                            {
                                // this element already was already deleted by another process or during a failed retry
                                // this is not a fatal error; continue deleting elements
                                Log.Write(EventKind.Warning, string.Format(CultureInfo.InstalledUICulture, "The user {0} does not exist in the role {1}.", row.UserName, row.RoleName));
                            }
                            else
                            {
                                throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "Error deleting user {0} from role {1}.", row.UserName, row.RoleName));
                            }
                        }
                    }
                }
                return(true);
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
        // RoleProvider methods
        public override void Initialize(string name, NameValueCollection config)
        {
            // Verify that config isn't null
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            // Assign the provider a default name if it doesn't have one
            if (String.IsNullOrEmpty(name))
            {
                name = "TableStorageRoleProvider";
            }

            // Add a default "description" attribute to config if the
            // attribute doesn't exist or is empty
            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "Table storage-based role provider");
            }

            // Call the base class's Initialize method
            base.Initialize(name, config);

            bool allowInsecureRemoteEndpoints = Configuration.GetBooleanValue(config, "allowInsecureRemoteEndpoints", false);

            // structure storage-related properties
            ApplicationName = Configuration.GetStringValueWithGlobalDefault(config, "applicationName",
                                                                            Configuration.DefaultProviderApplicationNameConfigurationString,
                                                                            Configuration.DefaultProviderApplicationName, false);

            _account =
                CloudStorageAccount.Parse(
                    RoleEnvironment.GetConfigurationSettingValue(Configuration.ConfigurationStorageConnectionStringName));

            _tableName = Configuration.GetStringValueWithGlobalDefault(config, "roleTableName",
                                                                       Configuration.DefaultRoleTableNameConfigurationString,
                                                                       Configuration.DefaultRoleTableName, false);

            Configuration.GetStringValueWithGlobalDefault(config, "membershipTableName",
                                                          Configuration.DefaultMembershipTableNameConfigurationString,
                                                          Configuration.DefaultMembershipTableName, false);
            Configuration.GetStringValue(config, "tableServiceBaseUri", null, true);

            // remove required attributes
            config.Remove("allowInsecureRemoteEndpoints");
            config.Remove("applicationName");
            config.Remove("roleTableName");
            config.Remove("membershipTableName");


            // Throw an exception if unrecognized attributes remain
            if (config.Count > 0)
            {
                string attr = config.GetKey(0);
                if (!String.IsNullOrEmpty(attr))
                {
                    throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "Unrecognized attribute: {0}", attr));
                }
            }

            if (_account == null)
            {
                throw new ConfigurationErrorsException("Account information incomplete!");
            }

            _tableStorage = _account.CreateCloudTableClient();
            try
            {
                _tableStorage.RetryPolicy = _tableRetry;
                SecUtility.CheckAllowInsecureEndpoints(allowInsecureRemoteEndpoints, _tableStorage.BaseUri);

                if (_tableStorage.CreateTableIfNotExist(_tableName))
                {
                    var ctx      = _tableStorage.GetDataServiceContext();
                    var dummyRow = new RoleRow("dummy", "fake", "none");
                    ctx.AddObject(_tableName, dummyRow);
                    ctx.SaveChangesWithRetries();
                    ctx.DeleteObject(dummyRow);
                    ctx.SaveChangesWithRetries();
                }
            }
            catch (SecurityException)
            {
                throw;
            }
            // catch InvalidOperationException as well as StorageException
            catch (Exception e)
            {
                string exceptionDescription = Configuration.GetInitExceptionDescription(_tableStorage.Credentials as StorageCredentialsAccountAndKey, _tableStorage.BaseUri, "table storage configuration");
                string tableName            = _tableName ?? "no role table name specified";
                Log.Write(EventKind.Error, "Could not create or find role table: " + tableName + "!" + Environment.NewLine +
                          exceptionDescription + Environment.NewLine +
                          e.Message + Environment.NewLine + e.StackTrace);
                throw new ProviderException("Could not create or find role table. The most probable reason for this is that " +
                                            "the storage endpoints are not configured correctly. Please look at the configuration settings " +
                                            "in your .cscfg and Web.config files. More information about this error " +
                                            "can be found in the logs when running inside the hosting environment or in the output " +
                                            "window of Visual Studio.", e);
            }
        }