Updating initial Location crud endpoints to be global & restricted to SUPER role

This commit is contained in:
hz 2026-01-20 17:13:12 -06:00
parent eb34e6692f
commit cdeea60e52
5 changed files with 7 additions and 35 deletions

View File

@ -2,7 +2,6 @@ using LocationsApi.Models;
using LocationsApi.Services; using LocationsApi.Services;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
namespace LocationsApi.Controllers; namespace LocationsApi.Controllers;
@ -24,13 +23,8 @@ public class LocationsController : ControllerBase
if (string.IsNullOrWhiteSpace(req.Name)) if (string.IsNullOrWhiteSpace(req.Name))
return BadRequest("Name required"); return BadRequest("Name required");
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (string.IsNullOrWhiteSpace(userId))
return Unauthorized();
var location = new Location var location = new Location
{ {
OwnerUserId = userId,
Name = req.Name.Trim(), Name = req.Name.Trim(),
CreatedUtc = DateTime.UtcNow CreatedUtc = DateTime.UtcNow
}; };
@ -40,14 +34,10 @@ public class LocationsController : ControllerBase
} }
[HttpGet] [HttpGet]
[Authorize(Roles = "USER,SUPER")] [Authorize(Roles = "SUPER")]
public async Task<IActionResult> ListMine() public async Task<IActionResult> ListMine()
{ {
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var locations = await _locations.GetAllAsync();
if (string.IsNullOrWhiteSpace(userId))
return Unauthorized();
var locations = await _locations.GetForOwnerAsync(userId);
return Ok(locations); return Ok(locations);
} }
@ -55,12 +45,7 @@ public class LocationsController : ControllerBase
[Authorize(Roles = "SUPER")] [Authorize(Roles = "SUPER")]
public async Task<IActionResult> Delete(string id) public async Task<IActionResult> Delete(string id)
{ {
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var deleted = await _locations.DeleteAsync(id);
if (string.IsNullOrWhiteSpace(userId))
return Unauthorized();
var allowAnyOwner = User.IsInRole("SUPER");
var deleted = await _locations.DeleteForOwnerAsync(id, userId, allowAnyOwner);
if (!deleted) if (!deleted)
return NotFound(); return NotFound();

View File

@ -22,7 +22,6 @@ Stored documents (MongoDB)
```json ```json
{ {
"id": "string (ObjectId)", "id": "string (ObjectId)",
"ownerUserId": "string",
"name": "string", "name": "string",
"createdUtc": "string (ISO-8601 datetime)" "createdUtc": "string (ISO-8601 datetime)"
} }

View File

@ -9,8 +9,6 @@ public class Location
[BsonRepresentation(BsonType.ObjectId)] [BsonRepresentation(BsonType.ObjectId)]
public string? Id { get; set; } public string? Id { get; set; }
public string OwnerUserId { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
public DateTime CreatedUtc { get; set; } = DateTime.UtcNow; public DateTime CreatedUtc { get; set; } = DateTime.UtcNow;

View File

@ -5,6 +5,6 @@ See `DOCUMENTS.md` for request payloads and stored document shapes.
## Endpoints ## Endpoints
- `POST /api/locations` Create a location (SUPER only). - `POST /api/locations` Create a location (SUPER only).
- `GET /api/locations` List locations for the current user. - `GET /api/locations` List all locations (SUPER only).
- `DELETE /api/locations/{id}` Delete a location (SUPER only). - `DELETE /api/locations/{id}` Delete a location (SUPER only).
- `PUT /api/locations/{id}` Update a location name (SUPER only). - `PUT /api/locations/{id}` Update a location name (SUPER only).

View File

@ -15,26 +15,16 @@ public class LocationStore
var db = client.GetDatabase(dbName); var db = client.GetDatabase(dbName);
_col = db.GetCollection<Location>("Locations"); _col = db.GetCollection<Location>("Locations");
var ownerIndex = Builders<Location>.IndexKeys.Ascending(l => l.OwnerUserId);
_col.Indexes.CreateOne(new CreateIndexModel<Location>(ownerIndex));
} }
public Task CreateAsync(Location location) => _col.InsertOneAsync(location); public Task CreateAsync(Location location) => _col.InsertOneAsync(location);
public Task<List<Location>> GetForOwnerAsync(string ownerUserId) => public Task<List<Location>> GetAllAsync() =>
_col.Find(l => l.OwnerUserId == ownerUserId).ToListAsync(); _col.Find(Builders<Location>.Filter.Empty).ToListAsync();
public async Task<bool> DeleteForOwnerAsync(string id, string ownerUserId, bool allowAnyOwner) public async Task<bool> DeleteAsync(string id)
{ {
var filter = Builders<Location>.Filter.Eq(l => l.Id, id); var filter = Builders<Location>.Filter.Eq(l => l.Id, id);
if (!allowAnyOwner)
{
filter = Builders<Location>.Filter.And(
filter,
Builders<Location>.Filter.Eq(l => l.OwnerUserId, ownerUserId)
);
}
var result = await _col.DeleteOneAsync(filter); var result = await _col.DeleteOneAsync(filter);
return result.DeletedCount > 0; return result.DeletedCount > 0;
} }