Skip to content
34 changes: 18 additions & 16 deletions API/Controller/Admin/GetOnlineDevices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,25 @@ public async Task<IActionResult> GetOnlineDevices()
}
}).ToArrayAsync();

return RespondSuccessLegacy(allOnlineDevices.Select(x =>
{
var dbItem = dbLookup.First(y => y.Id == x.Id);
return new AdminOnlineDeviceResponse
return RespondSuccessLegacy(
allOnlineDevices
.Select(x =>
{
Id = x.Id,
FirmwareVersion = x.FirmwareVersion,
Gateway = x.Gateway,
Owner = dbItem.Owner,
Name = dbItem.Name,
ConnectedAt = x.ConnectedAt,
UserAgent = x.UserAgent,
BootedAt = x.BootedAt,
LatencyMs = x.LatencyMs,
Rssi = x.Rssi,
};
})
var dbItem = dbLookup.First(y => y.Id == x.Id);
return new AdminOnlineDeviceResponse
{
Id = x.Id,
FirmwareVersion = x.FirmwareVersion,
Gateway = x.Gateway,
Owner = dbItem.Owner,
Name = dbItem.Name,
ConnectedAt = x.ConnectedAt,
UserAgent = x.UserAgent,
BootedAt = x.BootedAt,
LatencyMs = x.LatencyMs,
Rssi = x.Rssi,
};
})
);
}

Expand Down
10 changes: 6 additions & 4 deletions API/Controller/Devices/DevicesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,19 @@ public sealed partial class DevicesController
/// </summary>
/// <response code="200">All devices for the current user</response>
[HttpGet]
[ProducesResponseType<BaseResponse<Models.Response.ResponseDevice[]>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ProducesResponseType<BaseResponse<IAsyncEnumerable<Models.Response.ResponseDevice>>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[MapToApiVersion("1")]
public async Task<IActionResult> ListDevices()
public IActionResult ListDevices()
{
var devices = await _db.Devices.Where(x => x.Owner == CurrentUser.Id)
var devices = _db.Devices
.Where(x => x.Owner == CurrentUser.Id)
.Select(x => new Models.Response.ResponseDevice
{
Id = x.Id,
Name = x.Name,
CreatedOn = x.CreatedOn
}).ToArrayAsync();
})
.AsAsyncEnumerable();

