public async Task <TableStorageResponse <DeviceRule> > DeleteDeviceRuleAsync(DeviceRule ruleToDelete)
        {
            DeviceRuleTableEntity incomingEntity = BuildTableEntityFromRule(ruleToDelete);

            TableStorageResponse <DeviceRule> result =
                await _azureTableStorageClient.DoDeleteAsync <DeviceRule, DeviceRuleTableEntity>(incomingEntity, BuildRuleFromTableEntity);

            if (result.Status == TableStorageResponseStatus.Successful)
            {
                // Build up a new blob to push up for ASA job ref data
                List <DeviceRuleBlobEntity> blobList = await BuildBlobEntityListFromTableRows();
                await PersistRulesToBlobStorageAsync(blobList);
            }

            return(result);
        }
        /// <summary>
        /// Updated the enabled state of a given rule. This method does not update any other properties on the rule
        /// </summary>
        /// <param name="deviceId"></param>
        /// <param name="ruleId"></param>
        /// <param name="enabled"></param>
        /// <returns></returns>
        public async Task <TableStorageResponse <LocationRule> > UpdateLocationRuleEnabledStateAsync(string regionId, string ruleId, bool enabled)
        {
            LocationRule found = await _locationRulesRepository.GetLocationRuleAsync(regionId, ruleId);

            if (found == null)
            {
                var response = new TableStorageResponse <LocationRule>();
                response.Entity = found;
                response.Status = TableStorageResponseStatus.NotFound;

                return(response);
            }

            found.EnabledState = enabled;

            return(await _locationRulesRepository.SaveLocationRuleAsync(found));
        }
        /// <summary>
        /// Updated the enabled state of a given rule. This method does not update any other properties on the rule
        /// </summary>
        /// <param name="deviceId"></param>
        /// <param name="ruleId"></param>
        /// <param name="enabled"></param>
        /// <returns></returns>
        public async Task <TableStorageResponse <DeviceRule> > UpdateDeviceRuleEnabledStateAsync(string deviceId, string ruleId, bool enabled)
        {
            DeviceRule found = await _deviceRulesRepository.GetDeviceRuleAsync(deviceId, ruleId);

            if (found == null)
            {
                var response = new TableStorageResponse <DeviceRule>();
                response.Entity = found;
                response.Status = TableStorageResponseStatus.NotFound;

                return(response);
            }

            found.EnabledState = enabled;

            return(await _deviceRulesRepository.SaveDeviceRuleAsync(found));
        }
        public async Task <TableStorageResponse <DeviceRule> > DeleteDeviceRuleAsync(DeviceRule ruleToDelete)
        {
            DeviceRuleTableEntity incomingEntity = BuildTableEntityFromRule(ruleToDelete);

            TableStorageResponse <DeviceRule> result =
                await AzureTableStorageHelper.DoDeleteAsync <DeviceRule, DeviceRuleTableEntity>(incomingEntity, BuildRuleFromTableEntity,
                                                                                                _storageAccountConnectionString, _deviceRulesNormalizedTableName);

            if (result.Status == TableStorageResponseStatus.Successful)
            {
                // Build up a new blob to push up for ASA job ref data
                List <DeviceRuleBlobEntity> blobList = await BuildBlobEntityListFromTableRows();
                await PersistRulesToBlobStorageAsync(blobList);
            }

            return(result);
        }
