1
0
mirror of https://github.com/bitwarden/server synced 2026-01-01 16:13:33 +00:00

[PM-25182] Improve swagger OperationIDs: Part 1 (#6229)

* Improve swagger OperationIDs: Part 1

* Fix tests and fmt

* Improve docs and add more tests

* Fmt

* Improve Swagger OperationIDs for Auth

* Fix review feedback

* Use generic getcustomattributes

* Format

* replace swaggerexclude by split+obsolete

* Format

* Some remaining excludes
This commit is contained in:
Daniel García
2025-09-02 18:30:53 +02:00
committed by GitHub
parent cb1db262ca
commit a180317509
22 changed files with 583 additions and 55 deletions

View File

@@ -344,7 +344,6 @@ public class AccountsController : Controller
}
[HttpPut("profile")]
[HttpPost("profile")]
public async Task<ProfileResponseModel> PutProfile([FromBody] UpdateProfileRequestModel model)
{
var user = await _userService.GetUserByPrincipalAsync(User);
@@ -363,8 +362,14 @@ public class AccountsController : Controller
return response;
}
[HttpPost("profile")]
[Obsolete("This endpoint is deprecated. Use PUT /profile instead.")]
public async Task<ProfileResponseModel> PostProfile([FromBody] UpdateProfileRequestModel model)
{
return await PutProfile(model);
}
[HttpPut("avatar")]
[HttpPost("avatar")]
public async Task<ProfileResponseModel> PutAvatar([FromBody] UpdateAvatarRequestModel model)
{
var user = await _userService.GetUserByPrincipalAsync(User);
@@ -382,6 +387,13 @@ public class AccountsController : Controller
return response;
}
[HttpPost("avatar")]
[Obsolete("This endpoint is deprecated. Use PUT /avatar instead.")]
public async Task<ProfileResponseModel> PostAvatar([FromBody] UpdateAvatarRequestModel model)
{
return await PutAvatar(model);
}
[HttpGet("revision-date")]
public async Task<long?> GetAccountRevisionDate()
{
@@ -430,7 +442,6 @@ public class AccountsController : Controller
}
[HttpDelete]
[HttpPost("delete")]
public async Task Delete([FromBody] SecretVerificationRequestModel model)
{
var user = await _userService.GetUserByPrincipalAsync(User);
@@ -467,6 +478,13 @@ public class AccountsController : Controller
throw new BadRequestException(ModelState);
}
[HttpPost("delete")]
[Obsolete("This endpoint is deprecated. Use DELETE / instead.")]
public async Task PostDelete([FromBody] SecretVerificationRequestModel model)
{
await Delete(model);
}
[AllowAnonymous]
[HttpPost("delete-recover")]
public async Task PostDeleteRecover([FromBody] DeleteRecoverRequestModel model)
@@ -638,7 +656,6 @@ public class AccountsController : Controller
await _twoFactorEmailService.SendNewDeviceVerificationEmailAsync(user);
}
[HttpPost("verify-devices")]
[HttpPut("verify-devices")]
public async Task SetUserVerifyDevicesAsync([FromBody] SetVerifyDevicesRequestModel request)
{
@@ -654,6 +671,13 @@ public class AccountsController : Controller
await _userService.SaveUserAsync(user);
}
[HttpPost("verify-devices")]
[Obsolete("This endpoint is deprecated. Use PUT /verify-devices instead.")]
public async Task PostSetUserVerifyDevicesAsync([FromBody] SetVerifyDevicesRequestModel request)
{
await SetUserVerifyDevicesAsync(request);
}
private async Task<IEnumerable<Guid>> GetOrganizationIdsClaimingUserAsync(Guid userId)
{
var organizationsClaimingUser = await _userService.GetOrganizationsClaimingUserAsync(userId);

View File

@@ -31,7 +31,7 @@ public class AuthRequestsController(
private readonly IAuthRequestService _authRequestService = authRequestService;
[HttpGet("")]
public async Task<ListResponseModel<AuthRequestResponseModel>> Get()
public async Task<ListResponseModel<AuthRequestResponseModel>> GetAll()
{
var userId = _userService.GetProperUserId(User).Value;
var authRequests = await _authRequestRepository.GetManyByUserIdAsync(userId);

View File

@@ -79,7 +79,6 @@ public class EmergencyAccessController : Controller
}
[HttpPut("{id}")]
[HttpPost("{id}")]
public async Task Put(Guid id, [FromBody] EmergencyAccessUpdateRequestModel model)
{
var emergencyAccess = await _emergencyAccessRepository.GetByIdAsync(id);
@@ -92,14 +91,27 @@ public class EmergencyAccessController : Controller
await _emergencyAccessService.SaveAsync(model.ToEmergencyAccess(emergencyAccess), user);
}
[HttpPost("{id}")]
[Obsolete("This endpoint is deprecated. Use PUT /{id} instead.")]
public async Task Post(Guid id, [FromBody] EmergencyAccessUpdateRequestModel model)
{
await Put(id, model);
}
[HttpDelete("{id}")]
[HttpPost("{id}/delete")]
public async Task Delete(Guid id)
{
var userId = _userService.GetProperUserId(User);
await _emergencyAccessService.DeleteAsync(id, userId.Value);
}
[HttpPost("{id}/delete")]
[Obsolete("This endpoint is deprecated. Use DELETE /{id} instead.")]
public async Task PostDelete(Guid id)
{
await Delete(id);
}
[HttpPost("invite")]
public async Task Invite([FromBody] EmergencyAccessInviteRequestModel model)
{
@@ -136,7 +148,7 @@ public class EmergencyAccessController : Controller
}
[HttpPost("{id}/approve")]
public async Task Accept(Guid id)
public async Task Approve(Guid id)
{
var user = await _userService.GetUserByPrincipalAsync(User);
await _emergencyAccessService.ApproveAsync(id, user);

View File

@@ -110,7 +110,6 @@ public class TwoFactorController : Controller
}
[HttpPut("authenticator")]
[HttpPost("authenticator")]
public async Task<TwoFactorAuthenticatorResponseModel> PutAuthenticator(
[FromBody] UpdateTwoFactorAuthenticatorRequestModel model)
{
@@ -133,6 +132,14 @@ public class TwoFactorController : Controller
return response;
}
[HttpPost("authenticator")]
[Obsolete("This endpoint is deprecated. Use PUT /authenticator instead.")]
public async Task<TwoFactorAuthenticatorResponseModel> PostAuthenticator(
[FromBody] UpdateTwoFactorAuthenticatorRequestModel model)
{
return await PutAuthenticator(model);
}
[HttpDelete("authenticator")]
public async Task<TwoFactorProviderResponseModel> DisableAuthenticator(
[FromBody] TwoFactorAuthenticatorDisableRequestModel model)
@@ -157,7 +164,6 @@ public class TwoFactorController : Controller
}
[HttpPut("yubikey")]
[HttpPost("yubikey")]
public async Task<TwoFactorYubiKeyResponseModel> PutYubiKey([FromBody] UpdateTwoFactorYubicoOtpRequestModel model)
{
var user = await CheckAsync(model, true);
@@ -174,6 +180,13 @@ public class TwoFactorController : Controller
return response;
}
[HttpPost("yubikey")]
[Obsolete("This endpoint is deprecated. Use PUT /yubikey instead.")]
public async Task<TwoFactorYubiKeyResponseModel> PostYubiKey([FromBody] UpdateTwoFactorYubicoOtpRequestModel model)
{
return await PutYubiKey(model);
}
[HttpPost("get-duo")]
public async Task<TwoFactorDuoResponseModel> GetDuo([FromBody] SecretVerificationRequestModel model)
{
@@ -183,7 +196,6 @@ public class TwoFactorController : Controller
}
[HttpPut("duo")]
[HttpPost("duo")]
public async Task<TwoFactorDuoResponseModel> PutDuo([FromBody] UpdateTwoFactorDuoRequestModel model)
{
var user = await CheckAsync(model, true);
@@ -199,6 +211,13 @@ public class TwoFactorController : Controller
return response;
}
[HttpPost("duo")]
[Obsolete("This endpoint is deprecated. Use PUT /duo instead.")]
public async Task<TwoFactorDuoResponseModel> PostDuo([FromBody] UpdateTwoFactorDuoRequestModel model)
{
return await PutDuo(model);
}
[HttpPost("~/organizations/{id}/two-factor/get-duo")]
public async Task<TwoFactorDuoResponseModel> GetOrganizationDuo(string id,
[FromBody] SecretVerificationRequestModel model)
@@ -217,7 +236,6 @@ public class TwoFactorController : Controller
}
[HttpPut("~/organizations/{id}/two-factor/duo")]
[HttpPost("~/organizations/{id}/two-factor/duo")]
public async Task<TwoFactorDuoResponseModel> PutOrganizationDuo(string id,
[FromBody] UpdateTwoFactorDuoRequestModel model)
{
@@ -243,6 +261,14 @@ public class TwoFactorController : Controller
return response;
}
[HttpPost("~/organizations/{id}/two-factor/duo")]
[Obsolete("This endpoint is deprecated. Use PUT /organizations/{id}/two-factor/duo instead.")]
public async Task<TwoFactorDuoResponseModel> PostOrganizationDuo(string id,
[FromBody] UpdateTwoFactorDuoRequestModel model)
{
return await PutOrganizationDuo(id, model);
}
[HttpPost("get-webauthn")]
public async Task<TwoFactorWebAuthnResponseModel> GetWebAuthn([FromBody] SecretVerificationRequestModel model)
{
@@ -261,7 +287,6 @@ public class TwoFactorController : Controller
}
[HttpPut("webauthn")]
[HttpPost("webauthn")]
public async Task<TwoFactorWebAuthnResponseModel> PutWebAuthn([FromBody] TwoFactorWebAuthnRequestModel model)
{
var user = await CheckAsync(model, false);
@@ -277,6 +302,13 @@ public class TwoFactorController : Controller
return response;
}
[HttpPost("webauthn")]
[Obsolete("This endpoint is deprecated. Use PUT /webauthn instead.")]
public async Task<TwoFactorWebAuthnResponseModel> PostWebAuthn([FromBody] TwoFactorWebAuthnRequestModel model)
{
return await PutWebAuthn(model);
}
[HttpDelete("webauthn")]
public async Task<TwoFactorWebAuthnResponseModel> DeleteWebAuthn(
[FromBody] TwoFactorWebAuthnDeleteRequestModel model)
@@ -349,7 +381,6 @@ public class TwoFactorController : Controller
}
[HttpPut("email")]
[HttpPost("email")]
public async Task<TwoFactorEmailResponseModel> PutEmail([FromBody] UpdateTwoFactorEmailRequestModel model)
{
var user = await CheckAsync(model, false);
@@ -367,8 +398,14 @@ public class TwoFactorController : Controller
return response;
}
[HttpPost("email")]
[Obsolete("This endpoint is deprecated. Use PUT /email instead.")]
public async Task<TwoFactorEmailResponseModel> PostEmail([FromBody] UpdateTwoFactorEmailRequestModel model)
{
return await PutEmail(model);
}
[HttpPut("disable")]
[HttpPost("disable")]
public async Task<TwoFactorProviderResponseModel> PutDisable([FromBody] TwoFactorProviderRequestModel model)
{
var user = await CheckAsync(model, false);
@@ -377,8 +414,14 @@ public class TwoFactorController : Controller
return response;
}
[HttpPost("disable")]
[Obsolete("This endpoint is deprecated. Use PUT /disable instead.")]
public async Task<TwoFactorProviderResponseModel> PostDisable([FromBody] TwoFactorProviderRequestModel model)
{
return await PutDisable(model);
}
[HttpPut("~/organizations/{id}/two-factor/disable")]
[HttpPost("~/organizations/{id}/two-factor/disable")]
public async Task<TwoFactorProviderResponseModel> PutOrganizationDisable(string id,
[FromBody] TwoFactorProviderRequestModel model)
{
@@ -401,6 +444,14 @@ public class TwoFactorController : Controller
return response;
}
[HttpPost("~/organizations/{id}/two-factor/disable")]
[Obsolete("This endpoint is deprecated. Use PUT /organizations/{id}/two-factor/disable instead.")]
public async Task<TwoFactorProviderResponseModel> PostOrganizationDisable(string id,
[FromBody] TwoFactorProviderRequestModel model)
{
return await PutOrganizationDisable(id, model);
}
[HttpPost("get-recover")]
public async Task<TwoFactorRecoverResponseModel> GetRecover([FromBody] SecretVerificationRequestModel model)
{

View File

@@ -102,7 +102,7 @@ public class CollectionsController : Controller
}
[HttpGet("")]
public async Task<ListResponseModel<CollectionResponseModel>> Get(Guid orgId)
public async Task<ListResponseModel<CollectionResponseModel>> GetAll(Guid orgId)
{
IEnumerable<Collection> orgCollections;
@@ -173,7 +173,6 @@ public class CollectionsController : Controller
}
[HttpPut("{id}")]
[HttpPost("{id}")]
public async Task<CollectionResponseModel> Put(Guid orgId, Guid id, [FromBody] UpdateCollectionRequestModel model)
{
var collection = await _collectionRepository.GetByIdAsync(id);
@@ -198,6 +197,13 @@ public class CollectionsController : Controller
return new CollectionAccessDetailsResponseModel(collectionWithPermissions);
}
[HttpPost("{id}")]
[Obsolete("This endpoint is deprecated. Use PUT /{id} instead.")]
public async Task<CollectionResponseModel> Post(Guid orgId, Guid id, [FromBody] UpdateCollectionRequestModel model)
{
return await Put(orgId, id, model);
}
[HttpPost("bulk-access")]
public async Task PostBulkCollectionAccess(Guid orgId, [FromBody] BulkCollectionAccessRequestModel model)
{
@@ -222,7 +228,6 @@ public class CollectionsController : Controller
}
[HttpDelete("{id}")]
[HttpPost("{id}/delete")]
public async Task Delete(Guid orgId, Guid id)
{
var collection = await _collectionRepository.GetByIdAsync(id);
@@ -235,8 +240,14 @@ public class CollectionsController : Controller
await _deleteCollectionCommand.DeleteAsync(collection);
}
[HttpPost("{id}/delete")]
[Obsolete("This endpoint is deprecated. Use DELETE /{id} instead.")]
public async Task PostDelete(Guid orgId, Guid id)
{
await Delete(orgId, id);
}
[HttpDelete("")]
[HttpPost("delete")]
public async Task DeleteMany(Guid orgId, [FromBody] CollectionBulkDeleteRequestModel model)
{
var collections = await _collectionRepository.GetManyByManyIdsAsync(model.Ids);
@@ -248,4 +259,11 @@ public class CollectionsController : Controller
await _deleteCollectionCommand.DeleteManyAsync(collections);
}
[HttpPost("delete")]
[Obsolete("This endpoint is deprecated. Use DELETE / instead.")]
public async Task PostDeleteMany(Guid orgId, [FromBody] CollectionBulkDeleteRequestModel model)
{
await DeleteMany(orgId, model);
}
}