return RespondSuccessLegacy(devices);
}
Expand Down
23 changes: 13 additions & 10 deletions API/Controller/Devices/ShockersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,26 @@ public sealed partial class DevicesController
/// <response code="200">All shockers for the device</response>
/// <response code="404">Device does not exists or you do not have access to it.</response>
[HttpGet("{deviceId}/shockers")]
[ProducesResponseType<BaseResponse<ShockerResponse[]>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ProducesResponseType<BaseResponse<IAsyncEnumerable<ShockerResponse>>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ProducesResponseType<OpenShockProblem>(StatusCodes.Status404NotFound, MediaTypeNames.Application.ProblemJson)] // DeviceNotFound
[MapToApiVersion("1")]
public async Task<IActionResult> GetShockers([FromRoute] Guid deviceId)
{
var deviceExists = await _db.Devices.AnyAsync(x => x.Owner == CurrentUser.Id && x.Id == deviceId);
if (!deviceExists) return Problem(DeviceError.DeviceNotFound);

var shockers = await _db.Shockers.Where(x => x.Device == deviceId).Select(x => new ShockerResponse
{
Id = x.Id,
Name = x.Name,
RfId = x.RfId,
CreatedOn = x.CreatedOn,
Model = x.Model,
IsPaused = x.Paused
}).ToArrayAsync();
var shockers = _db.Shockers
.Where(x => x.Device == deviceId)
.Select(x => new ShockerResponse
{
Id = x.Id,
Name = x.Name,
RfId = x.RfId,
CreatedOn = x.CreatedOn,
Model = x.Model,
IsPaused = x.Paused
})
.AsAsyncEnumerable();

return RespondSuccessLegacy(shockers);
}
Expand Down
10 changes: 6 additions & 4 deletions API/Controller/Shares/Links/ListShareLinks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ public sealed partial class ShareLinksController
/// </summary>
/// <response code="200">All share links for the current user</response>
[HttpGet]
[ProducesResponseType<BaseResponse<ShareLinkResponse[]>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
public async Task<IActionResult> List()
[ProducesResponseType<BaseResponse<IAsyncEnumerable<ShareLinkResponse>>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
public IActionResult List()
{
var ownShareLinks = await _db.ShockerSharesLinks.Where(x => x.OwnerId == CurrentUser.Id)
.Select(x => ShareLinkResponse.GetFromEf(x)).ToArrayAsync();
var ownShareLinks = _db.ShockerSharesLinks
.Where(x => x.OwnerId == CurrentUser.Id)
.Select(x => ShareLinkResponse.GetFromEf(x))
.AsAsyncEnumerable();

return RespondSuccessLegacy(ownShareLinks);
}
Expand Down
19 changes: 12 additions & 7 deletions API/Controller/Shares/V2GetShares.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@ namespace OpenShock.API.Controller.Shares;
public sealed partial class SharesController
{
[HttpGet]
[ProducesResponseType<IEnumerable<GenericIni>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ProducesResponseType<IAsyncEnumerable<GenericIni>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ApiVersion("2")]
public async Task<GenericIni[]> GetSharesByUsers()
public IAsyncEnumerable<GenericIni> GetSharesByUsers()
{
var sharedToUsers = await _db.ShockerShares.Where(x => x.Shocker.DeviceNavigation.Owner == CurrentUser.Id)
return _db.ShockerShares
.Where(x => x.Shocker.DeviceNavigation.Owner == CurrentUser.Id)
.Select(x => new GenericIni
{
Id = x.SharedWithNavigation.Id,
Image = x.SharedWithNavigation.GetImageUrl(),
Name = x.SharedWithNavigation.Name
}).OrderBy(x => x.Name).Distinct().ToArrayAsync();
return sharedToUsers;
})
.OrderBy(x => x.Name)
.Distinct()
.AsAsyncEnumerable();
}

[HttpGet("{userId:guid}")]
Expand All @@ -35,7 +38,8 @@ public async Task<GenericIni[]> GetSharesByUsers()
[ApiVersion("2")]
public async Task<IActionResult> GetSharesToUser(Guid userId)
{
var sharedWithUser = await _db.ShockerShares.Where(x => x.Shocker.DeviceNavigation.Owner == CurrentUser.Id && x.SharedWith == userId)
var sharedWithUser = await _db.ShockerShares
.Where(x => x.Shocker.DeviceNavigation.Owner == CurrentUser.Id && x.SharedWith == userId)
.Select(x => new UserShareInfo
{
Id = x.Shocker.Id,
Expand All @@ -54,7 +58,8 @@ public async Task<IActionResult> GetSharesToUser(Guid userId)
Intensity = x.LimitIntensity
},
Paused = x.Paused
}).ToArrayAsync();
})
.ToArrayAsync();