Example #5
0
        /// <summary>
        /// Save a rule to the data store. This method should be used for new rules as well as updating existing rules
        /// </summary>
        /// <param name="updatedRule"></param>
        /// <returns></returns>
        public async Task <TableStorageResponse <DeviceRule> > SaveDeviceRuleAsync(DeviceRule updatedRule)
        {
            //Enforce single instance of a rule for a data field for a given device
            List <DeviceRule> foundForDevice = await _deviceRulesRepository.GetAllRulesForDeviceAsync(updatedRule.DeviceID);

            foreach (DeviceRule rule in foundForDevice)
            {
                if (rule.DataField == updatedRule.DataField && rule.RuleId != updatedRule.RuleId)
                {
                    var response = new TableStorageResponse <DeviceRule>();
                    response.Entity = rule;
                    response.Status = TableStorageResponseStatus.DuplicateInsert;
                    return(response);
                }
            }

            return(await _deviceRulesRepository.SaveDeviceRuleAsync(updatedRule));
        }
        /// <summary>
        /// Save a rule to the data store. This method should be used for new rules as well as updating existing rules
        /// </summary>
        /// <param name="updatedRule"></param>
        /// <returns></returns>
        public async Task<TableStorageResponse<DeviceRule>> SaveDeviceRuleAsync(DeviceRule updatedRule)
        {
            //Enforce single instance of a rule for a data field for a given device
            List<DeviceRule> foundForDevice = await _deviceRulesRepository.GetAllRulesForDeviceAsync(updatedRule.DeviceID);
            foreach(DeviceRule rule in foundForDevice)
            {
                if(rule.DataField == updatedRule.DataField && rule.RuleId != updatedRule.RuleId)
                {
                    var response = new TableStorageResponse<DeviceRule>();
                    response.Entity = rule;
                    response.Status = TableStorageResponseStatus.DuplicateInsert;

                    return response;
                }
            }

            return await _deviceRulesRepository.SaveDeviceRuleAsync(updatedRule);
        }
        private static async Task <TableStorageResponse <TResult> > PerformTableOperation <TResult, TInput>(CloudTable table,
                                                                                                            TableOperation operation, TInput incomingEntity, Func <TInput, TResult> tableEntityToModelConverter) where TInput : TableEntity
        {
            var result = new TableStorageResponse <TResult>();

            try
            {
                await table.ExecuteAsync(operation);

                var nullModel = tableEntityToModelConverter((TInput)null);
                result.Entity = nullModel;
                result.Status = TableStorageResponseStatus.Successful;
            }
            catch (Exception ex)
            {
                TableOperation retrieveOperation = TableOperation.Retrieve <TInput>(incomingEntity.PartitionKey, incomingEntity.RowKey);
                TableResult    retrievedEntity   = table.Execute(retrieveOperation);

                if (retrievedEntity != null)
                {
                    // Return the found version of this rule in case it had been modified by someone else since our last read.
                    var retrievedModel = tableEntityToModelConverter((TInput)retrievedEntity.Result);
                    result.Entity = retrievedModel;
                }
                else
                {
                    // We didn't find an existing rule, probably creating new, so we'll just return what was sent in
                    result.Entity = tableEntityToModelConverter(incomingEntity);
                }

                if (ex.GetType() == typeof(StorageException) &&
                    (((StorageException)ex).RequestInformation.HttpStatusCode == (int)HttpStatusCode.PreconditionFailed ||
                     ((StorageException)ex).RequestInformation.HttpStatusCode == (int)HttpStatusCode.Conflict))
                {
                    result.Status = TableStorageResponseStatus.ConflictError;
                }
                else
                {
                    result.Status = TableStorageResponseStatus.UnknownError;
                }
            }

            return(result);
        }
        public async Task <bool> RemoveAllRulesForDeviceAsync(string deviceId)
        {
            bool result = true;

            List <DeviceRule> deviceRules = await _deviceRulesRepository.GetAllRulesForDeviceAsync(deviceId);

            foreach (DeviceRule rule in deviceRules)
            {
                TableStorageResponse <DeviceRule> response = await _deviceRulesRepository.DeleteDeviceRuleAsync(rule);

                if (response.Status != TableStorageResponseStatus.Successful)
                {
                    //Do nothing, just report that it failed. The client can then take other steps if needed/desired
                    result = false;
                }
            }

            return(result);
        }
