public DeviceTwinName GetValidNames(string whitelist, DevicePropertyServiceModel existingData, string eventData) { ParseWhitelist(whitelist, out var fullNameWhitelist, out var prefixWhitelist); var validNames = new DeviceTwinName { Tags = fullNameWhitelist.Tags, ReportedProperties = fullNameWhitelist.ReportedProperties, }; if (existingData != null && (existingData.Tags.Count > 0 || existingData.Reported.Count > 0)) { validNames.Tags.UnionWith(existingData.Tags); validNames.ReportedProperties.UnionWith(existingData.Reported); } if (prefixWhitelist.Tags.Any() || prefixWhitelist.ReportedProperties.Any()) { DeviceTwinName allNames = new DeviceTwinName(); try { // Get list of tags and reported properties from the twin change event data received by Event hub allNames = this.GetDeviceTwinNames(eventData); } catch (Exception e) { throw new Exception("Unable to fetch IoT devices", e); } if (allNames != null) { validNames.Tags.UnionWith(allNames.Tags. Where(s => prefixWhitelist.Tags.Any(s.StartsWith))); validNames.ReportedProperties.UnionWith( allNames.ReportedProperties.Where( s => prefixWhitelist.ReportedProperties.Any(s.StartsWith))); } } return(validNames); }
private static void ParseWhitelist( string whitelist, out DeviceTwinName fullNameWhitelist, out DeviceTwinName prefixWhitelist) { var whitelistItems = whitelist.Split(',').Select(s => s.Trim()); var tags = whitelistItems .Where(s => s.StartsWith(WhitelistTagPrefix, StringComparison.OrdinalIgnoreCase)) .Select(s => s.Substring(WhitelistTagPrefix.Length)); var reported = whitelistItems .Where(s => s.StartsWith(WhitelistReportedPrefix, StringComparison.OrdinalIgnoreCase)) .Select(s => s.Substring(WhitelistReportedPrefix.Length)); var fixedTags = tags.Where(s => !s.EndsWith("*")); var fixedReported = reported.Where(s => !s.EndsWith("*")); var regexTags = tags.Where(s => s.EndsWith("*")).Select(s => s.Substring(0, s.Length - 1)); var regexReported = reported. Where(s => s.EndsWith("*")). Select(s => s.Substring(0, s.Length - 1)); fullNameWhitelist = new DeviceTwinName { Tags = new HashSet <string>(fixedTags), ReportedProperties = new HashSet <string>(fixedReported), }; prefixWhitelist = new DeviceTwinName { Tags = new HashSet <string>(regexTags), ReportedProperties = new HashSet <string>(regexReported), }; }
public async Task <bool> UpdateDevicePropertiesAsync(string eventData, string tenant) { bool updateStatus = false; DevicePropertyServiceModel existingDevProperties = null; ValueServiceModel deviceCacheValue = null; CosmosOperations docClient = null; try { this.cosmosDbcoll = $"{CollectionKey}-{tenant}"; this.cosmosDb = Environment.GetEnvironmentVariable("DevicePropertiesCacheDatabaseId", EnvironmentVariableTarget.Process); this.whitelist = Environment.GetEnvironmentVariable("WhiteList", EnvironmentVariableTarget.Process); this.cosmosDbRus = Convert.ToInt32(Environment.GetEnvironmentVariable("CosmosDBRus", EnvironmentVariableTarget.Process)); this.cosmosConnectionString = Environment.GetEnvironmentVariable("CosmosDbConnectionString", EnvironmentVariableTarget.Process); docClient = await CosmosOperations.GetClientAsync(); updateStatus = await docClient.CreateCollectionIfNotExistsAsync(this.cosmosDb, this.cosmosDbcoll, this.cosmosDbRus, CosmosOperation.DeviceCache); // CosmosHelper cosmosHelper = new CosmosHelper(cosmosConnectionString, cosmosDbcoll, cosmosDb, tenant, cosmosDbRus, CosmosOperation.devicecache); try { deviceCacheValue = await docClient.GetDocumentAsync(this.GenerateCollectionLink(this.cosmosDb, this.cosmosDbcoll), CollectionId, Key); existingDevProperties = JsonConvert.DeserializeObject <DevicePropertyServiceModel>(deviceCacheValue.Data); } catch (ResourceNotFoundException) { // Do nothing } catch (Exception exception) { throw new ApplicationException("Get Device Properties failed", exception); } DeviceTwinNameOperations devTwinOps = new DeviceTwinNameOperations(); DeviceTwinName deviceTwinName = devTwinOps.GetValidNames(this.whitelist, existingDevProperties, eventData); if (deviceTwinName != null) { DevicePropertyServiceModel devicePropertyModel = new DevicePropertyServiceModel { Tags = deviceTwinName.Tags, Reported = deviceTwinName.ReportedProperties, }; ValueServiceModel valueSvcModel = new ValueServiceModel(new KeyValueDocument(CollectionId, Key, JsonConvert.SerializeObject(devicePropertyModel))); if (devicePropertyModel != null && existingDevProperties == null) { // Create the document if (deviceCacheValue == null) { await docClient.SaveDocumentAsync(CollectionId, Key, valueSvcModel, this.GenerateCollectionLink(this.cosmosDb, this.cosmosDbcoll)); updateStatus = true; } } else { // update only if the Tags or the reported properties are different from ones stored in cosmos if (existingDevProperties != null && (!existingDevProperties.Tags.SetEquals(devicePropertyModel.Tags) || !existingDevProperties.Reported.SetEquals(devicePropertyModel.Reported))) { await docClient.SaveDocumentAsync(CollectionId, Key, valueSvcModel, this.GenerateCollectionLink(this.cosmosDb, this.cosmosDbcoll)); updateStatus = true; } } } else { updateStatus = true; } } catch (Exception exception) { throw new ApplicationException($"Update Device Properties failed {exception}, tenant: {tenant}"); } return(updateStatus); }