Пример #1
0
        public async Task <QueryResult <InAppMessageQueryDto> > GetByUserId(Guid userId
                                                                            , ODataQueryOptions <InAppMessageQueryDto> options)
        {
            options.Validate(ValidationSettings);

            var uid = GetCurrentUser();

            if (!uid.HasValue)
            {
                return(Query.Error(GeneralErrorCodes.TokenInvalid("UserId")));
            }


            var tenants     = _context.GetTenantsForUser(uid.Value);
            var shareTenant = tenants.Any(t => t.Users.Any(u => u.Id == userId));

            // Check if the calling User shares a Tenant with the UserId passed in
            if (!shareTenant)
            {
                return(Query.Error(EntityErrorCode.EntityNotFound));
            }

            var results =
                await Task.Run(() =>
                               _context.GetInAppMessagesForUser(userId)
                               .Select(_mapper.Map <InAppMessage, InAppMessageQueryDto>)
                               .AsQueryable())
                .ConfigureAwait(false);

            return(Query.Result(results));
        }
Пример #2
0
        /// <summary>
        /// Deletes a dashboard option.
        /// </summary>
        /// <param name="id">ID that identifies the entity to be deleted.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// </returns>
        public override async Task <CommandResult <DashboardOptionQueryDto, Guid> > Delete(Guid id)
        {
            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(Command.Error <DashboardOptionQueryDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var userDashboardOptions = _context.GetDashboardOptionsForUser(Guid.Parse(userId));
            var entity = userDashboardOptions.SingleOrDefault(x => x.Id == id);

            if (entity == null)
            {
                return(Command.Error <DashboardOptionQueryDto>(EntityErrorCode.EntityNotFound));
            }

            if (_context.Dashboards.Any(x => x.DashboardOptionId == id))
            {
                return(Command.Error <DashboardOptionQueryDto>(EntityErrorCode.EntityCouldNotBeDeleted));
            }

            _context.DashboardOptions.Remove(entity);
            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.NoContent <DashboardOptionQueryDto>());
        }
Пример #3
0
        /// <summary>
        /// Creates a dashboard.
        /// </summary>
        /// <param name="dto">Data Transfer Object (DTO) used to create an entity.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result contains the DTO associated with the entity created.
        /// </returns>
        public override async Task <CommandResult <DashboardQueryDto, Guid> > Create(DashboardBaseDto dto)
        {
            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(Command.Error <DashboardQueryDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var userIdGuid = Guid.Parse(userId);

            var validationResponse = ValidatorCreate.Validate(dto);

            if (dto == null)
            {
                return(Command.Error <DashboardQueryDto>(validationResponse));
            }

            if (dto.Id != Guid.Empty)
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.PropertyIsInvalid("Id"));
            }

            var userTenants = _context.GetTenantsForUser(userIdGuid);

            if (dto.TenantId != Guid.Empty && !userTenants.Any(x => x.Id == dto.TenantId))
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist("TenantId"));
            }

            if (_context.Dashboards.Any(x => x.OwnerUserId == userIdGuid && x.Name == dto.Name))
            {
                validationResponse.FFErrors.Add(EntityErrorCode.EntityAlreadyExists);
            }

            var userDashboardOptions = _context.GetDashboardOptionsForUser(userIdGuid);

            if (dto.DashboardOptionId != Guid.Empty && !userDashboardOptions.Any(x => x.Id == dto.DashboardOptionId))
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist("DashboardOptionId"));
            }

            if (validationResponse.IsInvalid)
            {
                return(Command.Error <DashboardQueryDto>(validationResponse));
            }

            var newEntity = new Dashboard();

            _mapper.Map(dto, newEntity);

            newEntity.Id = Guid.NewGuid();
            newEntity.SetAuditFieldsOnCreate(userId);
            newEntity.OwnerUserId = userIdGuid;

            _context.Dashboards.Add(newEntity);
            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.Created(_mapper.Map(newEntity, new DashboardQueryDto()), newEntity.Id));
        }