Example #9
0
        private async Task <UserSetting> SetUserSettingImplAsync(string userId, UserSetting setting)
        {
            var incomingEntity = new UserSettingTableEntity(userId, setting);

            if (!string.IsNullOrWhiteSpace(setting.Etag))
            {
                incomingEntity.ETag = setting.Etag;
            }

            TableStorageResponse <UserSetting> result = await _azureTableStorageClient.DoTableInsertOrReplaceAsync <UserSetting, UserSettingTableEntity>(incomingEntity, (tableEntity) =>
            {
                if (tableEntity == null)
                {
                    return(null);
                }

                return(new UserSetting(tableEntity));
            });

            return(result.Entity);
        }
Example #10
0
        private JsonResult BuildRuleUpdateResponse(TableStorageResponse <DeviceRule> response)
        {
            switch (response.Status)
            {
            case TableStorageResponseStatus.Successful:
                return(Json(new { success = true }));

            case TableStorageResponseStatus.ConflictError:
                return(Json(new { error = Strings.TableDataSaveConflictErrorMessage }));

            case TableStorageResponseStatus.DuplicateInsert:
                return(Json(new { error = Strings.RuleAlreadyAddedError }));

            case TableStorageResponseStatus.NotFound:
                return(Json(new { error = Strings.UnableToRetrieveRuleFromService }));

            case TableStorageResponseStatus.UnknownError:
            default:
                return(Json(new { error = Strings.RuleUpdateError }));
            }
        }
        public async Task DeleteNameAsyncTest()
        {
            var newNameCache = fixture.Create <NameCacheEntity>();
            NameCacheTableEntity tableEntity = null;
            var resp = new TableStorageResponse <NameCacheEntity>
            {
                Entity = newNameCache,
                Status = TableStorageResponseStatus.Successful
            };

            _tableStorageClientMock.Setup(
                x =>
                x.DoDeleteAsync(It.IsNotNull <NameCacheTableEntity>(),
                                It.IsNotNull <Func <NameCacheTableEntity, NameCacheEntity> >()))
            .Callback <NameCacheTableEntity, Func <NameCacheTableEntity, NameCacheEntity> >(
                (entity, func) => tableEntity = entity)
            .ReturnsAsync(resp);
            var ret = await nameCacheRepository.DeleteNameAsync(NameCacheEntityType.DesiredProperty, newNameCache.Name);

            Assert.True(ret);
            Assert.NotNull(tableEntity);
            Assert.Equal(newNameCache.Name, tableEntity.Name);
        }
        public async Task DeleteNameAsyncFailureTest()
        {
            var newNameCache = fixture.Create <NameCacheEntity>();
            NameCacheTableEntity tableEntity = null;
            var resp = new TableStorageResponse <NameCacheEntity>
            {
                Entity = newNameCache,
                Status = TableStorageResponseStatus.NotFound
            };

            _tableStorageClientMock.Setup(
                x =>
                x.DoDeleteAsync(It.IsNotNull <NameCacheTableEntity>(),
                                It.IsNotNull <Func <NameCacheTableEntity, NameCacheEntity> >()))
            .Callback <NameCacheTableEntity, Func <NameCacheTableEntity, NameCacheEntity> >(
                (entity, func) => tableEntity = null)
            .ReturnsAsync(resp);
            var ret = await nameCacheRepository.DeleteNameAsync(NameCacheEntityType.DesiredProperty, newNameCache.Name);

            Assert.False(ret);
            Assert.Null(tableEntity);
            await Assert.ThrowsAsync <ArgumentException>(async() =>
                                                         await nameCacheRepository.DeleteNameAsync(NameCacheEntityType.All, newNameCache.Name));
        }