View File

@@ -75,7 +75,7 @@ public class DevicesController : Controller
}
[HttpGet("")]
public async Task<ListResponseModel<DeviceAuthRequestResponseModel>> Get()
public async Task<ListResponseModel<DeviceAuthRequestResponseModel>> GetAll()
{
var devicesWithPendingAuthData = await _deviceRepository.GetManyByUserIdWithDeviceAuth(_userService.GetProperUserId(User).Value);
@@ -99,7 +99,6 @@ public class DevicesController : Controller
}
[HttpPut("{id}")]
[HttpPost("{id}")]
public async Task<DeviceResponseModel> Put(string id, [FromBody] DeviceRequestModel model)
{
var device = await _deviceRepository.GetByIdAsync(new Guid(id), _userService.GetProperUserId(User).Value);
@@ -114,8 +113,14 @@ public class DevicesController : Controller
return response;
}
[HttpPost("{id}")]
[Obsolete("This endpoint is deprecated. Use PUT /{id} instead.")]
public async Task<DeviceResponseModel> Post(string id, [FromBody] DeviceRequestModel model)
{
return await Put(id, model);
}
[HttpPut("{identifier}/keys")]
[HttpPost("{identifier}/keys")]
public async Task<DeviceResponseModel> PutKeys(string identifier, [FromBody] DeviceKeysRequestModel model)
{
var device = await _deviceRepository.GetByIdentifierAsync(identifier, _userService.GetProperUserId(User).Value);
@@ -130,6 +135,13 @@ public class DevicesController : Controller
return response;
}
[HttpPost("{identifier}/keys")]
[Obsolete("This endpoint is deprecated. Use PUT /{identifier}/keys instead.")]
public async Task<DeviceResponseModel> PostKeys(string identifier, [FromBody] DeviceKeysRequestModel model)
{
return await PutKeys(identifier, model);
}
[HttpPost("{identifier}/retrieve-keys")]
[Obsolete("This endpoint is deprecated. The keys are on the regular device GET endpoints now.")]
public async Task<ProtectedDeviceResponseModel> GetDeviceKeys(string identifier)
@@ -187,7 +199,6 @@ public class DevicesController : Controller
}
[HttpPut("identifier/{identifier}/token")]
[HttpPost("identifier/{identifier}/token")]
public async Task PutToken(string identifier, [FromBody] DeviceTokenRequestModel model)
{
var device = await _deviceRepository.GetByIdentifierAsync(identifier, _userService.GetProperUserId(User).Value);
@@ -199,8 +210,14 @@ public class DevicesController : Controller
await _deviceService.SaveAsync(model.ToDevice(device));
}
[HttpPost("identifier/{identifier}/token")]
[Obsolete("This endpoint is deprecated. Use PUT /identifier/{identifier}/token instead.")]
public async Task PostToken(string identifier, [FromBody] DeviceTokenRequestModel model)
{
await PutToken(identifier, model);
}
[HttpPut("identifier/{identifier}/web-push-auth")]
[HttpPost("identifier/{identifier}/web-push-auth")]
public async Task PutWebPushAuth(string identifier, [FromBody] WebPushAuthRequestModel model)
{
var device = await _deviceRepository.GetByIdentifierAsync(identifier, _userService.GetProperUserId(User).Value);
@@ -216,9 +233,15 @@ public class DevicesController : Controller
);
}
[HttpPost("identifier/{identifier}/web-push-auth")]
[Obsolete("This endpoint is deprecated. Use PUT /identifier/{identifier}/web-push-auth instead.")]
public async Task PostWebPushAuth(string identifier, [FromBody] WebPushAuthRequestModel model)
{
await PutWebPushAuth(identifier, model);
}
[AllowAnonymous]
[HttpPut("identifier/{identifier}/clear-token")]
[HttpPost("identifier/{identifier}/clear-token")]
public async Task PutClearToken(string identifier)
{
var device = await _deviceRepository.GetByIdentifierAsync(identifier);
@@ -230,8 +253,15 @@ public class DevicesController : Controller
await _deviceService.ClearTokenAsync(device);
}
[AllowAnonymous]
[HttpPost("identifier/{identifier}/clear-token")]
[Obsolete("This endpoint is deprecated. Use PUT /identifier/{identifier}/clear-token instead.")]
public async Task PostClearToken(string identifier)
{
await PutClearToken(identifier);
}
[HttpDelete("{id}")]
[HttpPost("{id}/deactivate")]
public async Task Deactivate(string id)
{
var device = await _deviceRepository.GetByIdAsync(new Guid(id), _userService.GetProperUserId(User).Value);
@@ -243,17 +273,24 @@ public class DevicesController : Controller
await _deviceService.DeactivateAsync(device);
}
[HttpPost("{id}/deactivate")]
[Obsolete("This endpoint is deprecated. Use DELETE /{id} instead.")]
public async Task PostDeactivate(string id)
{
await Deactivate(id);
}
[AllowAnonymous]
[HttpGet("knowndevice")]
public async Task<bool> GetByIdentifierQuery(
[Required][FromHeader(Name = "X-Request-Email")] string Email,
[Required][FromHeader(Name = "X-Device-Identifier")] string DeviceIdentifier)
=> await GetByIdentifier(CoreHelpers.Base64UrlDecodeString(Email), DeviceIdentifier);
=> await GetByEmailAndIdentifier(CoreHelpers.Base64UrlDecodeString(Email), DeviceIdentifier);
[Obsolete("Path is deprecated due to encoding issues, use /knowndevice instead.")]
[AllowAnonymous]
[HttpGet("knowndevice/{email}/{identifier}")]
public async Task<bool> GetByIdentifier(string email, string identifier)
public async Task<bool> GetByEmailAndIdentifier(string email, string identifier)
{
if (string.IsNullOrWhiteSpace(email) || string.IsNullOrWhiteSpace(identifier))
{

View File

@@ -6,12 +6,18 @@ namespace Bit.Api.Controllers;
public class InfoController : Controller
{
[HttpGet("~/alive")]
[HttpGet("~/now")]
public DateTime GetAlive()
{
return DateTime.UtcNow;
}
[HttpGet("~/now")]
[Obsolete("This endpoint is deprecated. Use GET /alive instead.")]
public DateTime GetNow()
{
return GetAlive();
}
[HttpGet("~/version")]
public JsonResult GetVersion()
{

View File

@@ -32,7 +32,6 @@ public class SettingsController : Controller
}
[HttpPut("domains")]
[HttpPost("domains")]
public async Task<DomainsResponseModel> PutDomains([FromBody] UpdateDomainsRequestModel model)
{
var user = await _userService.GetUserByPrincipalAsync(User);
@@ -46,4 +45,11 @@ public class SettingsController : Controller
var response = new DomainsResponseModel(user);
return response;
}
[HttpPost("domains")]
[Obsolete("This endpoint is deprecated. Use PUT /domains instead.")]
public async Task<DomainsResponseModel> PostDomains([FromBody] UpdateDomainsRequestModel model)
{
return await PutDomains(model);
}
}

View File

@@ -82,15 +82,7 @@ public static class ServiceCollectionExtensions
config.DescribeAllParametersInCamelCase();
// config.UseReferencedDefinitionsForEnums();
config.SchemaFilter<EnumSchemaFilter>();
config.SchemaFilter<EncryptedStringSchemaFilter>();
// These two filters require debug symbols/git, so only add them in development mode
if (environment.IsDevelopment())
{
config.DocumentFilter<GitCommitDocumentFilter>();
config.OperationFilter<SourceFileLineOperationFilter>();
}
config.InitializeSwaggerFilters(environment);
var apiFilePath = Path.Combine(AppContext.BaseDirectory, "Api.xml");
config.IncludeXmlComments(apiFilePath, true);