Пример #4
0
        /// <summary>
        /// Gets a list of dashboard options from the data store.
        /// </summary>
        /// <param name="queryOptions">OData query options.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result contains the list of DTOs retrieved.
        /// </returns>
        public override async Task <QueryResult <DashboardOptionQueryDto> > Get(ODataQueryOptions <DashboardOptionQueryDto> queryOptions)
        {
            queryOptions.Validate(ValidationSettings);

            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(Query.Error(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            try
            {
                var result = await Task.Run(() =>
                                            _context.GetDashboardOptionsForUser(Guid.Parse(userId))
                                            .Select(_mapper.Map <DashboardOption, DashboardOptionQueryDto>)
                                            .AsQueryable())
                             .ConfigureAwait(false);

                return(Query.Result(result));
            }
            catch (Exception ex)
            {
                throw;
            }
        }
Пример #5
0
        /// <summary>
        /// Deletes a location.
        /// </summary>
        /// <param name="id">ID that identifies the location to be deleted.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// </returns>
        public override async Task <CommandResult <LocationQueryDto, Guid> > Delete(Guid id)
        {
            // Thread.CurrentPrincipal is not available in the constructor.  Do not try and move this
            var uid = GetCurrentUser();

            if (!uid.HasValue)
            {
                return(Command.Error <LocationQueryDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var location = await _context.GetLocationsForUser(uid.Value)
                           .Include(l => l.Locations)
                           .SingleOrDefaultAsync(l => l.Id == id)
                           .ConfigureAwait(false);

            if (location == null)
            {
                return(Command.Error <LocationQueryDto>(EntityErrorCode.EntityNotFound));
            }

            if (location.Locations.Count > 0)
            {
                return(Command.Error <LocationQueryDto>(EntityErrorCode.EntityCouldNotBeDeleted));
            }

            _context.Locations.Remove(location);
            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.NoContent <LocationQueryDto>());
        }
Пример #6
0
        public static string GetSyncErrorMessage(string status)
        {
            if (string.IsNullOrEmpty(status))
            {
                return(string.Empty);
            }

            int code = -1;

            if (int.TryParse(status, out code))
            {
                if (GeneralErrorCodes.ContainsKey(code))
                {
                    return(GeneralErrorCodes[code]);
                }
                else if (SyncErrorCodes.ContainsKey(code))
                {
                    return(SyncErrorCodes[code]);
                }
                else
                {
                    return("UnknownError");
                }
            }

            return(status);
        }
Пример #7
0
        /// <summary>
        /// Gets a single location from the data store.
        /// </summary>
        /// <param name="id">ID that uniquely identifies the location to be retrieved.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result includes the location DTO retrieved.
        /// </returns>
        public override async Task <QueryResult <LocationQueryDto> > Get(Guid id)
        {
            var uid = GetCurrentUser();

            if (!uid.HasValue)
            {
                return(Query.Error(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var result = await Task.Run(() => _context.GetLocationsForUser(uid.Value)
                                        .Include(x => x.LocationType)
                                        .Include(x => x.Parent)
                                        .Include(x => x.Locations.Select(y => y.Locations))
                                        .Include(x => x.ProductOfferingTenantLocations)
                                        .FirstOrDefault(l => l.Id == id))
                         .ConfigureAwait(false);

            if (result == null)
            {
                return(Query.Error(EntityErrorCode.EntityNotFound));
            }

            var locationDto = _mapper.Map <Location, LocationQueryDto>(result);

            return(Query.Result(locationDto));
        }
Пример #8
0
        /// <summary>
        /// Updates a dashboard option using a <see cref="Delta"/> object.
        /// </summary>
        /// <param name="id">ID of the entity to be updated.</param>
        /// <param name="delta">
        /// Delta containing a list of entity properties.  Web Api does the magic of converting the JSON to
        /// a delta.
        /// </param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// </returns>
        public override async Task <CommandResult <DashboardOptionBaseDto, Guid> > Update(Guid id, Delta <DashboardOptionBaseDto> delta)
        {
            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(Command.Error <DashboardOptionBaseDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            if (delta == null)
            {
                return(Command.Error <DashboardOptionBaseDto>(EntityErrorCode.EntityFormatIsInvalid));
            }

            var userDashboardOptions = _context.GetDashboardOptionsForUser(Guid.Parse(userId));
            var entity = userDashboardOptions.SingleOrDefault(x => x.Id == id);

            if (entity == null)
            {
                return(Command.Error <DashboardOptionBaseDto>(EntityErrorCode.EntityNotFound));
            }

            var dto = _mapper.Map(entity, new DashboardOptionBaseDto());

            delta.Patch(dto);

            var validationResponse = ValidatorUpdate.Validate(dto);

            var userTenants = _context.GetTenantsForUser(Guid.Parse(userId));

            if (dto.TenantId != Guid.Empty && !userTenants.Any(x => x.Id == dto.TenantId))
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist("TenantId"));
            }
            else if (_context.DashboardOptions.Any(x => x.Id != id && x.TenantId == dto.TenantId))
            {
                validationResponse.FFErrors.Add(EntityErrorCode.EntityAlreadyExists);
            }

            // Including the original Id in the Patch request will not return an error but attempting to change the Id is not allowed.
            if (dto.Id != id)
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.EntityIDUpdateNotAllowed("Id"));
            }

            if (validationResponse.IsInvalid)
            {
                return(Command.Error <DashboardOptionBaseDto>(validationResponse));
            }

            _context.DashboardOptions.Attach(entity);
            _mapper.Map(dto, entity);
            entity.SetAuditFieldsOnUpdate(userId);

            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.NoContent <DashboardOptionBaseDto>());
        }
Пример #9
0
        /// <summary>
        /// Updates a Location Log Entry using a <see cref="Delta"/> object.
        /// </summary>
        /// <param name="id">ID of the Location Log Entry to be updated.</param>
        /// <param name="delta">
        /// Delta containing a list of Location Log Entry properties.  Web Api does the magic of converting the JSON to
        /// a delta.
        /// </param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// </returns>
        public override async Task <CommandResult <LocationLogEntryBaseDto, Guid> > Update(Guid id, Delta <LocationLogEntryBaseDto> delta)
        {
            // User ID should always be available, but if not ...
            var userId = GetCurrentUser();

            if (!userId.HasValue)
            {
                return(Command.Error <LocationLogEntryBaseDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            if (delta == null)
            {
                return(Command.Error <LocationLogEntryBaseDto>(EntityErrorCode.EntityFormatIsInvalid));
            }

            var locationLogEntry = await _context.GetLocationLogEntriesForUser(userId.Value)
                                   .SingleOrDefaultAsync(l => l.Id == id)
                                   .ConfigureAwait(false);

            if (locationLogEntry == null)
            {
                return(Command.Error <LocationLogEntryBaseDto>(EntityErrorCode.EntityNotFound));
            }

            var dto = _mapper.Map(locationLogEntry, new LocationLogEntryQueryDto());

            delta.Patch(dto);

            var validationResponse = ValidatorUpdate.Validate(dto);

            // Including the original ID in the Patch request will not return an error but attempting to change the Id is not allowed.
            if (dto.Id != id)
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.EntityIDUpdateNotAllowed("Id"));
            }

            var locationExists = await DoesLocationExist(dto.LocationId);

            if (!locationExists)
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist(nameof(LocationLogEntry.LocationId)));
            }

            if (validationResponse.IsInvalid)
            {
                return(Command.Error <LocationLogEntryBaseDto>(validationResponse));
            }

            _context.LocationLogEntries.Attach(locationLogEntry);
            _mapper.Map(dto, locationLogEntry);

            locationLogEntry.SetAuditFieldsOnUpdate(userId.Value);

            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.NoContent <LocationLogEntryBaseDto>());
        }