Example #13
0
        /// <summary>
        /// Save a rule to the data store. This method should be used for new rules as well as updating existing rules
        /// </summary>
        /// <param name="newRule"></param>
        /// <returns></returns>
        public async Task <TableStorageResponse <LocationRule> > SaveLocationRuleAsync(LocationRule newRule)
        {
            if (newRule.RegionId == "default")
            {
                return(await _locationRulesRepository.SaveLocationRuleAsync(newRule));
            }

            string regionId = $"{Math.Truncate(newRule.RegionLatitude * 10)/10}_{Math.Truncate(newRule.RegionLongitude *10)/10}";

            if (newRule.RegionId != regionId || string.IsNullOrWhiteSpace(newRule.RuleId))
            {
                var response = new TableStorageResponse <LocationRule>();
                response.Entity = newRule;
                response.Status = TableStorageResponseStatus.IncorrectEntry;

                return(response);
            }

            //Enforce single instance of a rule for a data field for a given device
            List <LocationRule> foundForRegion = await _locationRulesRepository.GetAllRulesForRegionAsync(newRule.RegionId);

            foreach (LocationRule rule in foundForRegion)
            {
                if ((rule.RuleId != newRule.RuleId) &&
                    (rule.RegionLatitude == newRule.RegionLatitude) && (rule.RegionLongitude == newRule.RegionLongitude))
                {
                    var response = new TableStorageResponse <LocationRule>();
                    response.Entity = rule;
                    response.Status = TableStorageResponseStatus.DuplicateInsert;

                    return(response);
                }
            }

            return(await _locationRulesRepository.SaveLocationRuleAsync(newRule));
        }
Example #14
0
        public async Task <ActionResult> DeleteLocationRule(string regionId, string ruleId)
        {
            TableStorageResponse <LocationRule> response = await _locationRulesLogic.DeleteLocationRuleAsync(regionId, ruleId);

            return(BuildRuleUpdateResponse(response));
        }
Example #15
0
        public async Task <ActionResult> DeleteDeviceRule(string deviceId, string ruleId)
        {
            TableStorageResponse <DeviceRule> response = await _deviceRulesLogic.DeleteDeviceRuleAsync(deviceId, ruleId);

            return(BuildRuleUpdateResponse(response));
        }
        /// <summary>
        /// Updated the enabled state of a given rule. This method does not update any other properties on the rule
        /// </summary>
        /// <param name="deviceId"></param>
        /// <param name="ruleId"></param>
        /// <param name="enabled"></param>
        /// <returns></returns>
        public async Task<TableStorageResponse<DeviceRule>> UpdateDeviceRuleEnabledStateAsync(string deviceId, string ruleId, bool enabled)
        {
            DeviceRule found = await _deviceRulesRepository.GetDeviceRuleAsync(deviceId, ruleId);
            if(found == null)
            {
                var response = new TableStorageResponse<DeviceRule>();
                response.Entity = found;
                response.Status = TableStorageResponseStatus.NotFound;

                return response;
            }

            found.EnabledState = enabled;

            return await _deviceRulesRepository.SaveDeviceRuleAsync(found);
        }