if(sharedWithUser.Length == 0)
{
Expand Down
62 changes: 31 additions & 31 deletions API/Controller/Shares/V2Requests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,45 @@ namespace OpenShock.API.Controller.Shares;
public sealed partial class SharesController
{
[HttpGet("requests/outstanding")]
[ProducesResponseType<ShareRequestBaseItem[]>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ProducesResponseType<IAsyncEnumerable<ShareRequestBaseItem>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ApiVersion("2")]
public async Task<ShareRequestBaseItem[]> GetOutstandingRequestsList()
public IAsyncEnumerable<ShareRequestBaseItem> GetOutstandingRequestsList()
{
var outstandingShares = await _db.ShareRequests.Where(x => x.Owner == CurrentUser.Id)
return _db.ShareRequests
.Where(x => x.Owner == CurrentUser.Id)
.Select(x => new ShareRequestBaseItem()
{
Id = x.Id,
CreatedOn = x.CreatedOn,
Owner = new GenericIni
{
Id = x.OwnerNavigation.Id,
Name = x.OwnerNavigation.Name,
Image = x.OwnerNavigation.GetImageUrl()
},
SharedWith = x.UserNavigation == null
? null
: new GenericIni
Id = x.Id,
CreatedOn = x.CreatedOn,
Owner = new GenericIni
{
Id = x.UserNavigation.Id,
Name = x.UserNavigation.Name,
Image = x.UserNavigation.GetImageUrl()
Id = x.OwnerNavigation.Id,
Name = x.OwnerNavigation.Name,
Image = x.OwnerNavigation.GetImageUrl()
},
Counts = new ShareRequestBaseItem.ShareRequestCounts
{
Shockers = x.ShareRequestsShockers.Count
}
}).ToArrayAsync();

return outstandingShares;
SharedWith = x.UserNavigation == null
? null
: new GenericIni
{
Id = x.UserNavigation.Id,
Name = x.UserNavigation.Name,
Image = x.UserNavigation.GetImageUrl()
},
Counts = new ShareRequestBaseItem.ShareRequestCounts
{
Shockers = x.ShareRequestsShockers.Count
}
})
.AsAsyncEnumerable();
}

[HttpGet("requests/incoming")]
[ProducesResponseType<ShareRequestBaseItem[]>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ProducesResponseType<IAsyncEnumerable<ShareRequestBaseItem>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ApiVersion("2")]
public async Task<ShareRequestBaseItem[]> GetIncomingRequestsList()
public IAsyncEnumerable<ShareRequestBaseItem> GetIncomingRequestsList()
{
var outstandingShares = await _db.ShareRequests.Where(x => x.User == CurrentUser.Id)
return _db.ShareRequests
.Where(x => x.User == CurrentUser.Id)
.Select(x => new ShareRequestBaseItem
{
Id = x.Id,
Expand All @@ -76,9 +77,8 @@ public async Task<ShareRequestBaseItem[]> GetIncomingRequestsList()
{
Shockers = x.ShareRequestsShockers.Count
}
}).ToArrayAsync();

return outstandingShares;
})
.AsAsyncEnumerable();
}

[HttpGet("requests/{id:guid}")]
Expand All @@ -88,7 +88,7 @@ public async Task<ShareRequestBaseItem[]> GetIncomingRequestsList()
public async Task<IActionResult> GetRequest(Guid id)
{
var outstandingShare = await _db.ShareRequests.Where(x => x.Id == id && (x.Owner == CurrentUser.Id || x.User == CurrentUser.Id))
.Select(x => new ShareRequestBaseDetails()
.Select(x => new ShareRequestBaseDetails
{
Id = x.Id,
CreatedOn = x.CreatedOn,
Expand Down
13 changes: 9 additions & 4 deletions API/Controller/Shockers/ControlLogController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public sealed partial class ShockerController
/// <response code="200">The logs</response>
/// <response code="404">Shocker does not exist</response>
[HttpGet("{shockerId}/logs")]
[ProducesResponseType<BaseResponse<IEnumerable<LogEntry>>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ProducesResponseType<BaseResponse<IAsyncEnumerable<LogEntry>>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ProducesResponseType<OpenShockProblem>(StatusCodes.Status404NotFound, MediaTypeNames.Application.ProblemJson)] // ShockerNotFound
[MapToApiVersion("1")]
public async Task<IActionResult> GetShockerLogs([FromRoute] Guid shockerId, [FromQuery] uint offset = 0,
Expand All @@ -33,8 +33,12 @@ [FromQuery] [Range(1, 500)] uint limit = 100)
var exists = await _db.Shockers.AnyAsync(x => x.DeviceNavigation.Owner == CurrentUser.Id && x.Id == shockerId);
if (!exists) return Problem(ShockerError.ShockerNotFound);

var logs = await _db.ShockerControlLogs.Where(x => x.ShockerId == shockerId)
.OrderByDescending(x => x.CreatedOn).Skip((int)offset).Take((int)limit).Select(x => new LogEntry
var logs = _db.ShockerControlLogs
.Where(x => x.ShockerId == shockerId)
.OrderByDescending(x => x.CreatedOn)
.Skip((int)offset)
.Take((int)limit)
.Select(x => new LogEntry
{
Id = x.Id,
Duration = x.Duration,
Expand All @@ -56,7 +60,8 @@ [FromQuery] [Range(1, 500)] uint limit = 100)
Image = x.ControlledByNavigation.GetImageUrl(),
CustomName = x.CustomName
}
}).ToArrayAsync();
})
.AsAsyncEnumerable();

return RespondSuccessLegacy(logs);
}
Expand Down
6 changes: 2 additions & 4 deletions API/Controller/Shockers/ControlShockerController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Net;
using System.Net.Mime;
using System.Net.Mime;
using Asp.Versioning;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
Expand All @@ -11,7 +10,6 @@
using OpenShock.Common.Models;
using OpenShock.Common.Problems;
using OpenShock.Common.Services.RedisPubSub;
using OpenShock.Common.Utils;

