mirror of
https://github.com/bitwarden/server.git
synced 2025-07-01 08:02:49 -05:00
Move request/response models (#1754)
This commit is contained in:
@ -2,8 +2,6 @@
|
||||
using Bit.Core;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Models.Api.Request.Accounts;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Table;
|
||||
@ -17,6 +15,9 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Request.Accounts;
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Core.Enums.Provider;
|
||||
|
||||
namespace Bit.Api.Controllers
|
||||
|
@ -4,7 +4,6 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Context;
|
||||
@ -15,6 +14,10 @@ using Bit.Core.Models.Table;
|
||||
using Bit.Core.Settings;
|
||||
using Core.Models.Data;
|
||||
using Azure.Messaging.EventGrid;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Request.Accounts;
|
||||
using Bit.Api.Models.Request.Organizations;
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Core.Models.Data;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
@ -600,8 +603,8 @@ namespace Bit.Api.Controllers
|
||||
throw new BadRequestException($"Max file size is {CipherService.MAX_FILE_SIZE_READABLE}.");
|
||||
}
|
||||
|
||||
|
||||
var (attachmentId, uploadUrl) = await _cipherService.CreateAttachmentForDelayedUploadAsync(cipher, request, userId);
|
||||
var (attachmentId, uploadUrl) = await _cipherService.CreateAttachmentForDelayedUploadAsync(cipher,
|
||||
request.Key, request.FileName, request.FileSize, request.AdminRequest, userId);
|
||||
return new AttachmentUploadDataResponseModel
|
||||
{
|
||||
AttachmentId = attachmentId,
|
||||
@ -713,7 +716,8 @@ namespace Bit.Api.Controllers
|
||||
{
|
||||
var userId = _userService.GetProperUserId(User).Value;
|
||||
var cipher = await _cipherRepository.GetByIdAsync(new Guid(id), userId);
|
||||
return await _cipherService.GetAttachmentDownloadDataAsync(cipher, attachmentId);
|
||||
var result = await _cipherService.GetAttachmentDownloadDataAsync(cipher, attachmentId);
|
||||
return new AttachmentResponseModel(result.Id, result.Data, result.Cipher, _globalSettings);
|
||||
}
|
||||
|
||||
[HttpPost("{id}/attachment/{attachmentId}/share")]
|
||||
|
@ -4,12 +4,13 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Models.Table;
|
||||
using System.Collections.Generic;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Response;
|
||||
|
||||
namespace Bit.Api.Controllers
|
||||
{
|
||||
|
@ -2,10 +2,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Response;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Services;
|
||||
|
@ -1,13 +1,14 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Request.Organizations;
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Models.Api.Request;
|
||||
using Bit.Core.Models.Api.Response;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
@ -20,15 +21,18 @@ namespace Bit.Api.Controllers
|
||||
private readonly IUserService _userService;
|
||||
private readonly IEmergencyAccessRepository _emergencyAccessRepository;
|
||||
private readonly IEmergencyAccessService _emergencyAccessService;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
|
||||
public EmergencyAccessController(
|
||||
IUserService userService,
|
||||
IEmergencyAccessRepository emergencyAccessRepository,
|
||||
IEmergencyAccessService emergencyAccessService)
|
||||
IEmergencyAccessService emergencyAccessService,
|
||||
IGlobalSettings globalSettings)
|
||||
{
|
||||
_userService = userService;
|
||||
_emergencyAccessRepository = emergencyAccessRepository;
|
||||
_emergencyAccessService = emergencyAccessService;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
[HttpGet("trusted")]
|
||||
@ -161,14 +165,17 @@ namespace Bit.Api.Controllers
|
||||
public async Task<EmergencyAccessViewResponseModel> ViewCiphers(string id)
|
||||
{
|
||||
var user = await _userService.GetUserByPrincipalAsync(User);
|
||||
return await _emergencyAccessService.ViewAsync(new Guid(id), user);
|
||||
var viewResult = await _emergencyAccessService.ViewAsync(new Guid(id), user);
|
||||
return new EmergencyAccessViewResponseModel(_globalSettings, viewResult.EmergencyAccess, viewResult.Ciphers);
|
||||
}
|
||||
|
||||
[HttpGet("{id}/{cipherId}/attachment/{attachmentId}")]
|
||||
public async Task<AttachmentResponseModel> GetAttachmentData(string id, string cipherId, string attachmentId)
|
||||
{
|
||||
var user = await _userService.GetUserByPrincipalAsync(User);
|
||||
return await _emergencyAccessService.GetAttachmentDownloadAsync(new Guid(id), cipherId, attachmentId, user);
|
||||
var result =
|
||||
await _emergencyAccessService.GetAttachmentDownloadAsync(new Guid(id), cipherId, attachmentId, user);
|
||||
return new AttachmentResponseModel(result.Id, result.Data, result.Cipher, _globalSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Response;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Models.Data;
|
||||
|
@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Response;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
|
||||
|
@ -4,11 +4,12 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Context;
|
||||
using System.Collections.Generic;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Response;
|
||||
|
||||
namespace Bit.Api.Controllers
|
||||
{
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Response;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Models.Api;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Utilities;
|
||||
|
@ -1,12 +1,10 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Models.Api;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Settings;
|
||||
using Stripe;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.Api.Controllers
|
||||
{
|
||||
|
@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request.Organizations;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Models.Api.Request;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
|
@ -4,11 +4,12 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Context;
|
||||
using System.Collections.Generic;
|
||||
using Bit.Api.Models.Request.Organizations;
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Data;
|
||||
@ -136,7 +137,7 @@ namespace Bit.Api.Controllers
|
||||
|
||||
var userId = _userService.GetProperUserId(User);
|
||||
var result = await _organizationService.InviteUsersAsync(orgGuidId, userId.Value,
|
||||
new (OrganizationUserInvite, string)[] { (new OrganizationUserInvite(model), null) });
|
||||
new (OrganizationUserInvite, string)[] { (new OrganizationUserInvite(model.ToData()), null) });
|
||||
}
|
||||
|
||||
[HttpPost("reinvite")]
|
||||
|
@ -1,16 +1,18 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Request.Accounts;
|
||||
using Bit.Api.Models.Request.Organizations;
|
||||
using Bit.Api.Models.Response;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Api.Utilities;
|
||||
using Bit.Core.Models.Api.Response;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Utilities;
|
||||
|
@ -1,10 +1,10 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Core.Models.Api;
|
||||
using System.Linq;
|
||||
using Bit.Core.Repositories;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Response;
|
||||
|
||||
namespace Bit.Api.Controllers
|
||||
{
|
||||
|
@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Response;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Context;
|
||||
|
@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request.Providers;
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Api.Models.Response.Providers;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Models.Api.Request;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
|
@ -2,10 +2,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request.Providers;
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Api.Models.Response.Providers;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Context;
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request.Providers;
|
||||
using Bit.Api.Models.Response.Providers;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
|
@ -1,14 +1,12 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Api;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Bit.Api.Utilities;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Core.Settings;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
@ -4,17 +4,17 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Models.Api.Response;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Context;
|
||||
using Azure.Messaging.EventGrid;
|
||||
using Bit.Api.Utilities;
|
||||
using System.Collections.Generic;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Core.Models.Table;
|
||||
using Newtonsoft.Json;
|
||||
using Bit.Core.Models.Data;
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Response;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Services;
|
||||
|
||||
namespace Bit.Api.Controllers
|
||||
|
@ -2,7 +2,6 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Enums;
|
||||
@ -10,6 +9,7 @@ using Bit.Core.Exceptions;
|
||||
using System.Linq;
|
||||
using Bit.Core.Models.Table;
|
||||
using System.Collections.Generic;
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Core.Enums.Provider;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Settings;
|
||||
|
@ -2,13 +2,16 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Enums;
|
||||
using System.Linq;
|
||||
using Bit.Api.Models.Request;
|
||||
using Bit.Api.Models.Request.Accounts;
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Api.Models.Response.TwoFactor;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Utilities;
|
||||
|
@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Api.Models.Response;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Api;
|
||||
|
||||
namespace Bit.Api.Controllers
|
||||
{
|
||||
|
21
src/Api/Models/CipherAttachmentModel.cs
Normal file
21
src/Api/Models/CipherAttachmentModel.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models
|
||||
{
|
||||
public class CipherAttachmentModel
|
||||
{
|
||||
public CipherAttachmentModel() { }
|
||||
|
||||
public CipherAttachmentModel(CipherAttachment.MetaData data)
|
||||
{
|
||||
FileName = data.FileName;
|
||||
Key = data.Key;
|
||||
}
|
||||
|
||||
[EncryptedStringLength(1000)]
|
||||
public string FileName { get; set; }
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Key { get; set; }
|
||||
}
|
||||
}
|
40
src/Api/Models/CipherCardModel.cs
Normal file
40
src/Api/Models/CipherCardModel.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models
|
||||
{
|
||||
public class CipherCardModel
|
||||
{
|
||||
public CipherCardModel() { }
|
||||
|
||||
public CipherCardModel(CipherCardData data)
|
||||
{
|
||||
CardholderName = data.CardholderName;
|
||||
Brand = data.Brand;
|
||||
Number = data.Number;
|
||||
ExpMonth = data.ExpMonth;
|
||||
ExpYear = data.ExpYear;
|
||||
Code = data.Code;
|
||||
}
|
||||
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string CardholderName { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Brand { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Number { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string ExpMonth { get; set; }
|
||||
[EncryptedString]
|
||||
[StringLength(1000)]
|
||||
public string ExpYear { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Code { get; set; }
|
||||
}
|
||||
}
|
37
src/Api/Models/CipherFieldModel.cs
Normal file
37
src/Api/Models/CipherFieldModel.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models
|
||||
{
|
||||
public class CipherFieldModel
|
||||
{
|
||||
public CipherFieldModel() { }
|
||||
|
||||
public CipherFieldModel(CipherFieldData data)
|
||||
{
|
||||
Type = data.Type;
|
||||
Name = data.Name;
|
||||
Value = data.Value;
|
||||
LinkedId = data.LinkedId ?? null;
|
||||
}
|
||||
|
||||
public FieldType Type { get; set; }
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Name { get; set; }
|
||||
[EncryptedStringLength(5000)]
|
||||
public string Value { get; set; }
|
||||
public int? LinkedId { get; set; }
|
||||
|
||||
public CipherFieldData ToCipherFieldData()
|
||||
{
|
||||
return new CipherFieldData
|
||||
{
|
||||
Type = Type,
|
||||
Name = Name,
|
||||
Value = Value,
|
||||
LinkedId = LinkedId ?? null,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
88
src/Api/Models/CipherIdentityModel.cs
Normal file
88
src/Api/Models/CipherIdentityModel.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models
|
||||
{
|
||||
public class CipherIdentityModel
|
||||
{
|
||||
public CipherIdentityModel() { }
|
||||
|
||||
public CipherIdentityModel(CipherIdentityData data)
|
||||
{
|
||||
Title = data.Title;
|
||||
FirstName = data.FirstName;
|
||||
MiddleName = data.MiddleName;
|
||||
LastName = data.LastName;
|
||||
Address1 = data.Address1;
|
||||
Address2 = data.Address2;
|
||||
Address3 = data.Address3;
|
||||
City = data.City;
|
||||
State = data.State;
|
||||
PostalCode = data.PostalCode;
|
||||
Country = data.Country;
|
||||
Company = data.Company;
|
||||
Email = data.Email;
|
||||
Phone = data.Phone;
|
||||
SSN = data.SSN;
|
||||
Username = data.Username;
|
||||
PassportNumber = data.PassportNumber;
|
||||
LicenseNumber = data.LicenseNumber;
|
||||
}
|
||||
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Title { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string FirstName { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string MiddleName { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string LastName { get; set; }
|
||||
[EncryptedString]
|
||||
[StringLength(1000)]
|
||||
public string Address1 { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Address2 { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Address3 { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string City { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string State { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string PostalCode { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Country { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Company { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Email { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Phone { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string SSN { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Username { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string PassportNumber { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string LicenseNumber { get; set; }
|
||||
}
|
||||
}
|
88
src/Api/Models/CipherLoginModel.cs
Normal file
88
src/Api/Models/CipherLoginModel.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models
|
||||
{
|
||||
public class CipherLoginModel
|
||||
{
|
||||
public CipherLoginModel() { }
|
||||
|
||||
public CipherLoginModel(CipherLoginData data)
|
||||
{
|
||||
Uris = data.Uris?.Select(u => new CipherLoginUriModel(u))?.ToList();
|
||||
if (!Uris?.Any() ?? true)
|
||||
{
|
||||
Uri = data.Uri;
|
||||
}
|
||||
|
||||
Username = data.Username;
|
||||
Password = data.Password;
|
||||
PasswordRevisionDate = data.PasswordRevisionDate;
|
||||
Totp = data.Totp;
|
||||
AutofillOnPageLoad = data.AutofillOnPageLoad;
|
||||
}
|
||||
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(10000)]
|
||||
public string Uri
|
||||
{
|
||||
get => Uris?.FirstOrDefault()?.Uri;
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Uris == null)
|
||||
{
|
||||
Uris = new List<CipherLoginUriModel>();
|
||||
}
|
||||
|
||||
Uris.Add(new CipherLoginUriModel(value));
|
||||
}
|
||||
}
|
||||
public List<CipherLoginUriModel> Uris { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Username { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(5000)]
|
||||
public string Password { get; set; }
|
||||
public DateTime? PasswordRevisionDate { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Totp { get; set; }
|
||||
public bool? AutofillOnPageLoad { get; set; }
|
||||
|
||||
public class CipherLoginUriModel
|
||||
{
|
||||
public CipherLoginUriModel() { }
|
||||
|
||||
public CipherLoginUriModel(string uri)
|
||||
{
|
||||
Uri = uri;
|
||||
}
|
||||
|
||||
public CipherLoginUriModel(CipherLoginData.CipherLoginUriData uri)
|
||||
{
|
||||
Uri = uri.Uri;
|
||||
Match = uri.Match;
|
||||
}
|
||||
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(10000)]
|
||||
public string Uri { get; set; }
|
||||
public UriMatchType? Match { get; set; } = null;
|
||||
|
||||
public CipherLoginData.CipherLoginUriData ToCipherLoginUriData()
|
||||
{
|
||||
return new CipherLoginData.CipherLoginUriData { Uri = Uri, Match = Match, };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
30
src/Api/Models/CipherPasswordHistoryModel.cs
Normal file
30
src/Api/Models/CipherPasswordHistoryModel.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models
|
||||
{
|
||||
public class CipherPasswordHistoryModel
|
||||
{
|
||||
public CipherPasswordHistoryModel() { }
|
||||
|
||||
public CipherPasswordHistoryModel(CipherPasswordHistoryData data)
|
||||
{
|
||||
Password = data.Password;
|
||||
LastUsedDate = data.LastUsedDate;
|
||||
}
|
||||
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(5000)]
|
||||
[Required]
|
||||
public string Password { get; set; }
|
||||
[Required]
|
||||
public DateTime? LastUsedDate { get; set; }
|
||||
|
||||
public CipherPasswordHistoryData ToCipherPasswordHistoryData()
|
||||
{
|
||||
return new CipherPasswordHistoryData { Password = Password, LastUsedDate = LastUsedDate.Value, };
|
||||
}
|
||||
}
|
||||
}
|
17
src/Api/Models/CipherSecureNoteModel.cs
Normal file
17
src/Api/Models/CipherSecureNoteModel.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
|
||||
namespace Bit.Api.Models
|
||||
{
|
||||
public class CipherSecureNoteModel
|
||||
{
|
||||
public CipherSecureNoteModel() { }
|
||||
|
||||
public CipherSecureNoteModel(CipherSecureNoteData data)
|
||||
{
|
||||
Type = data.Type;
|
||||
}
|
||||
|
||||
public SecureNoteType Type { get; set; }
|
||||
}
|
||||
}
|
20
src/Api/Models/Public/AssociationWithPermissionsBaseModel.cs
Normal file
20
src/Api/Models/Public/AssociationWithPermissionsBaseModel.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Public
|
||||
{
|
||||
public abstract class AssociationWithPermissionsBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The associated object's unique identifier.
|
||||
/// </summary>
|
||||
/// <example>bfbc8338-e329-4dc0-b0c9-317c2ebf1a09</example>
|
||||
[Required]
|
||||
public Guid? Id { get; set; }
|
||||
/// <summary>
|
||||
/// When true, the read only permission will not allow the user or group to make changes to items.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool? ReadOnly { get; set; }
|
||||
}
|
||||
}
|
14
src/Api/Models/Public/CollectionBaseModel.cs
Normal file
14
src/Api/Models/Public/CollectionBaseModel.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Public
|
||||
{
|
||||
public abstract class CollectionBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// External identifier for reference or linking this collection to another system.
|
||||
/// </summary>
|
||||
/// <example>external_id_123456</example>
|
||||
[StringLength(300)]
|
||||
public string ExternalId { get; set; }
|
||||
}
|
||||
}
|
27
src/Api/Models/Public/GroupBaseModel.cs
Normal file
27
src/Api/Models/Public/GroupBaseModel.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Public
|
||||
{
|
||||
public abstract class GroupBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the group.
|
||||
/// </summary>
|
||||
/// <example>Development Team</example>
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// Determines if this group can access all collections within the organization, or only the associated
|
||||
/// collections. If set to <c>true</c>, this option overrides any collection assignments.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool? AccessAll { get; set; }
|
||||
/// <summary>
|
||||
/// External identifier for reference or linking this group to another system, such as a user directory.
|
||||
/// </summary>
|
||||
/// <example>external_id_123456</example>
|
||||
[StringLength(300)]
|
||||
public string ExternalId { get; set; }
|
||||
}
|
||||
}
|
62
src/Api/Models/Public/MemberBaseModel.cs
Normal file
62
src/Api/Models/Public/MemberBaseModel.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Public
|
||||
{
|
||||
public abstract class MemberBaseModel
|
||||
{
|
||||
public MemberBaseModel() { }
|
||||
|
||||
public MemberBaseModel(OrganizationUser user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
Type = user.Type;
|
||||
AccessAll = user.AccessAll;
|
||||
ExternalId = user.ExternalId;
|
||||
ResetPasswordEnrolled = user.ResetPasswordKey != null;
|
||||
}
|
||||
|
||||
public MemberBaseModel(OrganizationUserUserDetails user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
Type = user.Type;
|
||||
AccessAll = user.AccessAll;
|
||||
ExternalId = user.ExternalId;
|
||||
ResetPasswordEnrolled = user.ResetPasswordKey != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The member's type (or role) within the organization.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public OrganizationUserType? Type { get; set; }
|
||||
/// <summary>
|
||||
/// Determines if this member can access all collections within the organization, or only the associated
|
||||
/// collections. If set to <c>true</c>, this option overrides any collection assignments.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool? AccessAll { get; set; }
|
||||
/// <summary>
|
||||
/// External identifier for reference or linking this member to another system, such as a user directory.
|
||||
/// </summary>
|
||||
/// <example>external_id_123456</example>
|
||||
[StringLength(300)]
|
||||
public string ExternalId { get; set; }
|
||||
/// <summary>
|
||||
/// Returns <c>true</c> if the member has enrolled in Password Reset assistance within the organization
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool ResetPasswordEnrolled { get; set; }
|
||||
}
|
||||
}
|
18
src/Api/Models/Public/PolicyBaseModel.cs
Normal file
18
src/Api/Models/Public/PolicyBaseModel.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Public
|
||||
{
|
||||
public abstract class PolicyBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if this policy is enabled and enforced.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool? Enabled { get; set; }
|
||||
/// <summary>
|
||||
/// Data for the policy.
|
||||
/// </summary>
|
||||
public Dictionary<string, object> Data { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
using Bit.Core.Models.Data;
|
||||
|
||||
namespace Bit.Api.Models.Public.Request
|
||||
{
|
||||
public class AssociationWithPermissionsRequestModel : AssociationWithPermissionsBaseModel
|
||||
{
|
||||
public SelectionReadOnly ToSelectionReadOnly()
|
||||
{
|
||||
return new SelectionReadOnly
|
||||
{
|
||||
Id = Id.Value,
|
||||
ReadOnly = ReadOnly.Value
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Public.Request
|
||||
{
|
||||
public class CollectionUpdateRequestModel : CollectionBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The associated groups that this collection is assigned to.
|
||||
/// </summary>
|
||||
public IEnumerable<AssociationWithPermissionsRequestModel> Groups { get; set; }
|
||||
|
||||
public Collection ToCollection(Collection existingCollection)
|
||||
{
|
||||
existingCollection.ExternalId = ExternalId;
|
||||
return existingCollection;
|
||||
}
|
||||
}
|
||||
}
|
51
src/Api/Models/Public/Request/EventFilterRequestModel.cs
Normal file
51
src/Api/Models/Public/Request/EventFilterRequestModel.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using Bit.Core.Exceptions;
|
||||
|
||||
namespace Bit.Api.Models.Public.Request
|
||||
{
|
||||
public class EventFilterRequestModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The start date. Must be less than the end date.
|
||||
/// </summary>
|
||||
public DateTime? Start { get; set; }
|
||||
/// <summary>
|
||||
/// The end date. Must be greater than the start date.
|
||||
/// </summary>
|
||||
public DateTime? End { get; set; }
|
||||
/// <summary>
|
||||
/// The unique identifier of the user that performed the event.
|
||||
/// </summary>
|
||||
public Guid? ActingUserId { get; set; }
|
||||
/// <summary>
|
||||
/// The unique identifier of the related item that the event describes.
|
||||
/// </summary>
|
||||
public Guid? ItemId { get; set; }
|
||||
/// <summary>
|
||||
/// A cursor for use in pagination.
|
||||
/// </summary>
|
||||
public string ContinuationToken { get; set; }
|
||||
|
||||
public Tuple<DateTime, DateTime> ToDateRange()
|
||||
{
|
||||
if (!End.HasValue || !Start.HasValue)
|
||||
{
|
||||
End = DateTime.UtcNow.Date.AddDays(1).AddMilliseconds(-1);
|
||||
Start = DateTime.UtcNow.Date.AddDays(-30);
|
||||
}
|
||||
else if (Start.Value > End.Value)
|
||||
{
|
||||
var newEnd = Start;
|
||||
Start = End;
|
||||
End = newEnd;
|
||||
}
|
||||
|
||||
if ((End.Value - Start.Value) > TimeSpan.FromDays(367))
|
||||
{
|
||||
throw new BadRequestException("Date range must be < 367 days.");
|
||||
}
|
||||
|
||||
return new Tuple<DateTime, DateTime>(Start.Value, End.Value);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Public.Request
|
||||
{
|
||||
public class GroupCreateUpdateRequestModel : GroupBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The associated collections that this group can access.
|
||||
/// </summary>
|
||||
public IEnumerable<AssociationWithPermissionsRequestModel> Collections { get; set; }
|
||||
|
||||
public Group ToGroup(Guid orgId)
|
||||
{
|
||||
return ToGroup(new Group
|
||||
{
|
||||
OrganizationId = orgId
|
||||
});
|
||||
}
|
||||
|
||||
public Group ToGroup(Group existingGroup)
|
||||
{
|
||||
existingGroup.Name = Name;
|
||||
existingGroup.AccessAll = AccessAll.Value;
|
||||
existingGroup.ExternalId = ExternalId;
|
||||
return existingGroup;
|
||||
}
|
||||
}
|
||||
}
|
24
src/Api/Models/Public/Request/MemberCreateRequestModel.cs
Normal file
24
src/Api/Models/Public/Request/MemberCreateRequestModel.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models.Public.Request
|
||||
{
|
||||
public class MemberCreateRequestModel : MemberUpdateRequestModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The member's email address.
|
||||
/// </summary>
|
||||
/// <example>jsmith@example.com</example>
|
||||
[Required]
|
||||
[StringLength(256)]
|
||||
[StrictEmailAddress]
|
||||
public string Email { get; set; }
|
||||
|
||||
public override OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
21
src/Api/Models/Public/Request/MemberUpdateRequestModel.cs
Normal file
21
src/Api/Models/Public/Request/MemberUpdateRequestModel.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Public.Request
|
||||
{
|
||||
public class MemberUpdateRequestModel : MemberBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The associated collections that this member can access.
|
||||
/// </summary>
|
||||
public IEnumerable<AssociationWithPermissionsRequestModel> Collections { get; set; }
|
||||
|
||||
public virtual OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
|
||||
{
|
||||
existingUser.Type = Type.Value;
|
||||
existingUser.AccessAll = AccessAll.Value;
|
||||
existingUser.ExternalId = ExternalId;
|
||||
return existingUser;
|
||||
}
|
||||
}
|
||||
}
|
109
src/Api/Models/Public/Request/OrganizationImportRequestModel.cs
Normal file
109
src/Api/Models/Public/Request/OrganizationImportRequestModel.cs
Normal file
@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Business;
|
||||
using Table = Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Public.Request
|
||||
{
|
||||
public class OrganizationImportRequestModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Groups to import.
|
||||
/// </summary>
|
||||
public OrganizationImportGroupRequestModel[] Groups { get; set; }
|
||||
/// <summary>
|
||||
/// Members to import.
|
||||
/// </summary>
|
||||
public OrganizationImportMemberRequestModel[] Members { get; set; }
|
||||
/// <summary>
|
||||
/// Determines if the data in this request should overwrite or append to the existing organization data.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool? OverwriteExisting { get; set; }
|
||||
/// <summary>
|
||||
/// Indicates an import of over 2000 users and/or groups is expected
|
||||
/// </summary>
|
||||
public bool LargeImport { get; set; } = false;
|
||||
|
||||
public class OrganizationImportGroupRequestModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the group.
|
||||
/// </summary>
|
||||
/// <example>Development Team</example>
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// External identifier for reference or linking this group to another system, such as a user directory.
|
||||
/// </summary>
|
||||
/// <example>external_id_123456</example>
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string ExternalId { get; set; }
|
||||
/// <summary>
|
||||
/// The associated external ids for members in this group.
|
||||
/// </summary>
|
||||
public IEnumerable<string> MemberExternalIds { get; set; }
|
||||
|
||||
public ImportedGroup ToImportedGroup(Guid organizationId)
|
||||
{
|
||||
var importedGroup = new ImportedGroup
|
||||
{
|
||||
Group = new Table.Group
|
||||
{
|
||||
OrganizationId = organizationId,
|
||||
Name = Name,
|
||||
ExternalId = ExternalId
|
||||
},
|
||||
ExternalUserIds = new HashSet<string>(MemberExternalIds)
|
||||
};
|
||||
|
||||
return importedGroup;
|
||||
}
|
||||
}
|
||||
|
||||
public class OrganizationImportMemberRequestModel : IValidatableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// The member's email address. Required for non-deleted users.
|
||||
/// </summary>
|
||||
/// <example>jsmith@example.com</example>
|
||||
[EmailAddress]
|
||||
[StringLength(256)]
|
||||
public string Email { get; set; }
|
||||
/// <summary>
|
||||
/// External identifier for reference or linking this member to another system, such as a user directory.
|
||||
/// </summary>
|
||||
/// <example>external_id_123456</example>
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string ExternalId { get; set; }
|
||||
/// <summary>
|
||||
/// Determines if this member should be removed from the organization during import.
|
||||
/// </summary>
|
||||
public bool Deleted { get; set; }
|
||||
|
||||
public ImportedOrganizationUser ToImportedOrganizationUser()
|
||||
{
|
||||
var importedUser = new ImportedOrganizationUser
|
||||
{
|
||||
Email = Email.ToLowerInvariant(),
|
||||
ExternalId = ExternalId
|
||||
};
|
||||
|
||||
return importedUser;
|
||||
}
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Email) && !Deleted)
|
||||
{
|
||||
yield return new ValidationResult("Email is required for enabled members.",
|
||||
new string[] { nameof(Email) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
src/Api/Models/Public/Request/PolicyUpdateRequestModel.cs
Normal file
24
src/Api/Models/Public/Request/PolicyUpdateRequestModel.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using Bit.Core.Models.Table;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Bit.Api.Models.Public.Request
|
||||
{
|
||||
public class PolicyUpdateRequestModel : PolicyBaseModel
|
||||
{
|
||||
public Policy ToPolicy(Guid orgId)
|
||||
{
|
||||
return ToPolicy(new Policy
|
||||
{
|
||||
OrganizationId = orgId
|
||||
});
|
||||
}
|
||||
|
||||
public virtual Policy ToPolicy(Policy existingPolicy)
|
||||
{
|
||||
existingPolicy.Enabled = Enabled.GetValueOrDefault();
|
||||
existingPolicy.Data = Data != null ? JsonConvert.SerializeObject(Data) : null;
|
||||
return existingPolicy;
|
||||
}
|
||||
}
|
||||
}
|
13
src/Api/Models/Public/Request/UpdateGroupIdsRequestModel.cs
Normal file
13
src/Api/Models/Public/Request/UpdateGroupIdsRequestModel.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.Api.Models.Public.Request
|
||||
{
|
||||
public class UpdateGroupIdsRequestModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The associated group ids that this object can access.
|
||||
/// </summary>
|
||||
public IEnumerable<Guid> GroupIds { get; set; }
|
||||
}
|
||||
}
|
13
src/Api/Models/Public/Request/UpdateMemberIdsRequestModel.cs
Normal file
13
src/Api/Models/Public/Request/UpdateMemberIdsRequestModel.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.Api.Models.Public.Request
|
||||
{
|
||||
public class UpdateMemberIdsRequestModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The associated member ids that have access to this object.
|
||||
/// </summary>
|
||||
public IEnumerable<Guid> MemberIds { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using Bit.Core.Models.Data;
|
||||
|
||||
namespace Bit.Api.Models.Public.Response
|
||||
{
|
||||
public class AssociationWithPermissionsResponseModel : AssociationWithPermissionsBaseModel
|
||||
{
|
||||
public AssociationWithPermissionsResponseModel(SelectionReadOnly selection)
|
||||
{
|
||||
if (selection == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(selection));
|
||||
}
|
||||
Id = selection.Id;
|
||||
ReadOnly = selection.ReadOnly;
|
||||
}
|
||||
}
|
||||
}
|
44
src/Api/Models/Public/Response/CollectionResponseModel.cs
Normal file
44
src/Api/Models/Public/Response/CollectionResponseModel.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Public.Response
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection.
|
||||
/// </summary>
|
||||
public class CollectionResponseModel : CollectionBaseModel, IResponseModel
|
||||
{
|
||||
public CollectionResponseModel(Collection collection, IEnumerable<SelectionReadOnly> groups)
|
||||
{
|
||||
if (collection == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
Id = collection.Id;
|
||||
ExternalId = collection.ExternalId;
|
||||
Groups = groups?.Select(c => new AssociationWithPermissionsResponseModel(c));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// String representing the object's type. Objects of the same type share the same properties.
|
||||
/// </summary>
|
||||
/// <example>collection</example>
|
||||
[Required]
|
||||
public string Object => "collection";
|
||||
/// <summary>
|
||||
/// The collection's unique identifier.
|
||||
/// </summary>
|
||||
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
|
||||
[Required]
|
||||
public Guid Id { get; set; }
|
||||
/// <summary>
|
||||
/// The associated groups that this collection is assigned to.
|
||||
/// </summary>
|
||||
public IEnumerable<AssociationWithPermissionsResponseModel> Groups { get; set; }
|
||||
}
|
||||
}
|
79
src/Api/Models/Public/Response/ErrorResponseModel.cs
Normal file
79
src/Api/Models/Public/Response/ErrorResponseModel.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace Bit.Api.Models.Public.Response
|
||||
{
|
||||
public class ErrorResponseModel : IResponseModel
|
||||
{
|
||||
public ErrorResponseModel(string message)
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public ErrorResponseModel(ModelStateDictionary modelState)
|
||||
{
|
||||
Message = "The request's model state is invalid.";
|
||||
Errors = new Dictionary<string, IEnumerable<string>>();
|
||||
|
||||
var keys = modelState.Keys.ToList();
|
||||
var values = modelState.Values.ToList();
|
||||
|
||||
for (var i = 0; i < values.Count; i++)
|
||||
{
|
||||
var value = values[i];
|
||||
if (keys.Count <= i)
|
||||
{
|
||||
// Keys not available for some reason.
|
||||
break;
|
||||
}
|
||||
|
||||
var key = keys[i];
|
||||
if (value.ValidationState != ModelValidationState.Invalid || value.Errors.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var errors = value.Errors.Select(e => e.ErrorMessage);
|
||||
Errors.Add(key, errors);
|
||||
}
|
||||
}
|
||||
|
||||
public ErrorResponseModel(Dictionary<string, IEnumerable<string>> errors)
|
||||
: this("Errors have occurred.", errors)
|
||||
{ }
|
||||
|
||||
public ErrorResponseModel(string errorKey, string errorValue)
|
||||
: this(errorKey, new string[] { errorValue })
|
||||
{ }
|
||||
|
||||
public ErrorResponseModel(string errorKey, IEnumerable<string> errorValues)
|
||||
: this(new Dictionary<string, IEnumerable<string>> { { errorKey, errorValues } })
|
||||
{ }
|
||||
|
||||
public ErrorResponseModel(string message, Dictionary<string, IEnumerable<string>> errors)
|
||||
{
|
||||
Message = message;
|
||||
Errors = errors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// String representing the object's type. Objects of the same type share the same properties.
|
||||
/// </summary>
|
||||
/// <example>error</example>
|
||||
[Required]
|
||||
public string Object => "error";
|
||||
/// <summary>
|
||||
/// A human-readable message providing details about the error.
|
||||
/// </summary>
|
||||
/// <example>The request model is invalid.</example>
|
||||
[Required]
|
||||
public string Message { get; set; }
|
||||
/// <summary>
|
||||
/// If multiple errors occurred, they are listed in dictionary. Errors related to a specific
|
||||
/// request parameter will include a dictionary key describing that parameter.
|
||||
/// </summary>
|
||||
public Dictionary<string, IEnumerable<string>> Errors { get; set; }
|
||||
}
|
||||
}
|
88
src/Api/Models/Public/Response/EventResponseModel.cs
Normal file
88
src/Api/Models/Public/Response/EventResponseModel.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
|
||||
namespace Bit.Api.Models.Public.Response
|
||||
{
|
||||
/// <summary>
|
||||
/// An event log.
|
||||
/// </summary>
|
||||
public class EventResponseModel : IResponseModel
|
||||
{
|
||||
public EventResponseModel(IEvent ev)
|
||||
{
|
||||
if (ev == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ev));
|
||||
}
|
||||
|
||||
Type = ev.Type;
|
||||
ItemId = ev.CipherId;
|
||||
CollectionId = ev.CollectionId;
|
||||
GroupId = ev.GroupId;
|
||||
PolicyId = ev.PolicyId;
|
||||
MemberId = ev.OrganizationUserId;
|
||||
ActingUserId = ev.ActingUserId;
|
||||
Date = ev.Date;
|
||||
Device = ev.DeviceType;
|
||||
IpAddress = ev.IpAddress;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// String representing the object's type. Objects of the same type share the same properties.
|
||||
/// </summary>
|
||||
/// <example>event</example>
|
||||
[Required]
|
||||
public string Object => "event";
|
||||
/// <summary>
|
||||
/// The type of event.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public EventType Type { get; set; }
|
||||
/// <summary>
|
||||
/// The unique identifier of the related item that the event describes.
|
||||
/// </summary>
|
||||
/// <example>3767a302-8208-4dc6-b842-030428a1cfad</example>
|
||||
public Guid? ItemId { get; set; }
|
||||
/// <summary>
|
||||
/// The unique identifier of the related collection that the event describes.
|
||||
/// </summary>
|
||||
/// <example>bce212a4-25f3-4888-8a0a-4c5736d851e0</example>
|
||||
public Guid? CollectionId { get; set; }
|
||||
/// <summary>
|
||||
/// The unique identifier of the related group that the event describes.
|
||||
/// </summary>
|
||||
/// <example>f29a2515-91d2-4452-b49b-5e8040e6b0f4</example>
|
||||
public Guid? GroupId { get; set; }
|
||||
/// <summary>
|
||||
/// The unique identifier of the related policy that the event describes.
|
||||
/// </summary>
|
||||
/// <example>f29a2515-91d2-4452-b49b-5e8040e6b0f4</example>
|
||||
public Guid? PolicyId { get; set; }
|
||||
/// <summary>
|
||||
/// The unique identifier of the related member that the event describes.
|
||||
/// </summary>
|
||||
/// <example>e68b8629-85eb-4929-92c0-b84464976ba4</example>
|
||||
public Guid? MemberId { get; set; }
|
||||
/// <summary>
|
||||
/// The unique identifier of the user that performed the event.
|
||||
/// </summary>
|
||||
/// <example>a2549f79-a71f-4eb9-9234-eb7247333f94</example>
|
||||
public Guid? ActingUserId { get; set; }
|
||||
/// <summary>
|
||||
/// The date/timestamp when the event occurred.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTime Date { get; set; }
|
||||
/// <summary>
|
||||
/// The type of device used by the acting user when the event occurred.
|
||||
/// </summary>
|
||||
public DeviceType? Device { get; set; }
|
||||
/// <summary>
|
||||
/// The IP address of the acting user.
|
||||
/// </summary>
|
||||
/// <example>172.16.254.1</example>
|
||||
public string IpAddress { get; set; }
|
||||
}
|
||||
}
|
46
src/Api/Models/Public/Response/GroupResponseModel.cs
Normal file
46
src/Api/Models/Public/Response/GroupResponseModel.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Public.Response
|
||||
{
|
||||
/// <summary>
|
||||
/// A user group.
|
||||
/// </summary>
|
||||
public class GroupResponseModel : GroupBaseModel, IResponseModel
|
||||
{
|
||||
public GroupResponseModel(Group group, IEnumerable<SelectionReadOnly> collections)
|
||||
{
|
||||
if (group == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(group));
|
||||
}
|
||||
|
||||
Id = group.Id;
|
||||
Name = group.Name;
|
||||
AccessAll = group.AccessAll;
|
||||
ExternalId = group.ExternalId;
|
||||
Collections = collections?.Select(c => new AssociationWithPermissionsResponseModel(c));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// String representing the object's type. Objects of the same type share the same properties.
|
||||
/// </summary>
|
||||
/// <example>group</example>
|
||||
[Required]
|
||||
public string Object => "group";
|
||||
/// <summary>
|
||||
/// The group's unique identifier.
|
||||
/// </summary>
|
||||
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
|
||||
[Required]
|
||||
public Guid Id { get; set; }
|
||||
/// <summary>
|
||||
/// The associated collections that this group can access.
|
||||
/// </summary>
|
||||
public IEnumerable<AssociationWithPermissionsResponseModel> Collections { get; set; }
|
||||
}
|
||||
}
|
7
src/Api/Models/Public/Response/IResponseModel.cs
Normal file
7
src/Api/Models/Public/Response/IResponseModel.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Bit.Api.Models.Public.Response
|
||||
{
|
||||
public interface IResponseModel
|
||||
{
|
||||
string Object { get; }
|
||||
}
|
||||
}
|
30
src/Api/Models/Public/Response/ListResponseModel.cs
Normal file
30
src/Api/Models/Public/Response/ListResponseModel.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Public.Response
|
||||
{
|
||||
public class ListResponseModel<T> : IResponseModel where T : IResponseModel
|
||||
{
|
||||
public ListResponseModel(IEnumerable<T> data, string continuationToken = null)
|
||||
{
|
||||
Data = data;
|
||||
ContinuationToken = continuationToken;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// String representing the object's type. Objects of the same type share the same properties.
|
||||
/// </summary>
|
||||
/// <example>list</example>
|
||||
[Required]
|
||||
public string Object => "list";
|
||||
/// <summary>
|
||||
/// An array containing the actual response elements, paginated by any request parameters.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public IEnumerable<T> Data { get; set; }
|
||||
/// <summary>
|
||||
/// A cursor for use in pagination.
|
||||
/// </summary>
|
||||
public string ContinuationToken { get; set; }
|
||||
}
|
||||
}
|
96
src/Api/Models/Public/Response/MemberResponseModel.cs
Normal file
96
src/Api/Models/Public/Response/MemberResponseModel.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Public.Response
|
||||
{
|
||||
/// <summary>
|
||||
/// An organization member.
|
||||
/// </summary>
|
||||
public class MemberResponseModel : MemberBaseModel, IResponseModel
|
||||
{
|
||||
public MemberResponseModel(OrganizationUser user, IEnumerable<SelectionReadOnly> collections)
|
||||
: base(user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
Id = user.Id;
|
||||
UserId = user.UserId;
|
||||
Email = user.Email;
|
||||
Status = user.Status;
|
||||
Collections = collections?.Select(c => new AssociationWithPermissionsResponseModel(c));
|
||||
}
|
||||
|
||||
public MemberResponseModel(OrganizationUserUserDetails user, bool twoFactorEnabled,
|
||||
IEnumerable<SelectionReadOnly> collections)
|
||||
: base(user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
Id = user.Id;
|
||||
UserId = user.UserId;
|
||||
Name = user.Name;
|
||||
Email = user.Email;
|
||||
TwoFactorEnabled = twoFactorEnabled;
|
||||
Status = user.Status;
|
||||
Collections = collections?.Select(c => new AssociationWithPermissionsResponseModel(c));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// String representing the object's type. Objects of the same type share the same properties.
|
||||
/// </summary>
|
||||
/// <example>member</example>
|
||||
[Required]
|
||||
public string Object => "member";
|
||||
/// <summary>
|
||||
/// The member's unique identifier within the organization.
|
||||
/// </summary>
|
||||
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
|
||||
[Required]
|
||||
public Guid Id { get; set; }
|
||||
/// <summary>
|
||||
/// The member's unique identifier across Bitwarden.
|
||||
/// </summary>
|
||||
/// <example>48b47ee1-493e-4c67-aef7-014996c40eca</example>
|
||||
[Required]
|
||||
public Guid? UserId { get; set; }
|
||||
/// <summary>
|
||||
/// The member's name, set from their user account profile.
|
||||
/// </summary>
|
||||
/// <example>John Smith</example>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// The member's email address.
|
||||
/// </summary>
|
||||
/// <example>jsmith@example.com</example>
|
||||
[Required]
|
||||
public string Email { get; set; }
|
||||
/// <summary>
|
||||
/// Returns <c>true</c> if the member has a two-step login method enabled on their user account.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool TwoFactorEnabled { get; set; }
|
||||
/// <summary>
|
||||
/// The member's status within the organization. All created members start with a status of "Invited".
|
||||
/// Once a member accept's their invitation to join the organization, their status changes to "Accepted".
|
||||
/// Accepted members are then "Confirmed" by an organization administrator. Once a member is "Confirmed",
|
||||
/// their status can no longer change.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public OrganizationUserStatusType Status { get; set; }
|
||||
/// <summary>
|
||||
/// The associated collections that this member can access.
|
||||
/// </summary>
|
||||
public IEnumerable<AssociationWithPermissionsResponseModel> Collections { get; set; }
|
||||
}
|
||||
}
|
49
src/Api/Models/Public/Response/PolicyResponseModel.cs
Normal file
49
src/Api/Models/Public/Response/PolicyResponseModel.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Table;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Bit.Api.Models.Public.Response
|
||||
{
|
||||
/// <summary>
|
||||
/// A policy.
|
||||
/// </summary>
|
||||
public class PolicyResponseModel : PolicyBaseModel, IResponseModel
|
||||
{
|
||||
public PolicyResponseModel(Policy policy)
|
||||
{
|
||||
if (policy == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(policy));
|
||||
}
|
||||
|
||||
Id = policy.Id;
|
||||
Type = policy.Type;
|
||||
Enabled = policy.Enabled;
|
||||
if (!string.IsNullOrWhiteSpace(policy.Data))
|
||||
{
|
||||
Data = JsonConvert.DeserializeObject<Dictionary<string, object>>(policy.Data);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// String representing the object's type. Objects of the same type share the same properties.
|
||||
/// </summary>
|
||||
/// <example>policy</example>
|
||||
[Required]
|
||||
public string Object => "policy";
|
||||
/// <summary>
|
||||
/// The policy's unique identifier.
|
||||
/// </summary>
|
||||
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
|
||||
[Required]
|
||||
public Guid Id { get; set; }
|
||||
/// <summary>
|
||||
/// The type of policy.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public PolicyType? Type { get; set; }
|
||||
}
|
||||
}
|
12
src/Api/Models/Request/Accounts/DeleteRecoverRequestModel.cs
Normal file
12
src/Api/Models/Request/Accounts/DeleteRecoverRequestModel.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class DeleteRecoverRequestModel
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
[StringLength(256)]
|
||||
public string Email { get; set; }
|
||||
}
|
||||
}
|
20
src/Api/Models/Request/Accounts/EmailRequestModel.cs
Normal file
20
src/Api/Models/Request/Accounts/EmailRequestModel.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class EmailRequestModel : SecretVerificationRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StrictEmailAddress]
|
||||
[StringLength(256)]
|
||||
public string NewEmail { get; set; }
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string NewMasterPasswordHash { get; set; }
|
||||
[Required]
|
||||
public string Token { get; set; }
|
||||
[Required]
|
||||
public string Key { get; set; }
|
||||
}
|
||||
}
|
13
src/Api/Models/Request/Accounts/EmailTokenRequestModel.cs
Normal file
13
src/Api/Models/Request/Accounts/EmailTokenRequestModel.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class EmailTokenRequestModel : SecretVerificationRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StrictEmailAddress]
|
||||
[StringLength(256)]
|
||||
public string NewEmail { get; set; }
|
||||
}
|
||||
}
|
11
src/Api/Models/Request/Accounts/ImportCiphersRequestModel.cs
Normal file
11
src/Api/Models/Request/Accounts/ImportCiphersRequestModel.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class ImportCiphersRequestModel
|
||||
{
|
||||
public FolderRequestModel[] Folders { get; set; }
|
||||
public CipherRequestModel[] Ciphers { get; set; }
|
||||
public KeyValuePair<int, int>[] FolderRelationships { get; set; }
|
||||
}
|
||||
}
|
32
src/Api/Models/Request/Accounts/KdfRequestModel.cs
Normal file
32
src/Api/Models/Request/Accounts/KdfRequestModel.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class KdfRequestModel : PasswordRequestModel, IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
public KdfType? Kdf { get; set; }
|
||||
[Required]
|
||||
public int? KdfIterations { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (Kdf.HasValue && KdfIterations.HasValue)
|
||||
{
|
||||
switch (Kdf.Value)
|
||||
{
|
||||
case KdfType.PBKDF2_SHA256:
|
||||
if (KdfIterations.Value < 5000 || KdfIterations.Value > 2_000_000)
|
||||
{
|
||||
yield return new ValidationResult("KDF iterations must be between 5000 and 2000000.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
27
src/Api/Models/Request/Accounts/KeysRequestModel.cs
Normal file
27
src/Api/Models/Request/Accounts/KeysRequestModel.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class KeysRequestModel
|
||||
{
|
||||
public string PublicKey { get; set; }
|
||||
[Required]
|
||||
public string EncryptedPrivateKey { get; set; }
|
||||
|
||||
public User ToUser(User existingUser)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(existingUser.PublicKey) && !string.IsNullOrWhiteSpace(PublicKey))
|
||||
{
|
||||
existingUser.PublicKey = PublicKey;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(existingUser.PrivateKey))
|
||||
{
|
||||
existingUser.PrivateKey = EncryptedPrivateKey;
|
||||
}
|
||||
|
||||
return existingUser;
|
||||
}
|
||||
}
|
||||
}
|
12
src/Api/Models/Request/Accounts/PasswordHintRequestModel.cs
Normal file
12
src/Api/Models/Request/Accounts/PasswordHintRequestModel.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class PasswordHintRequestModel
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
[StringLength(256)]
|
||||
public string Email { get; set; }
|
||||
}
|
||||
}
|
13
src/Api/Models/Request/Accounts/PasswordRequestModel.cs
Normal file
13
src/Api/Models/Request/Accounts/PasswordRequestModel.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class PasswordRequestModel : SecretVerificationRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string NewMasterPasswordHash { get; set; }
|
||||
[Required]
|
||||
public string Key { get; set; }
|
||||
}
|
||||
}
|
12
src/Api/Models/Request/Accounts/PreloginRequestModel.cs
Normal file
12
src/Api/Models/Request/Accounts/PreloginRequestModel.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class PreloginRequestModel
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
[StringLength(256)]
|
||||
public string Email { get; set; }
|
||||
}
|
||||
}
|
44
src/Api/Models/Request/Accounts/PremiumRequestModel.cs
Normal file
44
src/Api/Models/Request/Accounts/PremiumRequestModel.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Settings;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Enums = Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class PremiumRequestModel : IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
public Enums.PaymentMethodType? PaymentMethodType { get; set; }
|
||||
public string PaymentToken { get; set; }
|
||||
[Range(0, 99)]
|
||||
public short? AdditionalStorageGb { get; set; }
|
||||
public IFormFile License { get; set; }
|
||||
public string Country { get; set; }
|
||||
public string PostalCode { get; set; }
|
||||
|
||||
public bool Validate(GlobalSettings globalSettings)
|
||||
{
|
||||
if (!(License == null && !globalSettings.SelfHosted) ||
|
||||
(License != null && globalSettings.SelfHosted))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return globalSettings.SelfHosted || !string.IsNullOrWhiteSpace(Country);
|
||||
}
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
var creditType = PaymentMethodType.HasValue && PaymentMethodType.Value == Enums.PaymentMethodType.Credit;
|
||||
if (string.IsNullOrWhiteSpace(PaymentToken) && !creditType && License == null)
|
||||
{
|
||||
yield return new ValidationResult("Payment token or license is required.");
|
||||
}
|
||||
if (Country == "US" && string.IsNullOrWhiteSpace(PostalCode))
|
||||
{
|
||||
yield return new ValidationResult("Zip / postal code is required.",
|
||||
new string[] { nameof(PostalCode) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class RegenerateTwoFactorRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
public string Token { get; set; }
|
||||
}
|
||||
}
|
81
src/Api/Models/Request/Accounts/RegisterRequestModel.cs
Normal file
81
src/Api/Models/Request/Accounts/RegisterRequestModel.cs
Normal file
@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Api;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Utilities;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class RegisterRequestModel : IValidatableObject, ICaptchaProtectedModel
|
||||
{
|
||||
[StringLength(50)]
|
||||
public string Name { get; set; }
|
||||
[Required]
|
||||
[StrictEmailAddress]
|
||||
[StringLength(256)]
|
||||
public string Email { get; set; }
|
||||
[Required]
|
||||
[StringLength(1000)]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
[StringLength(50)]
|
||||
public string MasterPasswordHint { get; set; }
|
||||
public string CaptchaResponse { get; set; }
|
||||
public string Key { get; set; }
|
||||
public KeysRequestModel Keys { get; set; }
|
||||
public string Token { get; set; }
|
||||
public Guid? OrganizationUserId { get; set; }
|
||||
public KdfType? Kdf { get; set; }
|
||||
public int? KdfIterations { get; set; }
|
||||
public Dictionary<string, object> ReferenceData { get; set; }
|
||||
|
||||
public User ToUser()
|
||||
{
|
||||
var user = new User
|
||||
{
|
||||
Name = Name,
|
||||
Email = Email,
|
||||
MasterPasswordHint = MasterPasswordHint,
|
||||
Kdf = Kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256),
|
||||
KdfIterations = KdfIterations.GetValueOrDefault(5000),
|
||||
};
|
||||
|
||||
if (ReferenceData != null)
|
||||
{
|
||||
user.ReferenceData = JsonConvert.SerializeObject(ReferenceData);
|
||||
}
|
||||
|
||||
if (Key != null)
|
||||
{
|
||||
user.Key = Key;
|
||||
}
|
||||
|
||||
if (Keys != null)
|
||||
{
|
||||
Keys.ToUser(user);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (Kdf.HasValue && KdfIterations.HasValue)
|
||||
{
|
||||
switch (Kdf.Value)
|
||||
{
|
||||
case KdfType.PBKDF2_SHA256:
|
||||
if (KdfIterations.Value < 5000 || KdfIterations.Value > 1_000_000)
|
||||
{
|
||||
yield return new ValidationResult("KDF iterations must be between 5000 and 1000000.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class SecretVerificationRequestModel : IValidatableObject
|
||||
{
|
||||
[StringLength(300)]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
public string OTP { get; set; }
|
||||
public string Secret => !string.IsNullOrEmpty(MasterPasswordHash) ? MasterPasswordHash : OTP;
|
||||
|
||||
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Secret))
|
||||
{
|
||||
yield return new ValidationResult("MasterPasswordHash or OTP must be supplied.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class SetKeyConnectorKeyRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string Key { get; set; }
|
||||
[Required]
|
||||
public KeysRequestModel Keys { get; set; }
|
||||
[Required]
|
||||
public KdfType Kdf { get; set; }
|
||||
[Required]
|
||||
public int KdfIterations { get; set; }
|
||||
[Required]
|
||||
public string OrgIdentifier { get; set; }
|
||||
|
||||
public User ToUser(User existingUser)
|
||||
{
|
||||
existingUser.Kdf = Kdf;
|
||||
existingUser.KdfIterations = KdfIterations;
|
||||
existingUser.Key = Key;
|
||||
Keys.ToUser(existingUser);
|
||||
return existingUser;
|
||||
}
|
||||
}
|
||||
}
|
34
src/Api/Models/Request/Accounts/SetPasswordRequestModel.cs
Normal file
34
src/Api/Models/Request/Accounts/SetPasswordRequestModel.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class SetPasswordRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
[Required]
|
||||
public string Key { get; set; }
|
||||
[StringLength(50)]
|
||||
public string MasterPasswordHint { get; set; }
|
||||
[Required]
|
||||
public KeysRequestModel Keys { get; set; }
|
||||
[Required]
|
||||
public KdfType Kdf { get; set; }
|
||||
[Required]
|
||||
public int KdfIterations { get; set; }
|
||||
public string OrgIdentifier { get; set; }
|
||||
|
||||
public User ToUser(User existingUser)
|
||||
{
|
||||
existingUser.MasterPasswordHint = MasterPasswordHint;
|
||||
existingUser.Kdf = Kdf;
|
||||
existingUser.KdfIterations = KdfIterations;
|
||||
existingUser.Key = Key;
|
||||
Keys.ToUser(existingUser);
|
||||
return existingUser;
|
||||
}
|
||||
}
|
||||
}
|
20
src/Api/Models/Request/Accounts/StorageRequestModel.cs
Normal file
20
src/Api/Models/Request/Accounts/StorageRequestModel.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class StorageRequestModel : IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
public short? StorageGbAdjustment { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (StorageGbAdjustment == 0)
|
||||
{
|
||||
yield return new ValidationResult("Storage adjustment cannot be 0.",
|
||||
new string[] { nameof(StorageGbAdjustment) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
src/Api/Models/Request/Accounts/TaxInfoUpdateRequestModel.cs
Normal file
21
src/Api/Models/Request/Accounts/TaxInfoUpdateRequestModel.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class TaxInfoUpdateRequestModel : IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
public string Country { get; set; }
|
||||
public string PostalCode { get; set; }
|
||||
|
||||
public virtual IEnumerable<ValidationResult> Validate (ValidationContext validationContext)
|
||||
{
|
||||
if (Country == "US" && string.IsNullOrWhiteSpace(PostalCode))
|
||||
{
|
||||
yield return new ValidationResult("Zip / postal code is required.",
|
||||
new string[] { nameof(PostalCode) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
src/Api/Models/Request/Accounts/UpdateKeyRequestModel.cs
Normal file
21
src/Api/Models/Request/Accounts/UpdateKeyRequestModel.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class UpdateKeyRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string MasterPasswordHash { get; set; }
|
||||
[Required]
|
||||
public IEnumerable<CipherWithIdRequestModel> Ciphers { get; set; }
|
||||
[Required]
|
||||
public IEnumerable<FolderWithIdRequestModel> Folders { get; set; }
|
||||
public IEnumerable<SendWithIdRequestModel> Sends { get; set; }
|
||||
[Required]
|
||||
public string PrivateKey { get; set; }
|
||||
[Required]
|
||||
public string Key { get; set; }
|
||||
}
|
||||
}
|
20
src/Api/Models/Request/Accounts/UpdateProfileRequestModel.cs
Normal file
20
src/Api/Models/Request/Accounts/UpdateProfileRequestModel.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class UpdateProfileRequestModel
|
||||
{
|
||||
[StringLength(50)]
|
||||
public string Name { get; set; }
|
||||
[StringLength(50)]
|
||||
public string MasterPasswordHint { get; set; }
|
||||
|
||||
public User ToUser(User existingUser)
|
||||
{
|
||||
existingUser.Name = Name;
|
||||
existingUser.MasterPasswordHint = string.IsNullOrWhiteSpace(MasterPasswordHint) ? null : MasterPasswordHint;
|
||||
return existingUser;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Api.Models.Request.Organizations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class UpdateTempPasswordRequestModel : OrganizationUserResetPasswordRequestModel
|
||||
{
|
||||
[StringLength(50)]
|
||||
public string MasterPasswordHint { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class VerifyDeleteRecoverRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string UserId { get; set; }
|
||||
[Required]
|
||||
public string Token { get; set; }
|
||||
}
|
||||
}
|
12
src/Api/Models/Request/Accounts/VerifyEmailRequestModel.cs
Normal file
12
src/Api/Models/Request/Accounts/VerifyEmailRequestModel.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class VerifyEmailRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string UserId { get; set; }
|
||||
[Required]
|
||||
public string Token { get; set; }
|
||||
}
|
||||
}
|
10
src/Api/Models/Request/Accounts/VerifyOTPRequestModel.cs
Normal file
10
src/Api/Models/Request/Accounts/VerifyOTPRequestModel.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Accounts
|
||||
{
|
||||
public class VerifyOTPRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string OTP { get; set; }
|
||||
}
|
||||
}
|
10
src/Api/Models/Request/AttachmentRequestModel.cs
Normal file
10
src/Api/Models/Request/AttachmentRequestModel.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class AttachmentRequestModel
|
||||
{
|
||||
public string Key { get; set; }
|
||||
public string FileName { get; set; }
|
||||
public long FileSize { get; set; }
|
||||
public bool AdminRequest { get; set; } = false;
|
||||
}
|
||||
}
|
68
src/Api/Models/Request/BitPayInvoiceRequestModel.cs
Normal file
68
src/Api/Models/Request/BitPayInvoiceRequestModel.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Settings;
|
||||
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class BitPayInvoiceRequestModel : IValidatableObject
|
||||
{
|
||||
public Guid? UserId { get; set; }
|
||||
public Guid? OrganizationId { get; set; }
|
||||
public bool Credit { get; set; }
|
||||
[Required]
|
||||
public decimal? Amount { get; set; }
|
||||
public string ReturnUrl { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Email { get; set; }
|
||||
|
||||
public BitPayLight.Models.Invoice.Invoice ToBitpayInvoice(GlobalSettings globalSettings)
|
||||
{
|
||||
var inv = new BitPayLight.Models.Invoice.Invoice
|
||||
{
|
||||
Price = Convert.ToDouble(Amount.Value),
|
||||
Currency = "USD",
|
||||
RedirectUrl = ReturnUrl,
|
||||
Buyer = new BitPayLight.Models.Invoice.Buyer
|
||||
{
|
||||
Email = Email,
|
||||
Name = Name
|
||||
},
|
||||
NotificationUrl = globalSettings.BitPay.NotificationUrl,
|
||||
FullNotifications = true,
|
||||
ExtendedNotifications = true
|
||||
};
|
||||
|
||||
var posData = string.Empty;
|
||||
if (UserId.HasValue)
|
||||
{
|
||||
posData = "userId:" + UserId.Value;
|
||||
}
|
||||
else if (OrganizationId.HasValue)
|
||||
{
|
||||
posData = "organizationId:" + OrganizationId.Value;
|
||||
}
|
||||
|
||||
if (Credit)
|
||||
{
|
||||
posData += ",accountCredit:1";
|
||||
inv.ItemDesc = "Bitwarden Account Credit";
|
||||
}
|
||||
else
|
||||
{
|
||||
inv.ItemDesc = "Bitwarden";
|
||||
}
|
||||
|
||||
inv.PosData = posData;
|
||||
return inv;
|
||||
}
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (!UserId.HasValue && !OrganizationId.HasValue)
|
||||
{
|
||||
yield return new ValidationResult("User or Ooganization is required.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
src/Api/Models/Request/CipherPartialRequestModel.cs
Normal file
11
src/Api/Models/Request/CipherPartialRequestModel.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class CipherPartialRequestModel
|
||||
{
|
||||
[StringLength(36)]
|
||||
public string FolderId { get; set; }
|
||||
public bool Favorite { get; set; }
|
||||
}
|
||||
}
|
353
src/Api/Models/Request/CipherRequestModel.cs
Normal file
353
src/Api/Models/Request/CipherRequestModel.cs
Normal file
@ -0,0 +1,353 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Utilities;
|
||||
using Core.Models.Data;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class CipherRequestModel
|
||||
{
|
||||
public CipherType Type { get; set; }
|
||||
|
||||
[StringLength(36)]
|
||||
public string OrganizationId { get; set; }
|
||||
public string FolderId { get; set; }
|
||||
public bool Favorite { get; set; }
|
||||
public CipherRepromptType Reprompt { get; set; }
|
||||
[Required]
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Name { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(10000)]
|
||||
public string Notes { get; set; }
|
||||
public IEnumerable<CipherFieldModel> Fields { get; set; }
|
||||
public IEnumerable<CipherPasswordHistoryModel> PasswordHistory { get; set; }
|
||||
[Obsolete]
|
||||
public Dictionary<string, string> Attachments { get; set; }
|
||||
// TODO: Rename to Attachments whenever the above is finally removed.
|
||||
public Dictionary<string, CipherAttachmentModel> Attachments2 { get; set; }
|
||||
|
||||
public CipherLoginModel Login { get; set; }
|
||||
public CipherCardModel Card { get; set; }
|
||||
public CipherIdentityModel Identity { get; set; }
|
||||
public CipherSecureNoteModel SecureNote { get; set; }
|
||||
public DateTime? LastKnownRevisionDate { get; set; } = null;
|
||||
|
||||
public CipherDetails ToCipherDetails(Guid userId, bool allowOrgIdSet = true)
|
||||
{
|
||||
var hasOrgId = !string.IsNullOrWhiteSpace(OrganizationId);
|
||||
var cipher = new CipherDetails
|
||||
{
|
||||
Type = Type,
|
||||
UserId = !hasOrgId ? (Guid?)userId : null,
|
||||
OrganizationId = allowOrgIdSet && hasOrgId ? new Guid(OrganizationId) : (Guid?)null,
|
||||
Edit = true,
|
||||
ViewPassword = true,
|
||||
};
|
||||
ToCipherDetails(cipher);
|
||||
return cipher;
|
||||
}
|
||||
|
||||
public CipherDetails ToCipherDetails(CipherDetails existingCipher)
|
||||
{
|
||||
existingCipher.FolderId = string.IsNullOrWhiteSpace(FolderId) ? null : (Guid?)new Guid(FolderId);
|
||||
existingCipher.Favorite = Favorite;
|
||||
ToCipher(existingCipher);
|
||||
return existingCipher;
|
||||
}
|
||||
|
||||
public Cipher ToCipher(Cipher existingCipher)
|
||||
{
|
||||
switch (existingCipher.Type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
var loginObj = JObject.FromObject(ToCipherLoginData(),
|
||||
new JsonSerializer { NullValueHandling = NullValueHandling.Ignore });
|
||||
loginObj[nameof(CipherLoginData.Uri)]?.Parent?.Remove();
|
||||
existingCipher.Data = loginObj.ToString(Formatting.None);
|
||||
break;
|
||||
case CipherType.Card:
|
||||
existingCipher.Data = JsonConvert.SerializeObject(ToCipherCardData(),
|
||||
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
existingCipher.Data = JsonConvert.SerializeObject(ToCipherIdentityData(),
|
||||
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
existingCipher.Data = JsonConvert.SerializeObject(ToCipherSecureNoteData(),
|
||||
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unsupported type: " + nameof(Type) + ".");
|
||||
}
|
||||
|
||||
existingCipher.Reprompt = Reprompt;
|
||||
|
||||
var hasAttachments2 = (Attachments2?.Count ?? 0) > 0;
|
||||
var hasAttachments = (Attachments?.Count ?? 0) > 0;
|
||||
|
||||
if (!hasAttachments2 && !hasAttachments)
|
||||
{
|
||||
return existingCipher;
|
||||
}
|
||||
|
||||
var attachments = existingCipher.GetAttachments();
|
||||
if ((attachments?.Count ?? 0) == 0)
|
||||
{
|
||||
return existingCipher;
|
||||
}
|
||||
|
||||
if (hasAttachments2)
|
||||
{
|
||||
foreach (var attachment in attachments.Where(a => Attachments2.ContainsKey(a.Key)))
|
||||
{
|
||||
var attachment2 = Attachments2[attachment.Key];
|
||||
attachment.Value.FileName = attachment2.FileName;
|
||||
attachment.Value.Key = attachment2.Key;
|
||||
}
|
||||
}
|
||||
else if (hasAttachments)
|
||||
{
|
||||
foreach (var attachment in attachments.Where(a => Attachments.ContainsKey(a.Key)))
|
||||
{
|
||||
attachment.Value.FileName = Attachments[attachment.Key];
|
||||
attachment.Value.Key = null;
|
||||
}
|
||||
}
|
||||
|
||||
existingCipher.SetAttachments(attachments);
|
||||
return existingCipher;
|
||||
}
|
||||
|
||||
public Cipher ToOrganizationCipher()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(OrganizationId))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(OrganizationId));
|
||||
}
|
||||
|
||||
return ToCipher(new Cipher
|
||||
{
|
||||
Type = Type,
|
||||
OrganizationId = new Guid(OrganizationId)
|
||||
});
|
||||
}
|
||||
|
||||
public CipherDetails ToOrganizationCipherDetails(Guid orgId)
|
||||
{
|
||||
return ToCipherDetails(new CipherDetails
|
||||
{
|
||||
Type = Type,
|
||||
OrganizationId = orgId,
|
||||
Edit = true
|
||||
});
|
||||
}
|
||||
|
||||
private CipherLoginData ToCipherLoginData()
|
||||
{
|
||||
return new CipherLoginData
|
||||
{
|
||||
Name = Name,
|
||||
Notes = Notes,
|
||||
Fields = Fields?.Select(f => f.ToCipherFieldData()),
|
||||
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
|
||||
|
||||
Uris =
|
||||
Login.Uris?.Where(u => u != null)
|
||||
.Select(u => u.ToCipherLoginUriData()),
|
||||
Username = Login.Username,
|
||||
Password = Login.Password,
|
||||
PasswordRevisionDate = Login.PasswordRevisionDate,
|
||||
Totp = Login.Totp,
|
||||
AutofillOnPageLoad = Login.AutofillOnPageLoad,
|
||||
};
|
||||
}
|
||||
|
||||
private CipherIdentityData ToCipherIdentityData()
|
||||
{
|
||||
return new CipherIdentityData
|
||||
{
|
||||
Name = Name,
|
||||
Notes = Notes,
|
||||
Fields = Fields?.Select(f => f.ToCipherFieldData()),
|
||||
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
|
||||
|
||||
Title = Identity.Title,
|
||||
FirstName = Identity.FirstName,
|
||||
MiddleName = Identity.MiddleName,
|
||||
LastName = Identity.LastName,
|
||||
Address1 = Identity.Address1,
|
||||
Address2 = Identity.Address2,
|
||||
Address3 = Identity.Address3,
|
||||
City = Identity.City,
|
||||
State = Identity.State,
|
||||
PostalCode = Identity.PostalCode,
|
||||
Country = Identity.Country,
|
||||
Company = Identity.Company,
|
||||
Email = Identity.Email,
|
||||
Phone = Identity.Phone,
|
||||
SSN = Identity.SSN,
|
||||
Username = Identity.Username,
|
||||
PassportNumber = Identity.PassportNumber,
|
||||
LicenseNumber = Identity.LicenseNumber,
|
||||
};
|
||||
}
|
||||
|
||||
private CipherCardData ToCipherCardData()
|
||||
{
|
||||
return new CipherCardData
|
||||
{
|
||||
Name = Name,
|
||||
Notes = Notes,
|
||||
Fields = Fields?.Select(f => f.ToCipherFieldData()),
|
||||
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
|
||||
|
||||
CardholderName = Card.CardholderName,
|
||||
Brand = Card.Brand,
|
||||
Number = Card.Number,
|
||||
ExpMonth = Card.ExpMonth,
|
||||
ExpYear = Card.ExpYear,
|
||||
Code = Card.Code,
|
||||
};
|
||||
}
|
||||
|
||||
private CipherSecureNoteData ToCipherSecureNoteData()
|
||||
{
|
||||
return new CipherSecureNoteData
|
||||
{
|
||||
Name = Name,
|
||||
Notes = Notes,
|
||||
Fields = Fields?.Select(f => f.ToCipherFieldData()),
|
||||
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
|
||||
|
||||
Type = SecureNote.Type,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class CipherWithIdRequestModel : CipherRequestModel
|
||||
{
|
||||
[Required]
|
||||
public Guid? Id { get; set; }
|
||||
}
|
||||
|
||||
public class CipherCreateRequestModel : IValidatableObject
|
||||
{
|
||||
public IEnumerable<Guid> CollectionIds { get; set; }
|
||||
[Required]
|
||||
public CipherRequestModel Cipher { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(Cipher.OrganizationId) && (!CollectionIds?.Any() ?? true))
|
||||
{
|
||||
yield return new ValidationResult("You must select at least one collection.",
|
||||
new string[] { nameof(CollectionIds) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CipherShareRequestModel : IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
public IEnumerable<string> CollectionIds { get; set; }
|
||||
[Required]
|
||||
public CipherRequestModel Cipher { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Cipher.OrganizationId))
|
||||
{
|
||||
yield return new ValidationResult("Cipher OrganizationId is required.",
|
||||
new string[] { nameof(Cipher.OrganizationId) });
|
||||
}
|
||||
|
||||
if (!CollectionIds?.Any() ?? true)
|
||||
{
|
||||
yield return new ValidationResult("You must select at least one collection.",
|
||||
new string[] { nameof(CollectionIds) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CipherCollectionsRequestModel
|
||||
{
|
||||
[Required]
|
||||
public IEnumerable<string> CollectionIds { get; set; }
|
||||
}
|
||||
|
||||
public class CipherBulkDeleteRequestModel
|
||||
{
|
||||
[Required]
|
||||
public IEnumerable<string> Ids { get; set; }
|
||||
public string OrganizationId { get; set; }
|
||||
}
|
||||
|
||||
public class CipherBulkRestoreRequestModel
|
||||
{
|
||||
[Required]
|
||||
public IEnumerable<string> Ids { get; set; }
|
||||
}
|
||||
|
||||
public class CipherBulkMoveRequestModel
|
||||
{
|
||||
[Required]
|
||||
public IEnumerable<string> Ids { get; set; }
|
||||
public string FolderId { get; set; }
|
||||
}
|
||||
|
||||
public class CipherBulkShareRequestModel : IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
public IEnumerable<string> CollectionIds { get; set; }
|
||||
[Required]
|
||||
public IEnumerable<CipherWithIdRequestModel> Ciphers { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (!Ciphers?.Any() ?? true)
|
||||
{
|
||||
yield return new ValidationResult("You must select at least one cipher.",
|
||||
new string[] { nameof(Ciphers) });
|
||||
}
|
||||
else
|
||||
{
|
||||
var allHaveIds = true;
|
||||
var organizationIds = new HashSet<string>();
|
||||
foreach (var c in Ciphers)
|
||||
{
|
||||
organizationIds.Add(c.OrganizationId);
|
||||
if (allHaveIds)
|
||||
{
|
||||
allHaveIds = !(!c.Id.HasValue || string.IsNullOrWhiteSpace(c.OrganizationId));
|
||||
}
|
||||
}
|
||||
|
||||
if (!allHaveIds)
|
||||
{
|
||||
yield return new ValidationResult("All Ciphers must have an Id and OrganizationId.",
|
||||
new string[] { nameof(Ciphers) });
|
||||
}
|
||||
else if (organizationIds.Count != 1)
|
||||
{
|
||||
yield return new ValidationResult("All ciphers must be for the same organization.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!CollectionIds?.Any() ?? true)
|
||||
{
|
||||
yield return new ValidationResult("You must select at least one collection.",
|
||||
new string[] { nameof(CollectionIds) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
src/Api/Models/Request/CollectionRequestModel.cs
Normal file
34
src/Api/Models/Request/CollectionRequestModel.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class CollectionRequestModel
|
||||
{
|
||||
[Required]
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Name { get; set; }
|
||||
[StringLength(300)]
|
||||
public string ExternalId { get; set; }
|
||||
public IEnumerable<SelectionReadOnlyRequestModel> Groups { get; set; }
|
||||
|
||||
public Collection ToCollection(Guid orgId)
|
||||
{
|
||||
return ToCollection(new Collection
|
||||
{
|
||||
OrganizationId = orgId
|
||||
});
|
||||
}
|
||||
|
||||
public Collection ToCollection(Collection existingCollection)
|
||||
{
|
||||
existingCollection.Name = Name;
|
||||
existingCollection.ExternalId = ExternalId;
|
||||
return existingCollection;
|
||||
}
|
||||
}
|
||||
}
|
51
src/Api/Models/Request/DeviceRequestModels.cs
Normal file
51
src/Api/Models/Request/DeviceRequestModels.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class DeviceRequestModel
|
||||
{
|
||||
[Required]
|
||||
public DeviceType? Type { get; set; }
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
public string Name { get; set; }
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
public string Identifier { get; set; }
|
||||
[StringLength(255)]
|
||||
public string PushToken { get; set; }
|
||||
|
||||
public Device ToDevice(Guid? userId = null)
|
||||
{
|
||||
return ToDevice(new Device
|
||||
{
|
||||
UserId = userId == null ? default(Guid) : userId.Value
|
||||
});
|
||||
}
|
||||
|
||||
public Device ToDevice(Device existingDevice)
|
||||
{
|
||||
existingDevice.Name = Name;
|
||||
existingDevice.Identifier = Identifier;
|
||||
existingDevice.PushToken = PushToken;
|
||||
existingDevice.Type = Type.Value;
|
||||
|
||||
return existingDevice;
|
||||
}
|
||||
}
|
||||
|
||||
public class DeviceTokenRequestModel
|
||||
{
|
||||
[StringLength(255)]
|
||||
public string PushToken { get; set; }
|
||||
|
||||
public Device ToDevice(Device existingDevice)
|
||||
{
|
||||
existingDevice.PushToken = PushToken;
|
||||
return existingDevice;
|
||||
}
|
||||
}
|
||||
}
|
49
src/Api/Models/Request/EmergencyAccessRequstModels.cs
Normal file
49
src/Api/Models/Request/EmergencyAccessRequstModels.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class EmergencyAccessInviteRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StrictEmailAddress]
|
||||
[StringLength(256)]
|
||||
public string Email { get; set; }
|
||||
[Required]
|
||||
public EmergencyAccessType? Type { get; set; }
|
||||
[Required]
|
||||
public int WaitTimeDays { get; set; }
|
||||
}
|
||||
|
||||
public class EmergencyAccessUpdateRequestModel
|
||||
{
|
||||
[Required]
|
||||
public EmergencyAccessType Type { get; set; }
|
||||
[Required]
|
||||
public int WaitTimeDays { get; set; }
|
||||
public string KeyEncrypted { get; set; }
|
||||
|
||||
public EmergencyAccess ToEmergencyAccess(EmergencyAccess existingEmergencyAccess)
|
||||
{
|
||||
// Ensure we only set keys for a confirmed emergency access.
|
||||
if (!string.IsNullOrWhiteSpace(existingEmergencyAccess.KeyEncrypted) && !string.IsNullOrWhiteSpace(KeyEncrypted))
|
||||
{
|
||||
existingEmergencyAccess.KeyEncrypted = KeyEncrypted;
|
||||
}
|
||||
existingEmergencyAccess.Type = Type;
|
||||
existingEmergencyAccess.WaitTimeDays = WaitTimeDays;
|
||||
return existingEmergencyAccess;
|
||||
}
|
||||
}
|
||||
|
||||
public class EmergencyAccessPasswordRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string NewMasterPasswordHash { get; set; }
|
||||
[Required]
|
||||
public string Key { get; set; }
|
||||
}
|
||||
}
|
34
src/Api/Models/Request/FolderRequestModel.cs
Normal file
34
src/Api/Models/Request/FolderRequestModel.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class FolderRequestModel
|
||||
{
|
||||
[Required]
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string Name { get; set; }
|
||||
|
||||
public Folder ToFolder(Guid userId)
|
||||
{
|
||||
return ToFolder(new Folder
|
||||
{
|
||||
UserId = userId
|
||||
});
|
||||
}
|
||||
|
||||
public Folder ToFolder(Folder existingFolder)
|
||||
{
|
||||
existingFolder.Name = Name;
|
||||
return existingFolder;
|
||||
}
|
||||
}
|
||||
|
||||
public class FolderWithIdRequestModel : FolderRequestModel
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
}
|
||||
}
|
35
src/Api/Models/Request/GroupRequestModel.cs
Normal file
35
src/Api/Models/Request/GroupRequestModel.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class GroupRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string Name { get; set; }
|
||||
[Required]
|
||||
public bool? AccessAll { get; set; }
|
||||
[StringLength(300)]
|
||||
public string ExternalId { get; set; }
|
||||
public IEnumerable<SelectionReadOnlyRequestModel> Collections { get; set; }
|
||||
|
||||
public Group ToGroup(Guid orgId)
|
||||
{
|
||||
return ToGroup(new Group
|
||||
{
|
||||
OrganizationId = orgId
|
||||
});
|
||||
}
|
||||
|
||||
public Group ToGroup(Group existingGroup)
|
||||
{
|
||||
existingGroup.Name = Name;
|
||||
existingGroup.AccessAll = AccessAll.Value;
|
||||
existingGroup.ExternalId = ExternalId;
|
||||
return existingGroup;
|
||||
}
|
||||
}
|
||||
}
|
21
src/Api/Models/Request/IapCheckRequestModel.cs
Normal file
21
src/Api/Models/Request/IapCheckRequestModel.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Enums = Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class IapCheckRequestModel : IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
public Enums.PaymentMethodType? PaymentMethodType { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (PaymentMethodType != Enums.PaymentMethodType.AppleInApp)
|
||||
{
|
||||
yield return new ValidationResult("Not a supported in-app purchase payment method.",
|
||||
new string[] { nameof(PaymentMethodType) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
src/Api/Models/Request/InstallationRequestModel.cs
Normal file
24
src/Api/Models/Request/InstallationRequestModel.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class InstallationRequestModel
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
[StringLength(256)]
|
||||
public string Email { get; set; }
|
||||
|
||||
public Installation ToInstallation()
|
||||
{
|
||||
return new Installation
|
||||
{
|
||||
Key = CoreHelpers.SecureRandomString(20),
|
||||
Email = Email,
|
||||
Enabled = true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
11
src/Api/Models/Request/LicenseRequestModel.cs
Normal file
11
src/Api/Models/Request/LicenseRequestModel.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Bit.Api.Models.Request
|
||||
{
|
||||
public class LicenseRequestModel
|
||||
{
|
||||
[Required]
|
||||
public IFormFile License { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.Api.Models.Request.Organizations
|
||||
{
|
||||
public class ImportOrganizationCiphersRequestModel
|
||||
{
|
||||
public CollectionRequestModel[] Collections { get; set; }
|
||||
public CipherRequestModel[] Ciphers { get; set; }
|
||||
public KeyValuePair<int, int>[] CollectionRelationships { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Business;
|
||||
using Table = Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Request.Organizations
|
||||
{
|
||||
public class ImportOrganizationUsersRequestModel
|
||||
{
|
||||
public Group[] Groups { get; set; }
|
||||
public User[] Users { get; set; }
|
||||
public bool OverwriteExisting { get; set; }
|
||||
public bool LargeImport { get; set; }
|
||||
|
||||
public class Group
|
||||
{
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string Name { get; set; }
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string ExternalId { get; set; }
|
||||
public IEnumerable<string> Users { get; set; }
|
||||
|
||||
public ImportedGroup ToImportedGroup(Guid organizationId)
|
||||
{
|
||||
var importedGroup = new ImportedGroup
|
||||
{
|
||||
Group = new Table.Group
|
||||
{
|
||||
OrganizationId = organizationId,
|
||||
Name = Name,
|
||||
ExternalId = ExternalId
|
||||
},
|
||||
ExternalUserIds = new HashSet<string>(Users)
|
||||
};
|
||||
|
||||
return importedGroup;
|
||||
}
|
||||
}
|
||||
|
||||
public class User : IValidatableObject
|
||||
{
|
||||
[EmailAddress]
|
||||
[StringLength(256)]
|
||||
public string Email { get; set; }
|
||||
public bool Deleted { get; set; }
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
public string ExternalId { get; set; }
|
||||
|
||||
public ImportedOrganizationUser ToImportedOrganizationUser()
|
||||
{
|
||||
var importedUser = new ImportedOrganizationUser
|
||||
{
|
||||
Email = Email.ToLowerInvariant(),
|
||||
ExternalId = ExternalId
|
||||
};
|
||||
|
||||
return importedUser;
|
||||
}
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Email) && !Deleted)
|
||||
{
|
||||
yield return new ValidationResult("Email is required for enabled users.", new string[] { nameof(Email) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models.Request.Organizations
|
||||
{
|
||||
public class OrganizationCreateLicenseRequestModel : LicenseRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string Key { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string CollectionName { get; set; }
|
||||
public OrganizationKeysRequestModel Keys { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models.Request.Organizations
|
||||
{
|
||||
public class OrganizationCreateRequestModel : IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
public string Name { get; set; }
|
||||
[StringLength(50)]
|
||||
public string BusinessName { get; set; }
|
||||
[Required]
|
||||
[StringLength(256)]
|
||||
[EmailAddress]
|
||||
public string BillingEmail { get; set; }
|
||||
public PlanType PlanType { get; set; }
|
||||
[Required]
|
||||
public string Key { get; set; }
|
||||
public OrganizationKeysRequestModel Keys { get; set; }
|
||||
public PaymentMethodType? PaymentMethodType { get; set; }
|
||||
public string PaymentToken { get; set; }
|
||||
[Range(0, int.MaxValue)]
|
||||
public int AdditionalSeats { get; set; }
|
||||
[Range(0, 99)]
|
||||
public short? AdditionalStorageGb { get; set; }
|
||||
public bool PremiumAccessAddon { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string CollectionName { get; set; }
|
||||
public string TaxIdNumber { get; set; }
|
||||
public string BillingAddressLine1 { get; set; }
|
||||
public string BillingAddressLine2 { get; set; }
|
||||
public string BillingAddressCity { get; set; }
|
||||
public string BillingAddressState { get; set; }
|
||||
public string BillingAddressPostalCode { get; set; }
|
||||
[StringLength(2)]
|
||||
public string BillingAddressCountry { get; set; }
|
||||
public int? MaxAutoscaleSeats { get; set; }
|
||||
|
||||
public virtual OrganizationSignup ToOrganizationSignup(User user)
|
||||
{
|
||||
var orgSignup = new OrganizationSignup
|
||||
{
|
||||
Owner = user,
|
||||
OwnerKey = Key,
|
||||
Name = Name,
|
||||
Plan = PlanType,
|
||||
PaymentMethodType = PaymentMethodType,
|
||||
PaymentToken = PaymentToken,
|
||||
AdditionalSeats = AdditionalSeats,
|
||||
MaxAutoscaleSeats = MaxAutoscaleSeats,
|
||||
AdditionalStorageGb = AdditionalStorageGb.GetValueOrDefault(0),
|
||||
PremiumAccessAddon = PremiumAccessAddon,
|
||||
BillingEmail = BillingEmail,
|
||||
BusinessName = BusinessName,
|
||||
CollectionName = CollectionName,
|
||||
TaxInfo = new TaxInfo
|
||||
{
|
||||
TaxIdNumber = TaxIdNumber,
|
||||
BillingAddressLine1 = BillingAddressLine1,
|
||||
BillingAddressLine2 = BillingAddressLine2,
|
||||
BillingAddressCity = BillingAddressCity,
|
||||
BillingAddressState = BillingAddressState,
|
||||
BillingAddressPostalCode = BillingAddressPostalCode,
|
||||
BillingAddressCountry = BillingAddressCountry,
|
||||
},
|
||||
};
|
||||
|
||||
Keys?.ToOrganizationSignup(orgSignup);
|
||||
|
||||
return orgSignup;
|
||||
}
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (PlanType != PlanType.Free && string.IsNullOrWhiteSpace(PaymentToken))
|
||||
{
|
||||
yield return new ValidationResult("Payment required.", new string[] { nameof(PaymentToken) });
|
||||
}
|
||||
if (PlanType != PlanType.Free && !PaymentMethodType.HasValue)
|
||||
{
|
||||
yield return new ValidationResult("Payment method type required.",
|
||||
new string[] { nameof(PaymentMethodType) });
|
||||
}
|
||||
if (PlanType != PlanType.Free && string.IsNullOrWhiteSpace(BillingAddressCountry))
|
||||
{
|
||||
yield return new ValidationResult("Country required.",
|
||||
new string[] { nameof(BillingAddressCountry) });
|
||||
}
|
||||
if (PlanType != PlanType.Free && BillingAddressCountry == "US" &&
|
||||
string.IsNullOrWhiteSpace(BillingAddressPostalCode))
|
||||
{
|
||||
yield return new ValidationResult("Zip / postal code is required.",
|
||||
new string[] { nameof(BillingAddressPostalCode) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Api.Models.Request.Organizations
|
||||
{
|
||||
public class OrganizationKeysRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string PublicKey { get; set; }
|
||||
[Required]
|
||||
public string EncryptedPrivateKey { get; set; }
|
||||
|
||||
public OrganizationSignup ToOrganizationSignup(OrganizationSignup existingSignup)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(existingSignup.PublicKey))
|
||||
{
|
||||
existingSignup.PublicKey = PublicKey;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(existingSignup.PrivateKey))
|
||||
{
|
||||
existingSignup.PrivateKey = EncryptedPrivateKey;
|
||||
}
|
||||
|
||||
return existingSignup;
|
||||
}
|
||||
|
||||
public OrganizationUpgrade ToOrganizationUpgrade(OrganizationUpgrade existingUpgrade)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(existingUpgrade.PublicKey))
|
||||
{
|
||||
existingUpgrade.PublicKey = PublicKey;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(existingUpgrade.PrivateKey))
|
||||
{
|
||||
existingUpgrade.PrivateKey = EncryptedPrivateKey;
|
||||
}
|
||||
|
||||
return existingUpgrade;
|
||||
}
|
||||
|
||||
public Organization ToOrganization(Organization existingOrg)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(existingOrg.PublicKey))
|
||||
{
|
||||
existingOrg.PublicKey = PublicKey;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(existingOrg.PrivateKey))
|
||||
{
|
||||
existingOrg.PrivateKey = EncryptedPrivateKey;
|
||||
}
|
||||
|
||||
return existingOrg;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Organizations
|
||||
{
|
||||
public class OrganizationSeatRequestModel : IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
public int? SeatAdjustment { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (SeatAdjustment == 0)
|
||||
{
|
||||
yield return new ValidationResult("Seat adjustment cannot be 0.", new string[] { nameof(SeatAdjustment) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Api.Models.Request.Organizations
|
||||
{
|
||||
public class OrganizationSponsorshipRedeemRequestModel
|
||||
{
|
||||
[Required]
|
||||
public PlanSponsorshipType PlanSponsorshipType { get; set; }
|
||||
[Required]
|
||||
public Guid SponsoredOrganizationId { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Models.Request.Organizations
|
||||
{
|
||||
public class OrganizationSponsorshipRequestModel
|
||||
{
|
||||
[Required]
|
||||
public PlanSponsorshipType PlanSponsorshipType { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(256)]
|
||||
[StrictEmailAddress]
|
||||
public string SponsoredEmail { get; set; }
|
||||
|
||||
[StringLength(256)]
|
||||
public string FriendlyName { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,239 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text.RegularExpressions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Sso;
|
||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||
using U2F.Core.Utils;
|
||||
|
||||
namespace Bit.Api.Models.Request.Organizations
|
||||
{
|
||||
public class OrganizationSsoRequestModel
|
||||
{
|
||||
[Required]
|
||||
public bool Enabled { get; set; }
|
||||
[Required]
|
||||
public SsoConfigurationDataRequest Data { get; set; }
|
||||
|
||||
public SsoConfig ToSsoConfig(Guid organizationId)
|
||||
{
|
||||
return ToSsoConfig(new SsoConfig { OrganizationId = organizationId });
|
||||
}
|
||||
|
||||
public SsoConfig ToSsoConfig(SsoConfig existingConfig)
|
||||
{
|
||||
existingConfig.Enabled = Enabled;
|
||||
var configurationData = Data.ToConfigurationData();
|
||||
existingConfig.SetData(configurationData);
|
||||
return existingConfig;
|
||||
}
|
||||
}
|
||||
|
||||
public class SsoConfigurationDataRequest : IValidatableObject
|
||||
{
|
||||
public SsoConfigurationDataRequest() {}
|
||||
|
||||
[Required]
|
||||
public SsoType ConfigType { get; set; }
|
||||
|
||||
public bool KeyConnectorEnabled { get; set; }
|
||||
public string KeyConnectorUrl { get; set; }
|
||||
|
||||
// OIDC
|
||||
public string Authority { get; set; }
|
||||
public string ClientId { get; set; }
|
||||
public string ClientSecret { get; set; }
|
||||
public string MetadataAddress { get; set; }
|
||||
public OpenIdConnectRedirectBehavior RedirectBehavior { get; set; }
|
||||
public bool? GetClaimsFromUserInfoEndpoint { get; set; }
|
||||
public string AdditionalScopes { get; set; }
|
||||
public string AdditionalUserIdClaimTypes { get; set; }
|
||||
public string AdditionalEmailClaimTypes { get; set; }
|
||||
public string AdditionalNameClaimTypes { get; set; }
|
||||
public string AcrValues { get; set; }
|
||||
public string ExpectedReturnAcrValue { get; set; }
|
||||
|
||||
// SAML2 SP
|
||||
public Saml2NameIdFormat SpNameIdFormat { get; set; }
|
||||
public string SpOutboundSigningAlgorithm { get; set; }
|
||||
public Saml2SigningBehavior SpSigningBehavior { get; set; }
|
||||
public bool? SpWantAssertionsSigned { get; set; }
|
||||
public bool? SpValidateCertificates { get; set; }
|
||||
public string SpMinIncomingSigningAlgorithm { get; set; }
|
||||
|
||||
// SAML2 IDP
|
||||
public string IdpEntityId { get; set; }
|
||||
public Saml2BindingType IdpBindingType { get; set; }
|
||||
public string IdpSingleSignOnServiceUrl { get; set; }
|
||||
public string IdpSingleLogoutServiceUrl { get; set; }
|
||||
public string IdpArtifactResolutionServiceUrl { get; set; }
|
||||
public string IdpX509PublicCert { get; set; }
|
||||
public string IdpOutboundSigningAlgorithm { get; set; }
|
||||
public bool? IdpAllowUnsolicitedAuthnResponse { get; set; }
|
||||
public bool? IdpDisableOutboundLogoutRequests { get; set; }
|
||||
public bool? IdpWantAuthnRequestsSigned { get; set; }
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext context)
|
||||
{
|
||||
var i18nService = context.GetService(typeof(II18nService)) as I18nService;
|
||||
|
||||
if (ConfigType == SsoType.OpenIdConnect)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Authority))
|
||||
{
|
||||
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("AuthorityValidationError"),
|
||||
new[] { nameof(Authority) });
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ClientId))
|
||||
{
|
||||
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("ClientIdValidationError"),
|
||||
new[] { nameof(ClientId) });
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ClientSecret))
|
||||
{
|
||||
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("ClientSecretValidationError"),
|
||||
new[] { nameof(ClientSecret) });
|
||||
}
|
||||
}
|
||||
else if (ConfigType == SsoType.Saml2)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(IdpEntityId))
|
||||
{
|
||||
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpEntityIdValidationError"),
|
||||
new[] { nameof(IdpEntityId) });
|
||||
}
|
||||
|
||||
if (IdpBindingType == Saml2BindingType.Artifact && string.IsNullOrWhiteSpace(IdpArtifactResolutionServiceUrl))
|
||||
{
|
||||
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("Saml2BindingTypeValidationError"),
|
||||
new[] { nameof(IdpArtifactResolutionServiceUrl) });
|
||||
}
|
||||
|
||||
if (!Uri.IsWellFormedUriString(IdpEntityId, UriKind.Absolute) && string.IsNullOrWhiteSpace(IdpSingleSignOnServiceUrl))
|
||||
{
|
||||
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleSignOnServiceUrlValidationError"),
|
||||
new[] { nameof(IdpSingleSignOnServiceUrl) });
|
||||
}
|
||||
|
||||
if (InvalidServiceUrl(IdpSingleSignOnServiceUrl))
|
||||
{
|
||||
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleSignOnServiceUrlInvalid"),
|
||||
new[] { nameof(IdpSingleSignOnServiceUrl) });
|
||||
}
|
||||
|
||||
if (InvalidServiceUrl(IdpArtifactResolutionServiceUrl))
|
||||
{
|
||||
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpArtifactResolutionServiceUrlInvalid"),
|
||||
new[] { nameof(IdpArtifactResolutionServiceUrl) });
|
||||
}
|
||||
|
||||
if (InvalidServiceUrl(IdpSingleLogoutServiceUrl))
|
||||
{
|
||||
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleLogoutServiceUrlInvalid"),
|
||||
new[] { nameof(IdpSingleLogoutServiceUrl) });
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(IdpX509PublicCert))
|
||||
{
|
||||
// Validate the certificate is in a valid format
|
||||
ValidationResult failedResult = null;
|
||||
try
|
||||
{
|
||||
var certData = StripPemCertificateElements(IdpX509PublicCert).Base64StringToByteArray();
|
||||
new X509Certificate2(certData);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertInvalidFormatValidationError"),
|
||||
new[] { nameof(IdpX509PublicCert) });
|
||||
}
|
||||
catch (CryptographicException cryptoEx)
|
||||
{
|
||||
failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertCryptographicExceptionValidationError", cryptoEx.Message),
|
||||
new[] { nameof(IdpX509PublicCert) });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertValidationError", ex.Message),
|
||||
new[] { nameof(IdpX509PublicCert) });
|
||||
}
|
||||
if (failedResult != null)
|
||||
{
|
||||
yield return failedResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SsoConfigurationData ToConfigurationData()
|
||||
{
|
||||
return new SsoConfigurationData
|
||||
{
|
||||
ConfigType = ConfigType,
|
||||
KeyConnectorEnabled = KeyConnectorEnabled,
|
||||
KeyConnectorUrl = KeyConnectorUrl,
|
||||
Authority = Authority,
|
||||
ClientId = ClientId,
|
||||
ClientSecret = ClientSecret,
|
||||
MetadataAddress = MetadataAddress,
|
||||
GetClaimsFromUserInfoEndpoint = GetClaimsFromUserInfoEndpoint.GetValueOrDefault(),
|
||||
RedirectBehavior = RedirectBehavior,
|
||||
IdpEntityId = IdpEntityId,
|
||||
IdpBindingType = IdpBindingType,
|
||||
IdpSingleSignOnServiceUrl = IdpSingleSignOnServiceUrl,
|
||||
IdpSingleLogoutServiceUrl = IdpSingleLogoutServiceUrl,
|
||||
IdpArtifactResolutionServiceUrl = IdpArtifactResolutionServiceUrl,
|
||||
IdpX509PublicCert = StripPemCertificateElements(IdpX509PublicCert),
|
||||
IdpOutboundSigningAlgorithm = IdpOutboundSigningAlgorithm,
|
||||
IdpAllowUnsolicitedAuthnResponse = IdpAllowUnsolicitedAuthnResponse.GetValueOrDefault(),
|
||||
IdpDisableOutboundLogoutRequests = IdpDisableOutboundLogoutRequests.GetValueOrDefault(),
|
||||
IdpWantAuthnRequestsSigned = IdpWantAuthnRequestsSigned.GetValueOrDefault(),
|
||||
SpNameIdFormat = SpNameIdFormat,
|
||||
SpOutboundSigningAlgorithm = SpOutboundSigningAlgorithm ?? SamlSigningAlgorithms.Sha256,
|
||||
SpSigningBehavior = SpSigningBehavior,
|
||||
SpWantAssertionsSigned = SpWantAssertionsSigned.GetValueOrDefault(),
|
||||
SpValidateCertificates = SpValidateCertificates.GetValueOrDefault(),
|
||||
SpMinIncomingSigningAlgorithm = SpMinIncomingSigningAlgorithm,
|
||||
AdditionalScopes = AdditionalScopes,
|
||||
AdditionalUserIdClaimTypes = AdditionalUserIdClaimTypes,
|
||||
AdditionalEmailClaimTypes = AdditionalEmailClaimTypes,
|
||||
AdditionalNameClaimTypes = AdditionalNameClaimTypes,
|
||||
AcrValues = AcrValues,
|
||||
ExpectedReturnAcrValue = ExpectedReturnAcrValue,
|
||||
};
|
||||
}
|
||||
|
||||
private string StripPemCertificateElements(string certificateText)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(certificateText))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return Regex.Replace(certificateText,
|
||||
@"(((BEGIN|END) CERTIFICATE)|([\-\n\r\t\s\f]))",
|
||||
string.Empty,
|
||||
RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
}
|
||||
|
||||
private bool InvalidServiceUrl(string url)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!url.StartsWith("http://") && !url.StartsWith("https://"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return Regex.IsMatch(url, "[<>\"]");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Api.Models.Request.Organizations
|
||||
{
|
||||
public class OrganizationSubscriptionUpdateRequestModel
|
||||
{
|
||||
[Required]
|
||||
public int SeatAdjustment { get; set; }
|
||||
public int? MaxAutoscaleSeats { get; set; }
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user