Example #17
0
        public static async Task <TableStorageResponse <TResult> > DoTableInsertOrReplace <TResult, TInput>(TInput incomingEntity,
                                                                                                            Func <TInput, TResult> tableEntityToModelConverter, string storageAccountConnectionString, string tableName) where TInput : TableEntity
        {
            var result = new TableStorageResponse <TResult>();

            var deviceRulesTable = await AzureTableStorageHelper.GetTableAsync(storageAccountConnectionString, tableName);

            // Simply doing an InsertOrReplace will not do any concurrency checking, according to
            // http://azure.microsoft.com/en-us/blog/managing-concurrency-in-microsoft-azure-storage-2/
            // So we will not use InsertOrReplace. Instead we will look to see if we have a rule like this
            // If so, then we'll do a concurrency-safe update, otherwise simply insert
            TableOperation retrieveOperation =
                TableOperation.Retrieve <TInput>(incomingEntity.PartitionKey, incomingEntity.RowKey);
            TableResult retrievedEntity = await deviceRulesTable.ExecuteAsync(retrieveOperation);

            try
            {
                TableOperation operation = null;
                if (retrievedEntity.Result != null)
                {
                    operation = TableOperation.Replace(incomingEntity);
                }
                else
                {
                    operation = TableOperation.Insert(incomingEntity);
                }
                await deviceRulesTable.ExecuteAsync(operation);

                //Get the new version of the entity out of the database
                // And set up the result to return to the caller
                retrievedEntity = await deviceRulesTable.ExecuteAsync(retrieveOperation);

                var updatedModel = tableEntityToModelConverter((TInput)retrievedEntity.Result);
                result.Entity = updatedModel;
                result.Status = TableStorageResponseStatus.Successful;
            }
            catch (Exception ex)
            {
                if (retrievedEntity != null)
                {
                    // Return the found version of this rule in case it had been modified by someone else since our last read.
                    var retrievedModel = tableEntityToModelConverter((TInput)retrievedEntity.Result);
                    result.Entity = retrievedModel;
                }
                else
                {
                    // We didn't find an existing rule, probably creating new, so we'll just return what was sent in
                    result.Entity = tableEntityToModelConverter(incomingEntity);
                }

                if (ex.GetType() == typeof(StorageException) &&
                    (((StorageException)ex).RequestInformation.HttpStatusCode == (int)HttpStatusCode.PreconditionFailed ||
                     ((StorageException)ex).RequestInformation.HttpStatusCode == (int)HttpStatusCode.Conflict))
                {
                    result.Status = TableStorageResponseStatus.ConflictError;
                }
                else
                {
                    result.Status = TableStorageResponseStatus.UnknownError;
                }
            }

            return(result);
        }
 private JsonResult BuildRuleUpdateResponse(TableStorageResponse<DeviceRule> response)
 {
     switch (response.Status)
     {
         case TableStorageResponseStatus.Successful:
             return Json(new 
             { 
                 success = true
             });
         case TableStorageResponseStatus.ConflictError:
             return Json(new
             {
                 error = Strings.TableDataSaveConflictErrorMessage,
                 entity = JsonConvert.SerializeObject(response.Entity)
             });
         case TableStorageResponseStatus.DuplicateInsert:
             return Json(new
             {
                 error = Strings.RuleAlreadyAddedError,
                 entity = JsonConvert.SerializeObject(response.Entity)
             });
         case TableStorageResponseStatus.NotFound:
             return Json(new
             {
                 error = Strings.UnableToRetrieveRuleFromService,
                 entity = JsonConvert.SerializeObject(response.Entity)
             });
         case TableStorageResponseStatus.UnknownError:
         default:
             return Json(new
             {
                 error = Strings.RuleUpdateError,
                 entity = JsonConvert.SerializeObject(response.Entity)
             });
     }
 }
 public async void SaveDeviceRuleAsyncTest()
 {
     var newRule = fixture.Create<DeviceRule>();
     DeviceRuleTableEntity tableEntity = null;
     var resp = new TableStorageResponse<DeviceRule>
     {
         Entity = newRule,
         Status = TableStorageResponseStatus.Successful
     };
     _tableStorageClientMock.Setup(
         x =>
             x.DoTableInsertOrReplaceAsync(It.IsNotNull<DeviceRuleTableEntity>(),
                 It.IsNotNull<Func<DeviceRuleTableEntity, DeviceRule>>()))
         .Callback<DeviceRuleTableEntity, Func<DeviceRuleTableEntity, DeviceRule>>(
             (entity, func) => tableEntity = entity)
         .ReturnsAsync(resp);
     var tableEntities = fixture.Create<List<DeviceRuleTableEntity>>();
     _tableStorageClientMock.Setup(x => x.ExecuteQueryAsync(It.IsNotNull<TableQuery<DeviceRuleTableEntity>>()))
         .ReturnsAsync(tableEntities);
     string blobEntititesStr = null;
     _blobClientMock.Setup(x => x.UploadTextAsync(It.IsNotNull<string>(), It.IsNotNull<string>()))
         .Callback<string, string>((name, blob) => blobEntititesStr = blob)
         .Returns(Task.FromResult(true));
     var ret = await deviceRulesRepository.SaveDeviceRuleAsync(newRule);
     Assert.NotNull(ret);
     Assert.Equal(resp, ret);
     Assert.NotNull(tableEntity);
     Assert.Equal(newRule.DeviceID, tableEntity.DeviceId);
     Assert.NotNull(blobEntititesStr);
 }