Пример #10
0
        /// <summary>
        /// Updates a limit type using a <see cref="Delta"/> object.
        /// </summary>
        /// <param name="id">ID of the entity to be updated.</param>
        /// <param name="delta">
        /// Delta containing a list of entity properties.  Web Api does the magic of converting the JSON to
        /// a delta.
        /// </param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// </returns>
        public override async Task <CommandResult <LimitTypeBaseDto, Guid> > Update(Guid id, Delta <LimitTypeBaseDto> delta)
        {
            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(Command.Error <LimitTypeBaseDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            if (delta == null)
            {
                return(Command.Error <LimitTypeBaseDto>(EntityErrorCode.EntityFormatIsInvalid));
            }

            var entity = await _context.LimitTypes
                         .SingleOrDefaultAsync(x => x.Id == id)
                         .ConfigureAwait(false);

            if (entity == null)
            {
                return(Command.Error <LimitTypeBaseDto>(EntityErrorCode.EntityNotFound));
            }

            var dto = _mapper.Map(entity, new LimitTypeBaseDto());

            delta.Patch(dto);

            var validationResponse = ValidatorUpdate.Validate(dto);

            if (_context.LimitTypes.Any(x => x.Id != id && x.I18NKeyName == dto.I18NKeyName))
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.EntityPropertyDuplicateNotAllowed(nameof(LocationType.I18NKeyName)));
            }

            // Including the original Id in the Patch request will not return an error but attempting to change the Id is not allowed.
            if (dto.Id != id)
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.EntityIDUpdateNotAllowed("Id"));
            }

            if (validationResponse.IsInvalid)
            {
                return(Command.Error <LimitTypeBaseDto>(validationResponse));
            }

            _context.LimitTypes.Attach(entity);
            _mapper.Map(dto, entity);
            entity.SetAuditFieldsOnUpdate(userId);

            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.NoContent <LimitTypeBaseDto>());
        }
Пример #11
0
        /// <summary>
        /// Creates a Location Log Entry.
        /// </summary>
        /// <param name="dto">Data Transfer Object (DTO) used to create a Location Log Entry.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result contains the DTO associated with the Location Log Entry.
        /// </returns>
        public override async Task <CommandResult <LocationLogEntryQueryDto, Guid> > Create(LocationLogEntryBaseDto dto)
        {
            // User ID should always be available, but if not ...
            var userId = GetCurrentUser();

            if (!userId.HasValue)
            {
                return(Command.Error <LocationLogEntryQueryDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var validationResponse = ValidatorCreate.Validate(dto);

            if (dto == null)
            {
                return(Command.Error <LocationLogEntryQueryDto>(validationResponse));
            }

            if (dto.Id != Guid.Empty)
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.PropertyIsInvalid(nameof(LocationLogEntry.Id)));
            }

            var locationExists = await DoesLocationExist(dto.LocationId);

            if (!locationExists)
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist(nameof(LocationLogEntry.LocationId)));
            }

            if (validationResponse.IsInvalid)
            {
                return(Command.Error <LocationLogEntryQueryDto>(validationResponse));
            }

            var locationLogEntry = new LocationLogEntry
            {
                Id = Guid.NewGuid()
            };

            _mapper.Map(dto, locationLogEntry);

            locationLogEntry.SetAuditFieldsOnCreate(userId.Value);

            _context.LocationLogEntries.Add(locationLogEntry);
            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.Created(_mapper.Map(locationLogEntry, new LocationLogEntryQueryDto()), locationLogEntry.Id));
        }