namespace OpenShock.API.Controller.Shockers;

Expand Down Expand Up @@ -65,7 +63,7 @@ public async Task<IActionResult> SendControl(
[ProducesResponseType<OpenShockProblem>(StatusCodes.Status412PreconditionFailed, MediaTypeNames.Application.ProblemJson)] // Shocker is paused
[ProducesResponseType<OpenShockProblem>(StatusCodes.Status403Forbidden, MediaTypeNames.Application.ProblemJson)] // You don't have permission to control this shocker
public Task<IActionResult> SendControl_DEPRECATED(
[FromBody] IEnumerable<Common.Models.WebSocket.User.Control> body,
[FromBody] IReadOnlyList<Common.Models.WebSocket.User.Control> body,
[FromServices] IHubContext<UserHub, IUserHub> userHub,
[FromServices] IRedisPubService redisPubService)
{
Expand Down
33 changes: 19 additions & 14 deletions API/Controller/Shockers/OwnShockerController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,31 @@ public sealed partial class ShockerController
/// </summary>
/// <response code="200">The shockers were successfully retrieved.</response>
[HttpGet("own")]
[ProducesResponseType<BaseResponse<IEnumerable<ResponseDeviceWithShockers>>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[ProducesResponseType<BaseResponse<IAsyncEnumerable<ResponseDeviceWithShockers>>>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)]
[MapToApiVersion("1")]
public async Task<IActionResult> ListShockers()
public IActionResult ListShockers()
{
var shockers = await _db.Devices.Where(x => x.Owner == CurrentUser.Id).OrderBy(x => x.CreatedOn).Select(
x => new ResponseDeviceWithShockers
var shockers = _db.Devices
.Where(x => x.Owner == CurrentUser.Id)
.OrderBy(x => x.CreatedOn).Select(x => new ResponseDeviceWithShockers
{
Id = x.Id,
Name = x.Name,
CreatedOn = x.CreatedOn,
Shockers = x.Shockers.OrderBy(y => y.CreatedOn).Select(y => new ShockerResponse
{
Id = y.Id,
Name = y.Name,
RfId = y.RfId,
CreatedOn = y.CreatedOn,
Model = y.Model,
IsPaused = y.Paused
})
}).ToArrayAsync();
Shockers = x.Shockers
.OrderBy(y => y.CreatedOn)
.Select(y => new ShockerResponse
{
Id = y.Id,
Name = y.Name,
RfId = y.RfId,
CreatedOn = y.CreatedOn,
Model = y.Model,
IsPaused = y.Paused
})
.ToArray()
})
.AsAsyncEnumerable();

return RespondSuccessLegacy(shockers);
}
Expand Down
Loading