Esempio n. 1
0
        public async Task <IActionResult> SetUserData([FromBody] Poco.User.SyncData syncData)
        {
            var user = await _userManager.GetUserAsync(User);

            var userId = new Guid(user.Id);

            if (syncData.People.Any() && (syncData.People.First().Id != userId))
            {
                return(BadRequest("Non-matching user id."));
            }
            if (syncData.Locations.Any(l => l.PersonId != userId))
            {
                return(BadRequest("Can't edit data with non-matching user."));
            }

            // These two requre a db query to make sure they have valid locations (owned by them).
            if (syncData.Devices.Any() || syncData.CropCycles.Any() || syncData.Sensors.Any())
            {
                var existingLocations = await _db.Locations.Where(l => l.PersonId == userId).ToListAsync();

                // The personId on the syncData locations has been checked already, new locations sent are valid too.
                var existingLocationIds = existingLocations.Concat(existingLocations).Select(l => l.Id).ToList();
                if (!syncData.Devices.All(d => existingLocationIds.Contains(d.LocationId)) ||
                    !syncData.CropCycles.All(c => existingLocationIds.Contains(c.LocationId)))
                {
                    return(BadRequest("Can't edit data with non-matching user."));
                }

                if (syncData.Sensors.Any())
                {
                    var validDeviceIds = (await _db.Devices.Where(d => existingLocationIds.Contains(d.LocationId))
                                          .Select(d => d.Id).ToListAsync())
                                         .Concat(syncData.Devices.Select(d => d.Id));
                    if (!syncData.Sensors.All(s => validDeviceIds.Contains(s.DeviceId)))
                    {
                        return(BadRequest("Can't edit data with non-matching user."));
                    }
                }
            }

            // The updatedAt times are automatically set by savechanges.
            await _db.People.AddOrUpdateRange(syncData.People, (a, b) => a.Id == b.Id);

            await _db.Locations.AddOrUpdateRange(syncData.Locations, (a, b) => a.Id == b.Id);

            await _db.Devices.AddOrUpdateRange(syncData.Devices, (a, b) => a.Id == b.Id);

            await _db.CropCycles.AddOrUpdateRange(syncData.CropCycles, (a, b) => a.Id == b.Id);

            await _db.Sensors.AddOrUpdateRange(syncData.Sensors, (a, b) => a.Id == b.Id);

            await _db.SaveChangesAsync();

            return(new OkResult());
        }
Esempio n. 2
0
        /// <summary>All user data including Person that has been updated after a specified date.</summary>
        /// <param name="startUnixUtcTimeSeconds">The earliest updated time to include, in UTC seconds since Unix epoch.</param>
        /// <returns>All user data apart from SensorHistory; people, locations, devies, cropCycles and sensors. Also sends
        ///     serverDateTime just before the queries to get the data are made.</returns>
        public async Task <IActionResult> GetUserData(long?startUnixUtcTimeSeconds)
        {
            // Get the current server time before any database requests are started.
            // The client will regard itself be up-to-date to this time.
            var serverDateTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            var startDateTime  = DateTimeOffset.FromUnixTimeSeconds(startUnixUtcTimeSeconds ?? 0);

            var user = await _userManager.GetUserAsync(User);

            var userGuid = new Guid(user.Id);

            // This will be an array with either 1 or 0 entries. This is more conventient than not using an array.
            var people = await _db.People
                         .Where(p => p.Id == userGuid)
                         .Where(p => p.UpdatedAt >= startDateTime).ToArrayAsync();

            var locations = await _db.Locations
                            .Where(l => l.PersonId == userGuid)
                            .Where(l => l.UpdatedAt >= startDateTime).ToArrayAsync();

            var locationIds = locations.Select(l => l.Id);

            var devices = await _db.Devices
                          .Where(d => locationIds.Contains(d.LocationId))
                          .Where(d => d.UpdatedAt >= startDateTime).ToArrayAsync();

            var cropcycles = await _db.CropCycles
                             .Where(c => locationIds.Contains(c.LocationId))
                             .Where(c => c.UpdatedAt >= startDateTime).ToArrayAsync();

            var cropCycleIds = cropcycles.Select(c => c.Id);
            var sensors      = await _db.Sensors
                               .Where(s => cropCycleIds.Contains(s.Id))
                               .Where(s => s.UpdatedAt >= startDateTime).ToArrayAsync();

            var userData = new Poco.User.SyncData(serverDateTime, people, locations, devices, cropcycles, sensors);

            return(new JsonResult(userData));
        }