Skip to content

Commit c1f4e4e

Browse files
hhvrcLucHeartCopilot
authored
Introduce max devices and shockers per user limit (#207)
* Initial implementation * Fix error on create device * Finish impl * bleh * Rename Device -> Hub * Use async override * Update API/Controller/Devices/DevicesController.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Luc ♥ <luca@perugia.ovh> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent cd69b9f commit c1f4e4e

File tree

8 files changed

+40
-28
lines changed

8 files changed

+40
-28
lines changed

API/Controller/Devices/DeviceOtaController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public async Task<IActionResult> GetOtaUpdateHistory([FromRoute] Guid deviceId,
4646
// Check if user owns device or has a share
4747
var deviceExistsAndYouHaveAccess = await _db.Devices.AnyAsync(x =>
4848
x.Id == deviceId && x.OwnerId == CurrentUser.Id);
49-
if (!deviceExistsAndYouHaveAccess) return Problem(DeviceError.DeviceNotFound);
49+
if (!deviceExistsAndYouHaveAccess) return Problem(HubError.HubNotFound);
5050

5151
return LegacyDataOk(await otaService.GetUpdates(deviceId));
5252
}

API/Controller/Devices/DevicesController.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using OpenShock.API.Models.Requests;
55
using OpenShock.API.Services;
66
using OpenShock.Common.Authentication.Attributes;
7+
using OpenShock.Common.Constants;
78
using OpenShock.Common.Errors;
89
using OpenShock.Common.Extensions;
910
using OpenShock.Common.Models;
@@ -59,7 +60,7 @@ public async Task<IActionResult> GetDeviceById([FromRoute] Guid deviceId)
5960
CreatedOn = x.CreatedAt,
6061
Token = hasAuthPerms ? x.Token : null
6162
}).FirstOrDefaultAsync();
62-
if (device == null) return Problem(DeviceError.DeviceNotFound);
63+
if (device == null) return Problem(HubError.HubNotFound);
6364