Пример #12
0
        /// <summary>
        /// Gets a single chemical form types from the data store.
        /// </summary>
        /// <param name="id">ID that uniquely identifies the entity to be retrieved.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result includes the DTO retrieved.
        /// </returns>
        public override async Task <QueryResult <ChemicalFormTypeQueryDto> > Get(Guid id)
        {
            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(Query.Error(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var result = await _context.ChemicalFormTypes
                         .FirstOrDefaultAsync(x => x.Id == id)
                         .ConfigureAwait(false);

            return(result == null
                ? Query.Error(EntityErrorCode.EntityNotFound)
                : Query.Result(_mapper.Map <ChemicalFormType, ChemicalFormTypeQueryDto>(result)));
        }
Пример #13
0
        /// <summary>
        /// Gets a list of limit types from the data store.
        /// </summary>
        /// <param name="queryOptions">OData query options.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result contains the list of DTOs retrieved.
        /// </returns>
        public override async Task <QueryResult <LimitTypeQueryDto> > Get(ODataQueryOptions <LimitTypeQueryDto> queryOptions)
        {
            queryOptions.Validate(ValidationSettings);

            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(Query.Error(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var results = await Task.Run(() => _context.LimitTypes
                                         .Select(_mapper.Map <LimitType, LimitTypeQueryDto>)
                                         .AsQueryable())
                          .ConfigureAwait(false);

            return(Query.Result(results));
        }
Пример #14
0
        /// <summary>
        /// Gets a single dashboard option from the data store.
        /// </summary>
        /// <param name="id">ID that uniquely identifies the entity to be retrieved.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result includes the DTO retrieved.
        /// </returns>
        public override async Task <QueryResult <DashboardOptionQueryDto> > Get(Guid id)
        {
            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(Query.Error(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var result = await Task.Run(() =>
                                        _context.GetDashboardOptionsForUser(Guid.Parse(userId))
                                        .FirstOrDefault(x => x.Id == id))
                         .ConfigureAwait(false);

            return(result == null
                    ? Query.Error(EntityErrorCode.EntityNotFound)
                    : Query.Result(_mapper.Map <DashboardOption, DashboardOptionQueryDto>(result)));
        }
Пример #15
0
        /// <summary>
        /// Creates a limit type.
        /// </summary>
        /// <param name="dto">Data Transfer Object (DTO) used to create an entity.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result contains the DTO associated with the entity created.
        /// </returns>
        public override async Task <CommandResult <LimitTypeQueryDto, Guid> > Create(LimitTypeBaseDto dto)
        {
            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(Command.Error <LimitTypeQueryDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var validationResponse = ValidatorCreate.Validate(dto);

            if (dto == null)
            {
                return(Command.Error <LimitTypeQueryDto>(validationResponse));
            }

            if (dto.Id != Guid.Empty)
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.PropertyIsInvalid("Id"));
            }

            if (_context.LimitTypes.Any(x => x.I18NKeyName == dto.I18NKeyName))
            {
                validationResponse.FFErrors.Add(EntityErrorCode.EntityAlreadyExists);
            }

            if (validationResponse.IsInvalid)
            {
                return(Command.Error <LimitTypeQueryDto>(validationResponse));
            }

            var newEntity = new LimitType();

            _mapper.Map(dto, newEntity);

            newEntity.Id = Guid.NewGuid();
            newEntity.SetAuditFieldsOnCreate(userId);

            _context.LimitTypes.Add(newEntity);
            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.Created(_mapper.Map(newEntity, new LimitTypeQueryDto()), newEntity.Id));
        }
Пример #16
0
        /// <summary>
        /// Gets a list of Location Log Entries from the data store.
        /// </summary>
        /// <param name="queryOptions">OData query options.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result contains the list of Location Log Entry DTOs retrieved.
        /// </returns>
        public override async Task <QueryResult <LocationLogEntryQueryDto> > Get(ODataQueryOptions <LocationLogEntryQueryDto> queryOptions)
        {
            queryOptions.Validate(ValidationSettings);

            // User ID should always be available, but if not ...
            var userId = GetCurrentUser();

            if (!userId.HasValue)
            {
                return(Query.Error(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var results = await Task.Run(() => _context.GetLocationLogEntriesForUser(userId.Value)
                                         .Select(_mapper.Map <LocationLogEntry, LocationLogEntryQueryDto>)
                                         .AsQueryable())
                          .ConfigureAwait(false);

            return(Query.Result(results));
        }
Пример #17
0
        /// <summary>
        /// Gets a list of Location Types from the data store.
        /// </summary>
        /// <param name="queryOptions">OData query options.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result contains the list of Location Type DTOs retrieved.
        /// </returns>
        public override async Task<QueryResult<LocationTypeQueryDto>> Get(ODataQueryOptions<LocationTypeQueryDto> queryOptions)
        {
            // Thread.CurrentPrincipal is not available in the constructor.  Do not try to move this.
            var uid = GetCurrentUser();

            if (!uid.HasValue)
                return Query.Error(GeneralErrorCodes.TokenInvalid("UserId"));

            queryOptions.Validate(ValidationSettings);

            var results = await Task.Run(() => _context.LocationTypes
                .Include(x => x.LocationTypeGroup)
                .Include(x => x.LocationTypes)
                .Include(x => x.Parent)
                .Select(_mapper.Map<LocationType, LocationTypeQueryDto>)
                .AsQueryable())
                .ConfigureAwait(false);

            return Query.Result(results);
        }
Пример #18
0
        /// <summary>
        /// Gets a single limit type from the data store.
        /// </summary>
        /// <param name="id">ID that uniquely identifies the entity to be retrieved.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result includes the DTO retrieved.
        /// </returns>
        public override async Task <QueryResult <LimitTypeQueryDto> > Get(Guid id)
        {
            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(Query.Error(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var result = await Task.Run(() => _context.LimitTypes
                                        .FirstOrDefault(x => x.Id == id))
                         .ConfigureAwait(false);

            if (result == null)
            {
                return(Query.Error(EntityErrorCode.EntityNotFound));
            }

            var dto = _mapper.Map <LimitType, LimitTypeQueryDto>(result);

            return(Query.Result(dto));
        }
Пример #19
0
        /// <summary>
        /// Gets a single Location Type from the data store.
        /// </summary>
        /// <param name="id">ID that uniquely identifies the Location Type to be retrieved.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result includes the Location Type DTO retrieved.
        /// </returns>
        public override async Task<QueryResult<LocationTypeQueryDto>> Get(Guid id)
        {
            // Thread.CurrentPrincipal is not available in the constructor.  Do not try to move this.
            var uid = GetCurrentUser();

            if (!uid.HasValue)
                return Query.Error(GeneralErrorCodes.TokenInvalid("UserId"));

            var result = await Task.Run(() => _context.LocationTypes
                .Include(x => x.LocationTypeGroup)
                .Include(x => x.LocationTypes)
                .Include(x => x.Parent)
                .FirstOrDefault(l => l.Id == id))
                .ConfigureAwait(false);

            if (result == null)
                return Query.Error(EntityErrorCode.EntityNotFound);

            var locationTypeDto = _mapper.Map<LocationType, LocationTypeQueryDto>(result);

            return Query.Result(locationTypeDto);
        }
Пример #20
0
        /// <summary>
        /// Gets a list of locations from the data store based on the user
        /// </summary>
        /// <param name="queryOptions">OData query options.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result contains the list of location DTOs retrieved.
        /// </returns>
        public override async Task <QueryResult <LocationQueryDto> > Get(ODataQueryOptions <LocationQueryDto> queryOptions)
        {
            queryOptions.Validate(ValidationSettings);

            var uid = GetCurrentUser();

            if (!uid.HasValue)
            {
                return(Query.Error(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var results = await Task.Run(() => _context.GetLocationsForUser(uid.Value)
                                         .Include(x => x.LocationType)
                                         .Include(x => x.LocationType.LocationTypeGroup)
                                         .Include(x => x.Parent)
                                         .Include(x => x.Locations.Select(y => y.Locations))
                                         .Include(x => x.ProductOfferingTenantLocations)
                                         .Select(_mapper.Map <Location, LocationQueryDto>)
                                         .AsQueryable())
                          .ConfigureAwait(false);

            return(Query.Result(results));
        }
Пример #21
0
        /// <summary>
        /// Deletes a limit type.
        /// </summary>
        /// <param name="id">ID that identifies the entity to be deleted.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// </returns>
        public override async Task <CommandResult <LimitTypeQueryDto, Guid> > Delete(Guid id)
        {
            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(Command.Error <LimitTypeQueryDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var entity = await _context.LimitTypes
                         .SingleOrDefaultAsync(x => x.Id == id)
                         .ConfigureAwait(false);

            if (entity == null)
            {
                return(Command.Error <LimitTypeQueryDto>(EntityErrorCode.EntityNotFound));
            }

            _context.LimitTypes.Remove(entity);
            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.NoContent <LimitTypeQueryDto>());
        }
Пример #22
0
        /// <summary>
        /// Gets a single Location Log Entry from the data store.
        /// </summary>
        /// <param name="id">ID that uniquely identifies the Location Log Entry to be retrieved.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result includes the Location Log Entry DTO retrieved.
        /// </returns>
        public override async Task <QueryResult <LocationLogEntryQueryDto> > Get(Guid id)
        {
            // User ID should always be available, but if not ...
            var userId = GetCurrentUser();

            if (!userId.HasValue)
            {
                return(Query.Error(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var result = await _context.GetLocationLogEntriesForUser(userId.Value)
                         .FirstOrDefaultAsync(l => l.Id == id)
                         .ConfigureAwait(false);

            if (result == null)
            {
                return(Query.Error(EntityErrorCode.EntityNotFound));
            }

            var locationLogEntryQueryDto = _mapper.Map <LocationLogEntry, LocationLogEntryQueryDto>(result);

            return(Query.Result(locationLogEntryQueryDto));
        }
Пример #23
0
        /// <summary>
        /// Deletes a Location Log Entry.
        /// </summary>
        /// <param name="id">ID that identifies the Location Log Entry to be deleted.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// </returns>
        public override async Task <CommandResult <LocationLogEntryQueryDto, Guid> > Delete(Guid id)
        {
            // User ID should always be available, but if not ...
            var userId = GetCurrentUser();

            if (!userId.HasValue)
            {
                return(Command.Error <LocationLogEntryQueryDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var locationLogEntry = await _context.GetLocationLogEntriesForUser(userId.Value)
                                   .SingleOrDefaultAsync(l => l.Id == id)
                                   .ConfigureAwait(false);

            if (locationLogEntry == null)
            {
                return(Command.Error <LocationLogEntryQueryDto>(EntityErrorCode.EntityNotFound));
            }

            _context.LocationLogEntries.Remove(locationLogEntry);
            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.NoContent <LocationLogEntryQueryDto>());
        }
Пример #24
0
        /// <summary>
        /// Updates a location using a <see cref="Delta"/> object.
        /// </summary>
        /// <param name="id">ID of the location to be updated.</param>
        /// <param name="delta">
        /// Delta containing a list of location properties.  Web Api does the magic of converting the JSON to
        /// a delta.
        /// </param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// </returns>
        public override async Task <CommandResult <LocationBaseDto, Guid> > Update(Guid id, Delta <LocationBaseDto> delta)
        {
            // Thread.CurrentPrincipal is not available in the constrtor.  Do not try and move this
            var uid = GetCurrentUser();

            // User ID should always be available, but if not ...
            if (!uid.HasValue)
            {
                return(Command.Error <LocationBaseDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            if (delta == null)
            {
                return(Command.Error <LocationBaseDto>(EntityErrorCode.EntityFormatIsInvalid));
            }

            var location = await _context.GetLocationsForUser(uid.Value)
                           .SingleOrDefaultAsync(l => l.Id == id)
                           .ConfigureAwait(false);

            if (location == null)
            {
                return(Command.Error <LocationBaseDto>(EntityErrorCode.EntityNotFound));
            }

            var locationDto = _mapper.Map(location, new LocationBaseDto());

            delta.Patch(locationDto);

            var validationResponse = ValidatorUpdate.Validate(locationDto);

            if (locationDto.ParentId.HasValue)
            {
                var existingTask = _context.Locations.AnyAsync(l => l.Id == locationDto.ParentId.Value);

                if (!existingTask.Result)
                {
                    validationResponse.FFErrors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist(nameof(Location.ParentId)));
                }
                else
                {
                    // Check for circular references
                    if (await LocationValidator.IsCircularReference(_context.Locations, locationDto, id))
                    {
                        validationResponse.FFErrors.Add(ValidationErrorCode.CircularReferenceNotAllowed(nameof(Location.ParentId)));
                    }
                }
            }

            // Check that Location Type exists
            if (locationDto.LocationTypeId != Guid.Empty && !_context.LocationTypes.Any(lt => lt.Id == locationDto.LocationTypeId))
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist(nameof(Location.LocationTypeId)));
            }

            // Including the original Id in the Patch request will not return an error but attempting to change the Id is not allowed.
            if (locationDto.Id != id)
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.EntityIDUpdateNotAllowed("Id"));
            }

            // Check that unique fields are still unique
            if (_context.Locations.Any(l => l.Id != id && l.Name == locationDto.Name))
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.EntityPropertyDuplicateNotAllowed(nameof(Location.Name)));
            }

            if (validationResponse.IsInvalid)
            {
                return(Command.Error <LocationBaseDto>(validationResponse));
            }

            _context.Locations.Attach(location);
            _mapper.Map(locationDto, location);

            location.SetAuditFieldsOnUpdate(uid.Value);

            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.NoContent <LocationBaseDto>());
        }
Пример #25
0
        /// <summary>
        /// Deletes the requested operation if the operation has no measurements associated to it's locations.
        /// </summary>
        /// <param name="operationId">Guid identitifer of the operation to delete</param>
        /// <returns>Task that returns the request result.</returns>
        public async Task <CommandResultNoDto> Delete(Guid?operationId)
        {
            var errors = new List <FFErrorCode>();

            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (string.IsNullOrEmpty(userId))
            {
                errors.Add(GeneralErrorCodes.TokenInvalid("UserId"));
            }

            if (!operationId.HasValue || operationId == Guid.Empty)
            {
                errors.Add(ValidationErrorCode.PropertyRequired("OperationId"));
            }

            if (errors.Count > 0)
            {
                return(NoDtoHelpers.CreateCommandResult(errors));
            }

            var userIdGuid = Guid.Parse(userId);

            List <Location> locations = new List <Location>();
            List <LocationParameterLimit> locationParameterLimits    = new List <LocationParameterLimit>();
            List <LocationParameter>      locationParameters         = new List <LocationParameter>();
            List <LocationLogEntry>       locationLocationLogEntries = new List <LocationLogEntry>();

            // Check that the Location exists and if it's an operation
            if (!_context.Locations.Any(x => x.Id == operationId.Value && x.LocationType.LocationTypeGroup.Id == Data.Constants.LocationTypeGroups.Operation.Id))
            {
                errors.Add(EntityErrorCode.EntityNotFound);
            }
            else
            {
                // Check if user is in the proper tenant.
                if (!_context.Locations.Single(x => x.Id == operationId.Value)
                    .ProductOfferingTenantLocations.Any(x => x.Tenant.Users.Any(u => u.Id == userIdGuid)))
                {
                    errors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist("TenantId"));
                }
                // Check that the operation has no measurements or notes and can be deleted

                // NOTE : This method will not scale beyond more than 4 or 5 levels max
                var operation = _context.Locations.Include("Locations").Single(x => x.Id == operationId.Value);
                locations.Add(operation);
                var systems = operation.Locations;
                locations.AddRange(systems);
                foreach (var system in systems)
                {
                    locations.AddRange(_context.Locations.Where(x => x.ParentId == system.Id).ToList());
                }

                var locationIds = locations.Select(l => l.Id);
                locationParameters =
                    _context.LocationParameters.Where(x => locationIds.Contains(x.LocationId)).ToList();

                var locationParamIds = locationParameters.Select(lp => lp.Id);
                locationParameterLimits =
                    _context.LocationParameterLimits.Where(
                        x => locationParamIds.Contains(x.LocationParameterId)).ToList();

                var hasLocationLocationLogEntries =
                    _context.LocationLogEntries.Any(x => locationIds.Contains(x.LocationId));

                var hasMeasurements   = _context.Measurements.Any(x => locationParamIds.Contains(x.LocationParameterId));
                var hasParameterNotes =
                    _context.LocationParameterNotes.Any(
                        x => locationParamIds.Contains(x.LocationParameterId));

                var hasMeasurementTransactions =
                    _context.MeasurementTransactions.Any(x => locationIds.Contains(x.LocationId));

                if (hasParameterNotes || hasMeasurements || hasLocationLocationLogEntries || hasMeasurementTransactions)
                {
                    errors.Add(EntityErrorCode.EntityCouldNotBeDeleted);
                }
            }

            if (errors.Count > 0)
            {
                return(NoDtoHelpers.CreateCommandResult(errors));
            }

            _context.LocationParameterLimits.RemoveRange(locationParameterLimits);
            _context.LocationParameters.RemoveRange(locationParameters);
            _context.Locations.RemoveRange(locations);
            _context.LocationLogEntries.RemoveRange(locationLocationLogEntries);

            await _context.SaveChangesAsync().ConfigureAwait(false);

            var commandResult = NoDtoHelpers.CreateCommandResult(errors);

            // CreateCommandResult will either return BadRequest(400) or Ok(200)
            // Overriding the Status code to return a 204 on a successful delete
            commandResult.StatusCode = FacadeStatusCode.NoContent;
            return(commandResult);
        }
Пример #26
0
        /// <summary>
        /// Creates a location.
        /// </summary>
        /// <param name="dto">Data Transfer Object (DTO) used to create a location.</param>
        /// <returns>
        /// An asynchronous task result containing information needed to create an API response message.
        /// If successful, the task result contains the DTO associated with the location.
        /// </returns>
        /// <remarks>
        /// Note that there is no checking for a circular reference for creating a location. This is
        /// because the created item does not have children. So, there cannot be a circular reference.
        /// </remarks>
        public override async Task <CommandResult <LocationQueryDto, Guid> > Create(LocationBaseDto dto)
        {
            // Thread.CurrentPrincipal is not available in the constructor.  Do not try to move this.
            var uid = GetCurrentUser();

            // User ID should always be available, but if not ...
            if (!uid.HasValue)
            {
                return(Command.Error <LocationQueryDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var user = await _context.Users
                       .Include(x => x.Tenants.Select(y => y.ProductOfferings))
                       .FirstOrDefaultAsync(u => u.Id == uid.Value);

            if (user == null)
            {
                return(Command.Error <LocationQueryDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            var validationResponse = ValidatorCreate.Validate(dto);

            if (dto == null)
            {
                return(Command.Error <LocationQueryDto>(validationResponse));
            }

            if (dto.Id != Guid.Empty)
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.PropertyIsInvalid(nameof(Location.Id)));
            }

            var existing = await _context.Locations.AnyAsync(l => l.Name == dto.Name).ConfigureAwait(false);

            if (existing)
            {
                validationResponse.FFErrors.Add(EntityErrorCode.EntityAlreadyExists);
            }

            if (dto.ParentId.HasValue)
            {
                existing = await _context.Locations.AnyAsync(l => l.Id == dto.ParentId.Value).ConfigureAwait(false);

                if (!existing)
                {
                    validationResponse.FFErrors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist(nameof(Location.ParentId)));
                }
            }

            if (dto.LocationTypeId != Guid.Empty && !_context.LocationTypes.Any(lt => lt.Id == dto.LocationTypeId))
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist(nameof(Location.LocationTypeId)));
            }

            if (validationResponse.IsInvalid)
            {
                return(Command.Error <LocationQueryDto>(validationResponse));
            }

            var location = new Location
            {
                Id = Guid.NewGuid()
            };

            _mapper.Map(dto, location);

            location.CreatedById = uid.Value;
            location.CreatedOn   = DateTime.UtcNow;
            location.SetAuditFieldsOnUpdate(uid.Value);

            _context.Locations.Add(location);

            // Add the Location to the Product Offering / Tenant / Location List
            if (user.Tenants.Count > 0)
            {
                // Only care about the first tenant in the list. In the future, the list of tenants
                // will contain only one element and may be replaced by a scalar.
                var tenant = user.Tenants.ElementAt(0);

                // Add a Product Offering / Tenant / Location for the Collect PO
                // TODO: This is going to break if we change the name of the productOffering
                var productOffering = tenant.ProductOfferings.FirstOrDefault(x => x.Name == "Collect");

                if (productOffering == null)
                {
                    return(Command.Error <LocationQueryDto>(EntityErrorCode.ReferencedEntityNotFound));
                }

                var productOfferingTenantLocation = new ProductOfferingTenantLocation
                {
                    ProductOfferingId = productOffering.Id,
                    TenantId          = tenant.Id,
                    LocationId        = location.Id
                };

                _context.ProductOfferingTenantLocations.Add(productOfferingTenantLocation);
            }

            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.Created(_mapper.Map(location, new LocationQueryDto()), location.Id));
        }
Пример #27
0
        /// <summary>
        /// Accepts a single xls file that contains operation configuration.
        /// </summary>
        /// <param name="fileMetadata">Metadata associated with the file upload request.</param>
        /// <param name="authenticationHeader">Authentication header for the request.</param>
        /// <param name="requestTenantId">The selected Tenant Id from the request import the Operation Config to</param>
        /// <returns>A task that returns the result of the upload option.</returns>
        public async Task <CommandResultNoDto> Upload(FileUploadMetadataDto fileMetadata, string authenticationHeader, Guid requestTenantId)
        {
            var errors      = new List <FFErrorCode>();
            var odataHelper = new Core.Api.OData.ODataHelper();

            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                errors.Add(GeneralErrorCodes.TokenInvalid("UserId"));
            }

            if (errors.Count > 0)
            {
                return(NoDtoHelpers.CreateCommandResult(errors));
            }

            // ReSharper disable once AssignNullToNotNullAttribute
            var userIdGuid = Guid.Parse(userId);

            // Check that the Tenant Id in the request body is in the user's claim tenants
            var tenants = odataHelper.GetTenantIds(Thread.CurrentPrincipal) as List <Guid>;

            // Check user has no tenants in their claim or if the tenantid in the request body is not in the claim
            if (tenants == null || tenants.All(x => x != requestTenantId))
            {
                errors.Add(ValidationErrorCode.ForeignKeyValueDoesNotExist("TenantId"));
            }

            if (errors.Count > 0)
            {
                return(NoDtoHelpers.CreateCommandResult(errors));
            }


            // Store file in blob storage.
            var result = await _blobManager.StoreAsync(_blobStorageConnectionString, _blobStorageContainerName, fileMetadata.SavedFileName);

            // Add file metadata to documentDB to later be retrieved by request
            // An Id property is created by documentDB and in populated in the result object
            await _documentDb.CreateItemAsync(
                new UploadTransaction
            {
                OriginalFileName      = fileMetadata.OriginalFileName,
                TenantIds             = tenants,
                UploadTransactionType = fileMetadata.TransactionType,
                UserId       = userIdGuid,
                UtcTimestamp = DateTime.UtcNow
            });

            var queueMessage = new BlobQueueMessage
            {
                BlobName            = result.BlobName,
                BlobSize            = result.BlobSize,
                BlobUrl             = result.BlobUrl,
                BlobTransactionType = fileMetadata.TransactionType,
                UserId = userIdGuid,
                AuthenticationHeader = authenticationHeader,
                // TenantId should be checked by the blob processor that it matches the tenant in the Operation Config to be processed
                TenantId = requestTenantId
            };

            var msg = JsonConvert.SerializeObject(queueMessage);
            // Add message to queue.
            await _queueManager.AddAsync(_blobStorageConnectionString, _queueStorageContainerName, msg);

            return(NoDtoHelpers.CreateCommandResult(errors));
        }
Пример #28
0
        public async Task <IHttpActionResult> Post()
        {
            var errors = new List <FFErrorCode>();

            // Parse Request Content
            var provider = new MultipartFormDataStreamProvider(Path.GetTempPath());
            var parts    = await Request.Content.ReadAsMultipartAsync(provider).ConfigureAwait(false);

            // Validate the request body
            if (string.IsNullOrEmpty(parts.FormData["uploadTransactionType"]))
            {
                errors.Add(GeneralErrorCodes.FormDataFieldMissing("uploadTransactionType"));
            }

            var tenantIdString = parts.FormData["tenantId"];

            if (string.IsNullOrEmpty(tenantIdString))
            {
                errors.Add(GeneralErrorCodes.FormDataFieldMissing("tenantId"));
            }

            var tenantIdGuid = Guid.Empty;

            if (!Guid.TryParse(tenantIdString, out tenantIdGuid) || tenantIdGuid == Guid.Empty)
            {
                errors.Add(GeneralErrorCodes.FormDataFieldInvalid("tenantId"));
            }

            // Get files
            var files           = parts.FileData.Select(x => x.LocalFileName);
            var enumeratedFiles = files as IList <string> ?? files.ToList();

            if (!enumeratedFiles.Any())
            {
                errors.Add(GeneralErrorCodes.FormDataFilesMissing());
            }

            if (errors.Any())
            {
                return(Request.CreateApiResponse(NoDtoHelpers.CreateCommandResult(errors)));
            }

            var fileToUpload     = enumeratedFiles.First();
            var originalFileName = parts.FileData[0].Headers.ContentDisposition.FileName.Replace("\"", string.Empty);

            var fileUploadMetadata = new FileUploadMetadataDto
            {
                SavedFileName    = fileToUpload,
                OriginalFileName = originalFileName,
                TransactionType  = parts.FormData["uploadTransactionType"].Replace("\"", string.Empty)
            };

            var authHeader = Request.Headers.Authorization.ToString();
            var result     = await _facade.Upload(fileUploadMetadata, authHeader, tenantIdGuid);

            foreach (var file in enumeratedFiles)
            {
                File.Delete(file);
            }

            return(Request.CreateApiResponse(result));
        }
Пример #29
0
        public override async Task <CommandResult <InAppMessageBaseDto, Guid> > Update(Guid id, Delta <InAppMessageBaseDto> delta)
        {
            // Check user has proper access to update the message
            var uid = GetCurrentUser();

            if (!uid.HasValue)
            {
                return(Command.Error <InAppMessageBaseDto>(GeneralErrorCodes.TokenInvalid("UserId")));
            }

            if (delta == null)
            {
                return(Command.Error <InAppMessageBaseDto>(EntityErrorCode.EntityFormatIsInvalid));
            }

            var entity = _context.InAppMessages.SingleOrDefault(msg => msg.Id == id);

            if (entity == null)
            {
                return(Command.Error <InAppMessageBaseDto>(EntityErrorCode.EntityNotFound));
            }

            // Check if the calling User shares a Tenant with the UserId passed in
            var tenants     = _context.GetTenantsForUser(uid.Value);
            var shareTenant = tenants.Any(t => t.Users.Any(u => u.Id == entity.UserId));

            if (!shareTenant)
            {
                return(Command.Error <InAppMessageBaseDto>(ValidationErrorCode.ForeignKeyValueDoesNotExist("UserId")));
            }

            var dto = _mapper.Map(entity, new InAppMessageBaseDto());

            delta.Patch(dto);

            var validationResponse = ValidatorUpdate.Validate(dto);

            // Including the original Id in the Patch request will not return an error but attempting to change the Id is not allowed.
            if (dto.Id != id)
            {
                validationResponse.FFErrors.Add(ValidationErrorCode.EntityIDUpdateNotAllowed("Id"));
            }

            if (validationResponse.IsInvalid)
            {
                return(Command.Error <InAppMessageBaseDto>(validationResponse));
            }

            // Apply the update
            _context.InAppMessages.Attach(entity);

            //if the entity's IsRead flag get set to true from false, then set the DateRead to now
            if (dto.IsRead == true == !entity.IsRead)
            {
                entity.DateRead = DateTime.UtcNow;
            }
            else if (dto.IsRead == false == !entity.IsRead)
            {
                entity.DateRead = null;
            }

            _mapper.Map(dto, entity);
            entity.SetAuditFieldsOnUpdate(uid.Value);

            await _context.SaveChangesAsync().ConfigureAwait(false);

            return(Command.NoContent <InAppMessageBaseDto>());
        }
Пример #30
0
        /// <summary>
        /// Retrieves the indicated file.
        /// </summary>
        /// <param name="id">
        /// ID that uniquely identifies the file to be retrieved. The ID is is the key of the
        /// metadata stored in DocumentDb.
        /// </param>
        /// <returns>The file indicated by the specified ID.</returns>
        public async Task <HttpResponseMessage> Get(Guid?id)
        {
            // Check that token contains a user ID
            var userId = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.GetUserIdFromPrincipal();

            if (userId == null)
            {
                return(HandleErrors(GeneralErrorCodes.TokenInvalid("UserId"), HttpStatusCode.Unauthorized));
            }

            // Make sure user ID is active
            var userIdGuid = new Guid(userId);
            var user       = await _context.Users.FirstOrDefaultAsync(u => u.Id == userIdGuid);

            if (user == null || !user.IsActive)
            {
                return(HandleErrors(GeneralErrorCodes.TokenInvalid("UserId"), HttpStatusCode.Unauthorized));
            }

            // Make sure there's a tenant associated with the user
            if (user.Tenants.Count < 1)
            {
                return(HandleErrors(GeneralErrorCodes.TokenInvalid("UserId"), HttpStatusCode.Unauthorized));
            }

            // Validate the argument (invalid Guid's are received as nulls)
            if (id == null)
            {
                return(HandleErrors(ValidationErrorCode.PropertyIsInvalid(nameof(id)), HttpStatusCode.BadRequest));
            }

            // Retrieve the metadata associated with the specified ID
            var metadata = await _documentDb.GetItemAsync(id.ToString());

            if (metadata == null || string.IsNullOrWhiteSpace(metadata.BlobStorageContainerName) ||
                string.IsNullOrWhiteSpace(metadata.BlobStorageBlobName))
            {
                return(HandleErrors(EntityErrorCode.EntityNotFound, HttpStatusCode.NotFound));
            }

            // Make sure the user is authorized (intentionally returns Not Found even though it's an authorization problem)
            if (metadata.TenantIds.Count < 1 ||
                !metadata.TenantIds.Intersect(user.Tenants.Select(u => u.Id)).Any())
            {
                return(HandleErrors(EntityErrorCode.EntityNotFound, HttpStatusCode.NotFound));
            }

            // Retrieve the blob
            var stream = new MemoryStream();
            BlobDownloadResult result;

            try
            {
                result = await _blobManager.DownloadBlobAsync(stream, _blobStorageConnectionString,
                                                              metadata.BlobStorageContainerName, metadata.BlobStorageBlobName);
            }
            catch (Exception ex)
            {
                FFLogManager.LogException(ex);
                return(HandleErrors(EntityErrorCode.EntityNotFound, HttpStatusCode.NotFound));
            }

            if (stream.Length == 0)
            {
                return(HandleErrors(EntityErrorCode.EntityNotFound, HttpStatusCode.NotFound));
            }

            // Create the response
            stream.Position = 0;
            var response = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StreamContent(stream)
            };

            // Determine file name
            string filename = result.BlobName;

            if (!string.IsNullOrWhiteSpace(metadata.OriginalFileName))
            {
                var fileInfo = new FileInfo(metadata.OriginalFileName);
                if (!string.IsNullOrWhiteSpace(fileInfo.Name))
                {
                    filename = fileInfo.Name;
                }
            }

            // Set response content headers
            response.Content.Headers.ContentLength      = stream.Length;
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = filename,
                Size     = stream.Length
            };

            return(response);
        }