public MembershipTable CreateMembershipTable() { var table = new MembershipTable(); table.Version = membershipVersion; table.Rows = new List <MembershipRow>(); foreach (var activation in activations.Values) { if (activation.Identity.Category == Identity.Categories.Service) { var service = (IService)activation.Addressable; var row = new MembershipRow(); row.Identity = activation.Identity; row.ServiceType = activation.InterfaceType.AssemblyQualifiedName; if (service.Metadata != null) { row.Metadata = binarySerializer.Serialize(service.Metadata); } table.Rows.Add(row); } } return(table); }
private void CreateOrUpdateUserAndProfile(string username, bool authenticated, DateTime now, string blobName, int size) { Debug.Assert(now.Kind == DateTimeKind.Utc); SecUtility.CheckParameter(ref username, true, true, true, Constants.MaxTableUsernameLength, "username"); _providerRetry(() => { TableServiceContext context = CreateDataServiceContext(); DataServiceQuery<MembershipRow> queryObj = context.CreateQuery<MembershipRow>(_tableName); var query = (from user in queryObj where user.PartitionKey == SecUtility.CombineToKey(_applicationName, username) select user).AsTableServiceQuery(); IEnumerable<MembershipRow> users = query.Execute(); // instantiate results List<MembershipRow> userList = null; if (users != null) { userList = new List<MembershipRow>(users); } if (userList != null && userList.Count > 0) { MembershipRow current = userList.First(); if (current.IsAnonymous != !authenticated) { // this is an error because we would need to create a user with the same name // this should not happen throw new ProviderException("A user with the same name but with a different authentication status already exists!"); } current.LastActivityDateUtc = now; current.ProfileBlobName = blobName; current.ProfileSize = size; current.ProfileLastUpdatedUtc = now; context.UpdateObject(current); } else { if (authenticated) { Log.Write(EventKind.Warning, "The authenticated user does not exist in the database."); } MembershipRow member = new MembershipRow(_applicationName, username); member.LastActivityDateUtc = now; member.IsAnonymous = !authenticated; member.ProfileBlobName = blobName; member.ProfileSize = size; member.ProfileLastUpdatedUtc = now; member.ProfileIsCreatedByProfileProvider = true; context.AddObject(_tableName, member); } context.SaveChanges(); }); }
// we don't use _providerRetry here because of the out parameter prof private bool DoesProfileExistAndUpdateUser(string username, out MembershipRow prof) { SecUtility.CheckParameter(ref username, true, true, true, Constants.MaxTableUsernameLength, "username"); int curRetry = 0; bool retry = false; do { retry = false; try { TableServiceContext context = CreateDataServiceContext(); DataServiceQuery<MembershipRow> queryObj = context.CreateQuery<MembershipRow>(_tableName); var query = (from profile in queryObj where profile.PartitionKey == SecUtility.CombineToKey(_applicationName, username) select profile).AsTableServiceQuery(); IEnumerable<MembershipRow> profiles = query.Execute(); if (profiles == null) { prof = null; return false; } // instantiate results List<MembershipRow> profileList = new List<MembershipRow>(profiles); if (profileList.Count > 1) { throw new ProviderException("Multiple profile rows for the same user!"); } if (profileList.Count == 1) { prof = profileList.First(); if (!string.IsNullOrEmpty(prof.ProfileBlobName)) { prof.LastActivityDateUtc = DateTime.UtcNow; context.UpdateObject(prof); context.SaveChangesWithRetries(); return true; } else { return false; } } else { prof = null; return false; } } catch (InvalidOperationException e) { if (e.InnerException is DataServiceClientException && (e.InnerException as DataServiceClientException).StatusCode == (int)HttpStatusCode.PreconditionFailed) { retry = true; } else { throw new ProviderException("Error accessing storage.", e); } } } while (curRetry++ < NumRetries && retry); prof = null; return false; }
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 = "TableStorageProfileProvider"; } // 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 profile 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)); // profile information are stored in the membership table _tableName = Configuration.GetStringValueWithGlobalDefault(config, "membershipTableName", Configuration.DefaultMembershipTableNameConfigurationString, Configuration.DefaultMembershipTableName, false); _containerName = Configuration.GetStringValueWithGlobalDefault(config, "containerName", Configuration.DefaultProfileContainerNameConfigurationString, Configuration.DefaultProfileContainerName, false); if (!SecUtility.IsValidContainerName(_containerName)) { throw new ProviderException("The provider configuration for the TableStorageProfileProvider 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); // remove required attributes config.Remove("allowInsecureRemoteEndpoints"); config.Remove("applicationName"); config.Remove("membershipTableName"); config.Remove("containerName"); config.Remove("tableServiceBaseUri"); config.Remove("blobServiceBaseUri"); // 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)); } } // profiles are stored within the membership table _tableStorage = _account.CreateCloudTableClient(); var blobClient = _account.CreateCloudBlobClient(); try { if (_account == null) throw new ConfigurationErrorsException("Account information incomplete!"); _tableStorage.RetryPolicy = _tableRetry; SecUtility.CheckAllowInsecureEndpoints(allowInsecureRemoteEndpoints, _tableStorage.BaseUri); if (_tableStorage.CreateTableIfNotExist(_tableName)) { var ctx = _tableStorage.GetDataServiceContext(); var dummyRow = new MembershipRow("dummy", "none"); ctx.AddObject(_tableName, dummyRow); ctx.SaveChangesWithRetries(); ctx.DeleteObject(dummyRow); ctx.SaveChangesWithRetries(); } SecUtility.CheckAllowInsecureEndpoints(allowInsecureRemoteEndpoints, blobClient.BaseUri); _blobProvider = new BlobProvider(blobClient, _containerName); } catch (SecurityException) { throw; } // catch InvalidOperationException and StorageException catch (Exception e) { string exceptionDescription = Configuration.GetInitExceptionDescription(blobClient, _tableStorage); string tableName = _tableName ?? "no profile table name specified"; string containerName = _containerName ?? "no container name specified"; Log.Write(EventKind.Error, "Initialization of data service structures (tables and/or blobs) failed!" + Environment.NewLine + 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); }
public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection) { if (collection == null) { throw new ArgumentNullException("collection"); } if (context == null) { throw new ArgumentNullException("context"); } SettingsPropertyValueCollection settings = new SettingsPropertyValueCollection(); // Do nothing if there are no properties to retrieve if (collection.Count < 1) { return(settings); } // For properties lacking an explicit SerializeAs setting, set // SerializeAs to String for strings and primitives, and XML // for everything else foreach (SettingsProperty property in collection) { if (property.SerializeAs == SettingsSerializeAs.ProviderSpecific) { if (property.PropertyType.IsPrimitive || property.PropertyType == typeof(String)) { property.SerializeAs = SettingsSerializeAs.String; } else { property.SerializeAs = SettingsSerializeAs.Xml; } } settings.Add(new SettingsPropertyValue(property)); } // Get the user name or anonymous user ID string username = (string)context["UserName"]; if (string.IsNullOrEmpty(username)) { return(settings); } if (!VerifyUsername(ref username)) { return(settings); } MembershipRow profile = null; if (!DoesProfileExistAndUpdateUser(username, out profile)) { // the profile does not exist // we update the last activity time of the user only if the profile does exist // so we can just return here return(settings); } Debug.Assert(profile != null); // We are ready to go: load the profile // Note that we do not have to deal with write locks here because we use a // different blob name each time we write a new profile StreamReader reader = null; MemoryStream stream = null; sqlBlobProperties blobProperties; string[] names; string values; byte[] buf = null; string line; try { // Open the blob containing the profile data stream = new MemoryStream(); if (!_blobProvider.GetBlobContentsWithoutInitialization(profile.ProfileBlobName, stream, out blobProperties) || blobProperties.Length == 0) { // not an error if the blob does not exist return(settings); } stream.Seek(0, SeekOrigin.Begin); reader = new StreamReader(stream); // Read names, values, and buf from the blob line = reader.ReadLine(); names = line.Split(':'); values = reader.ReadLine(); if (!string.IsNullOrEmpty(values)) { UnicodeEncoding encoding = new UnicodeEncoding(); values = encoding.GetString(Convert.FromBase64String(values)); } string temp = reader.ReadLine(); if (!String.IsNullOrEmpty(temp)) { buf = Convert.FromBase64String(temp); } else { buf = new byte[0]; } } catch (InvalidOperationException se) { throw new ProviderException("Error accessing blob storage when getting property values!", se); } catch (Exception e) { throw new ProviderException("Error getting property values.", e); } finally { if (reader != null) { reader.Close(); } if (stream != null) { stream.Close(); } } // Decode names, values, and buf and initialize the // SettingsPropertyValueCollection returned to the caller DecodeProfileData(names, values, buf, settings); return(settings); }
// we don't use _providerRetry here because of the out parameter prof private bool DoesProfileExistAndUpdateUser(string username, out MembershipRow prof) { prof = null; return(false); //SecUtility.CheckParameter(ref username, true, true, true, Constants.MaxTableUsernameLength, "username"); //int curRetry = 0; //bool retry = false; //do //{ // retry = false; // try // { // TableServiceContext context = CreateDataServiceContext(); // DataServiceQuery<MembershipRow> queryObj = context.CreateQuery<MembershipRow>(_tableName); // var query = (from profile in queryObj // where profile.PartitionKey == SecUtility.CombineToKey(_applicationName, username) // select profile).AsTableServiceQuery(); // IEnumerable<MembershipRow> profiles = query.Execute(); // if (profiles == null) // { // prof = null; // return false; // } // // instantiate results // List<MembershipRow> profileList = new List<MembershipRow>(profiles); // if (profileList.Count > 1) // { // throw new ProviderException("Multiple profile rows for the same user!"); // } // if (profileList.Count == 1) // { // prof = profileList.First(); // if (!string.IsNullOrEmpty(prof.ProfileBlobName)) // { // prof.LastActivityDateUtc = DateTime.UtcNow; // context.UpdateObject(prof); // context.SaveChangesWithRetries(); // return true; // } // else // { // return false; // } // } // else // { // prof = null; // return false; // } // } // catch (InvalidOperationException e) // { // if (e.InnerException is DataServiceClientException && (e.InnerException as DataServiceClientException).StatusCode == (int)HttpStatusCode.PreconditionFailed) // { // retry = true; // } // else // { // throw new ProviderException("Error accessing storage.", e); // } // } //} while (curRetry++ < NumRetries && retry); //prof = null; //return false; }