6465
return LegacyDataOk(device);
6566
}
@@ -80,7 +81,7 @@ public async Task<IActionResult> GetDeviceById([FromRoute] Guid deviceId)
8081
public async Task<IActionResult> EditDevice([FromRoute] Guid deviceId, [FromBody] HubEditRequest body, [FromServices] IDeviceUpdateService updateService)
8182
{
8283
var device = await _db.Devices.FirstOrDefaultAsync(x => x.OwnerId == CurrentUser.Id && x.Id == deviceId);
83-
if (device == null) return Problem(DeviceError.DeviceNotFound);
84+
if (device == null) return Problem(HubError.HubNotFound);
8485

8586
device.Name = body.Name;
8687
await _db.SaveChangesAsync();
@@ -105,7 +106,7 @@ public async Task<IActionResult> EditDevice([FromRoute] Guid deviceId, [FromBody
105106
public async Task<IActionResult> RegenerateDeviceToken([FromRoute] Guid deviceId)
106107
{
107108
var device = await _db.Devices.FirstOrDefaultAsync(x => x.OwnerId == CurrentUser.Id && x.Id == deviceId);
108-
if (device == null) return Problem(DeviceError.DeviceNotFound);
109+
if (device == null) return Problem(HubError.HubNotFound);
109110

110111
device.Token = CryptoUtils.RandomString(256);
111112

@@ -130,7 +131,7 @@ public async Task<IActionResult> RegenerateDeviceToken([FromRoute] Guid deviceId
130131
public async Task<IActionResult> RemoveDevice([FromRoute] Guid deviceId, [FromServices] IDeviceUpdateService updateService)
131132
{
132133
var affected = await _db.Devices.Where(x => x.Id == deviceId).WhereIsUserOrPrivileged(x => x.Owner, CurrentUser).ExecuteDeleteAsync();
133-
if (affected <= 0) return Problem(DeviceError.DeviceNotFound);
134+
if (affected <= 0) return Problem(HubError.HubNotFound);
134135

135136
await updateService.UpdateDeviceForAllShared(CurrentUser.Id, deviceId, DeviceUpdateType.Deleted);
136137

@@ -162,6 +163,12 @@ public Task<IActionResult> CreateDevice([FromServices] IDeviceUpdateService upda
162163
[MapToApiVersion("2")]
163164
public async Task<IActionResult> CreateDeviceV2([FromBody] HubCreateRequest data, [FromServices] IDeviceUpdateService updateService)
164165
{
166+
int nDevices = await _db.Devices.CountAsync(d => d.OwnerId == CurrentUser.Id);
167+
if (nDevices >= HardLimits.MaxHubsPerUser)
168+
{
169+
return Problem(HubError.TooManyHubs);
170+
}
171+
165172
var device = new Common.OpenShockDb.Device
166173
{
167174
Id = Guid.CreateVersion7(),
@@ -193,7 +200,7 @@ public async Task<IActionResult> GetPairCode([FromRoute] Guid deviceId)
193200
var devicePairs = _redis.RedisCollection<DevicePair>();
194201

195202
var deviceExists = await _db.Devices.AnyAsync(x => x.Id == deviceId && x.OwnerId == CurrentUser.Id);
196-
if (!deviceExists) Problem(DeviceError.DeviceNotFound);
203+
if (!deviceExists) return Problem(HubError.HubNotFound);
197204
// replace with unlink?
198205
var existing = await devicePairs.FindByIdAsync(deviceId.ToString());
199206
if (existing != null) await devicePairs.DeleteAsync(existing);
@@ -230,15 +237,15 @@ public async Task<IActionResult> GetLiveControlGatewayInfo([FromRoute] Guid devi
230237
var deviceExistsAndYouHaveAccess = await _db.Devices.AnyAsync(x =>
231238
x.Id == deviceId && (x.OwnerId == CurrentUser.Id || x.Shockers.Any(y => y.UserShares.Any(
232239
z => z.SharedWithUserId == CurrentUser.Id))));
233-
if (!deviceExistsAndYouHaveAccess) return Problem(DeviceError.DeviceNotFound);
240+
if (!deviceExistsAndYouHaveAccess) return Problem(HubError.HubNotFound);
234241

235242
// Check if device is online
236243
var devicesOnline = _redis.RedisCollection<DeviceOnline>();
237244
var online = await devicesOnline.FindByIdAsync(deviceId.ToString());
238-
if (online == null) return Problem(DeviceError.DeviceIsNotOnline);
245+
if (online == null) return Problem(HubError.HubIsNotOnline);
239246

240247
// Check if device is connected to a LCG node
241-
if (online.Gateway == null) return Problem(DeviceError.DeviceNotConnectedToGateway);
248+
if (online.Gateway == null) return Problem(HubError.HubNotConnectedToGateway);
242249

243250
// Get LCG node info
244251
var lcgNodes = _redis.RedisCollection<LcgNode>();

API/Controller/Devices/GetShockers.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public sealed partial class DevicesController
2424
public async Task<IActionResult> GetShockers([FromRoute] Guid deviceId)
2525
{
2626
var deviceExists = await _db.Devices.AnyAsync(x => x.OwnerId == CurrentUser.Id && x.Id == deviceId);
27-
if (!deviceExists) return Problem(DeviceError.DeviceNotFound);
27+
if (!deviceExists) return Problem(HubError.HubNotFound);
2828

2929
var shockers = _db.Shockers
3030
.Where(x => x.DeviceId == deviceId)

API/Controller/Shockers/EditShocker.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public async Task<IActionResult> EditShocker(
3232
[FromServices] IDeviceUpdateService deviceUpdateService)
3333
{
3434
var device = await _db.Devices.AnyAsync(x => x.OwnerId == CurrentUser.Id && x.Id == body.Device);
35-
if (!device) return Problem(DeviceError.DeviceNotFound);
35+
if (!device) return Problem(HubError.HubNotFound);
3636

3737
var shocker = await _db.Shockers.FirstOrDefaultAsync(x => x.Device.OwnerId == CurrentUser.Id && x.Id == shockerId);
3838
if (shocker == null) return Problem(ShockerError.ShockerNotFound);

API/Controller/Shockers/RegisterShocker.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using OpenShock.API.Models.Requests;
66
using OpenShock.API.Services;
77
using OpenShock.Common.Authentication.Attributes;
8+
using OpenShock.Common.Constants;
89
using OpenShock.Common.Errors;
910
using OpenShock.Common.Models;
1011
using OpenShock.Common.OpenShockDb;
@@ -32,10 +33,10 @@ public async Task<IActionResult> RegisterShocker(
3233
{
3334
var device = await _db.Devices.Where(x => x.OwnerId == CurrentUser.Id && x.Id == body.Device)
3435
.Select(x => x.Id).FirstOrDefaultAsync();
35-
if (device == Guid.Empty) return Problem(DeviceError.DeviceNotFound);
36+
if (device == Guid.Empty) return Problem(HubError.HubNotFound);
3637
var shockerCount = await _db.Shockers.CountAsync(x => x.DeviceId == body.Device);
3738

38-
if (shockerCount >= 11) return Problem(DeviceError.TooManyShockers);
39+
if (shockerCount >= HardLimits.MaxShockersPerHub) return Problem(HubError.TooManyShockers);
3940

4041
var shocker = new Shocker
4142
{

Common/Constants/HardLimits.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ public static class HardLimits
4646
public const int ShockerControlLogCustomNameMaxLength = 64;
4747

4848
public const int CreateShareRequestMaxShockers = 128;
49-
49+
50+
public const int MaxHubsPerUser = 4;
51+
public const int MaxShockersPerHub = 11;
5052
public const int MaxShockerControlLogsPerUser = 2048;
5153

5254
// Don't allow any firmware prior to 2024.

Common/Errors/DeviceError.cs

Lines changed: 0 additions & 14 deletions
This file was deleted.

Common/Errors/HubError.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.Net;
2+
using OpenShock.Common.Constants;
3+
using OpenShock.Common.Problems;
4+
5+
namespace OpenShock.Common.Errors;
6+
7+
public static class HubError
8+
{
9+
public static OpenShockProblem HubNotFound => new("Hub.NotFound", "Hub not found", HttpStatusCode.NotFound);
10+
public static OpenShockProblem HubIsNotOnline => new("Hub.NotOnline", "Hub is not online", HttpStatusCode.NotFound);
11+
public static OpenShockProblem HubNotConnectedToGateway => new("Hub.NotConnectedToGateway", "Hub is not connected to a gateway", HttpStatusCode.PreconditionFailed, "Hub is online but not connected to a LCG node, you might need to upgrade your firmware to use this feature");
12+
13+
public static OpenShockProblem TooManyHubs => new("Hub.TooManyHubs", "You have too many hubs", HttpStatusCode.Conflict, $"You have reached the maximum number of shockers for this hub ({HardLimits.MaxHubsPerUser})");
14+
public static OpenShockProblem TooManyShockers => new("Hub.TooManyShockers", "Hub has too many shockers", HttpStatusCode.BadRequest, $"You have reached the maximum number of shockers for this hub ({HardLimits.MaxShockersPerHub})");
15+
16+
}

0 commit comments

Comments
 (0)