Example #20
0
        public async void SaveFilterAsyncTest()
        {
            var newFilter = fixture.Create <DeviceListFilter>();
            var oldEntity = fixture.Create <DeviceListFilterTableEntity>();
            DeviceListFilterTableEntity tableEntity = null;
            var tableEntities = new List <DeviceListFilterTableEntity>();

            var resp = new TableStorageResponse <DeviceListFilter>
            {
                Entity = newFilter,
                Status = TableStorageResponseStatus.Successful
            };

            _filterTableStorageClientMock.Setup(x => x.ExecuteQueryAsync(It.IsNotNull <TableQuery <DeviceListFilterTableEntity> >()))
            .ReturnsAsync(tableEntities);
            _filterTableStorageClientMock.Setup(
                x =>
                x.DoTableInsertOrReplaceAsync(It.IsNotNull <DeviceListFilterTableEntity>(),
                                              It.IsNotNull <Func <DeviceListFilterTableEntity, DeviceListFilter> >()))
            .Callback <DeviceListFilterTableEntity, Func <DeviceListFilterTableEntity, DeviceListFilter> >(
                (entity, func) =>
            {
                tableEntity = entity;
                tableEntities.Add(tableEntity);
            })
            .ReturnsAsync(resp);
            var ret = await deviceListFilterRepository.SaveFilterAsync(newFilter, true);

            Assert.NotNull(ret);
            Assert.NotNull(tableEntity);

            _filterTableStorageClientMock.Setup(x => x.ExecuteQueryAsync(It.IsNotNull <TableQuery <DeviceListFilterTableEntity> >()))
            .ReturnsAsync(tableEntities);
            ret = await deviceListFilterRepository.SaveFilterAsync(newFilter, false);

            Assert.Equal(ret.Id, newFilter.Id);
            Assert.Equal(ret.Name, newFilter.Name);
            Assert.Equal(ret.Clauses.Count, newFilter.Clauses.Count);

            tableEntity.Name = "changedName";
            _filterTableStorageClientMock.SetupSequence(x => x.ExecuteQueryAsync(It.IsNotNull <TableQuery <DeviceListFilterTableEntity> >()))
            .ReturnsAsync(tableEntities)
            .ReturnsAsync(new List <DeviceListFilterTableEntity>());
            _filterTableStorageClientMock.Setup(x => x.DoDeleteAsync(It.IsNotNull <DeviceListFilterTableEntity>(), It.IsAny <Func <DeviceListFilterTableEntity, DeviceListFilter> >()));
            ret = await deviceListFilterRepository.SaveFilterAsync(newFilter, true);

            resp = new TableStorageResponse <DeviceListFilter>
            {
                Entity = newFilter,
                Status = TableStorageResponseStatus.NotFound
            };
            _filterTableStorageClientMock.Setup(
                x =>
                x.DoTableInsertOrReplaceAsync(It.IsNotNull <DeviceListFilterTableEntity>(),
                                              It.IsNotNull <Func <DeviceListFilterTableEntity, DeviceListFilter> >()))
            .ReturnsAsync(resp);
            _filterTableStorageClientMock.SetupSequence(x => x.ExecuteQueryAsync(It.IsNotNull <TableQuery <DeviceListFilterTableEntity> >()))
            .ReturnsAsync(tableEntities)
            .ReturnsAsync(new List <DeviceListFilterTableEntity>());
            await Assert.ThrowsAnyAsync <FilterSaveException>(async() => await deviceListFilterRepository.SaveFilterAsync(newFilter, true));
        }