mirror of
https://github.com/bitwarden/server.git
synced 2025-05-23 12:31:06 -05:00
apikey apis for orgs
This commit is contained in:
parent
6922cff638
commit
42b104bc8f
@ -378,5 +378,72 @@ namespace Bit.Api.Controllers
|
|||||||
model.Users.Where(u => !u.Deleted).Select(u => u.ToImportedOrganizationUser()),
|
model.Users.Where(u => !u.Deleted).Select(u => u.ToImportedOrganizationUser()),
|
||||||
model.Users.Where(u => u.Deleted).Select(u => u.ExternalId));
|
model.Users.Where(u => u.Deleted).Select(u => u.ExternalId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("{id}/api-key")]
|
||||||
|
public async Task<ApiKeyResponseModel> ApiKey(string id, [FromBody]ApiKeyRequestModel model)
|
||||||
|
{
|
||||||
|
var orgIdGuid = new Guid(id);
|
||||||
|
if(!_currentContext.OrganizationOwner(orgIdGuid))
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var organization = await _organizationRepository.GetByIdAsync(orgIdGuid);
|
||||||
|
if(organization == null)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await _userService.GetUserByPrincipalAsync(User);
|
||||||
|
if(user == null)
|
||||||
|
{
|
||||||
|
throw new UnauthorizedAccessException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!await _userService.CheckPasswordAsync(user, model.MasterPasswordHash))
|
||||||
|
{
|
||||||
|
await Task.Delay(2000);
|
||||||
|
throw new BadRequestException("MasterPasswordHash", "Invalid password.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var response = new ApiKeyResponseModel(organization);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("{id}/rotate-api-key")]
|
||||||
|
public async Task<ApiKeyResponseModel> RotateApiKey(string id, [FromBody]ApiKeyRequestModel model)
|
||||||
|
{
|
||||||
|
var orgIdGuid = new Guid(id);
|
||||||
|
if(!_currentContext.OrganizationOwner(orgIdGuid))
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var organization = await _organizationRepository.GetByIdAsync(orgIdGuid);
|
||||||
|
if(organization == null)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await _userService.GetUserByPrincipalAsync(User);
|
||||||
|
if(user == null)
|
||||||
|
{
|
||||||
|
throw new UnauthorizedAccessException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!await _userService.CheckPasswordAsync(user, model.MasterPasswordHash))
|
||||||
|
{
|
||||||
|
await Task.Delay(2000);
|
||||||
|
throw new BadRequestException("MasterPasswordHash", "Invalid password.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _organizationService.RotateApiKeyAsync(organization);
|
||||||
|
var response = new ApiKeyResponseModel(organization);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
src/Core/Models/Api/Request/ApiKeyRequestModel.cs
Normal file
10
src/Core/Models/Api/Request/ApiKeyRequestModel.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Bit.Core.Models.Api
|
||||||
|
{
|
||||||
|
public class ApiKeyRequestModel
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string MasterPasswordHash { get; set; }
|
||||||
|
}
|
||||||
|
}
|
20
src/Core/Models/Api/Response/ApiKeyResponseModel.cs
Normal file
20
src/Core/Models/Api/Response/ApiKeyResponseModel.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using Bit.Core.Models.Table;
|
||||||
|
|
||||||
|
namespace Bit.Core.Models.Api
|
||||||
|
{
|
||||||
|
public class ApiKeyResponseModel : ResponseModel
|
||||||
|
{
|
||||||
|
public ApiKeyResponseModel(Organization organization, string obj = "apiKey")
|
||||||
|
: base(obj)
|
||||||
|
{
|
||||||
|
if(organization == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(organization));
|
||||||
|
}
|
||||||
|
ApiKey = organization.ApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ApiKey { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -43,5 +43,6 @@ namespace Bit.Core.Services
|
|||||||
Task<OrganizationLicense> GenerateLicenseAsync(Organization organization, Guid installationId);
|
Task<OrganizationLicense> GenerateLicenseAsync(Organization organization, Guid installationId);
|
||||||
Task ImportAsync(Guid organizationId, Guid importingUserId, IEnumerable<ImportedGroup> groups,
|
Task ImportAsync(Guid organizationId, Guid importingUserId, IEnumerable<ImportedGroup> groups,
|
||||||
IEnumerable<ImportedOrganizationUser> newUsers, IEnumerable<string> removeUserExternalIds);
|
IEnumerable<ImportedOrganizationUser> newUsers, IEnumerable<string> removeUserExternalIds);
|
||||||
|
Task RotateApiKeyAsync(Organization organization);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1341,6 +1341,13 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task RotateApiKeyAsync(Organization organization)
|
||||||
|
{
|
||||||
|
organization.ApiKey = CoreHelpers.SecureRandomString(30);
|
||||||
|
organization.RevisionDate = DateTime.UtcNow;
|
||||||
|
await ReplaceAndUpdateCache(organization);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task UpdateUsersAsync(Group group, HashSet<string> groupUsers,
|
private async Task UpdateUsersAsync(Group group, HashSet<string> groupUsers,
|
||||||
Dictionary<string, Guid> existingUsersIdDict, HashSet<Guid> existingUsers = null)
|
Dictionary<string, Guid> existingUsersIdDict, HashSet<Guid> existingUsers = null)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user