1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 23:52:50 -05:00

Run formatting (#2230)

This commit is contained in:
Justin Baur
2022-08-29 16:06:55 -04:00
committed by GitHub
parent 9b7aef0763
commit 7f5f010e1e
1205 changed files with 73813 additions and 75022 deletions

View File

@ -1,27 +1,26 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Entities;
namespace Bit.Core.Models.Api.Request.Accounts
namespace Bit.Core.Models.Api.Request.Accounts;
public class KeysRequestModel
{
public class KeysRequestModel
public string PublicKey { get; set; }
[Required]
public string EncryptedPrivateKey { get; set; }
public User ToUser(User existingUser)
{
public string PublicKey { get; set; }
[Required]
public string EncryptedPrivateKey { get; set; }
public User ToUser(User existingUser)
if (string.IsNullOrWhiteSpace(existingUser.PublicKey) && !string.IsNullOrWhiteSpace(PublicKey))
{
if (string.IsNullOrWhiteSpace(existingUser.PublicKey) && !string.IsNullOrWhiteSpace(PublicKey))
{
existingUser.PublicKey = PublicKey;
}
if (string.IsNullOrWhiteSpace(existingUser.PrivateKey))
{
existingUser.PrivateKey = EncryptedPrivateKey;
}
return existingUser;
existingUser.PublicKey = PublicKey;
}
if (string.IsNullOrWhiteSpace(existingUser.PrivateKey))
{
existingUser.PrivateKey = EncryptedPrivateKey;
}
return existingUser;
}
}

View File

@ -1,12 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Core.Models.Api.Request.Accounts
namespace Bit.Core.Models.Api.Request.Accounts;
public class PreloginRequestModel
{
public class PreloginRequestModel
{
[Required]
[EmailAddress]
[StringLength(256)]
public string Email { get; set; }
}
[Required]
[EmailAddress]
[StringLength(256)]
public string Email { get; set; }
}

View File

@ -4,74 +4,73 @@ using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Utilities;
namespace Bit.Core.Models.Api.Request.Accounts
namespace Bit.Core.Models.Api.Request.Accounts;
public class RegisterRequestModel : IValidatableObject, ICaptchaProtectedModel
{
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()
{
[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
{
var user = new User
{
Name = Name,
Email = Email,
MasterPasswordHint = MasterPasswordHint,
Kdf = Kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256),
KdfIterations = KdfIterations.GetValueOrDefault(5000),
};
Name = Name,
Email = Email,
MasterPasswordHint = MasterPasswordHint,
Kdf = Kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256),
KdfIterations = KdfIterations.GetValueOrDefault(5000),
};
if (ReferenceData != null)
{
user.ReferenceData = JsonSerializer.Serialize(ReferenceData);
}
if (Key != null)
{
user.Key = Key;
}
if (Keys != null)
{
Keys.ToUser(user);
}
return user;
if (ReferenceData != null)
{
user.ReferenceData = JsonSerializer.Serialize(ReferenceData);
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
if (Key != null)
{
if (Kdf.HasValue && KdfIterations.HasValue)
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)
{
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;
}
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;
}
}
}

View File

@ -1,7 +1,6 @@
namespace Bit.Core.Models.Api
namespace Bit.Core.Models.Api;
public interface ICaptchaProtectedModel
{
public interface ICaptchaProtectedModel
{
string CaptchaResponse { get; set; }
}
string CaptchaResponse { get; set; }
}

View File

@ -2,55 +2,54 @@
using Bit.Core.Enums;
using Bit.Core.Models.Data.Organizations.OrganizationSponsorships;
namespace Bit.Core.Models.Api.Request.OrganizationSponsorships
namespace Bit.Core.Models.Api.Request.OrganizationSponsorships;
public class OrganizationSponsorshipRequestModel
{
public class OrganizationSponsorshipRequestModel
public Guid SponsoringOrganizationUserId { get; set; }
public string FriendlyName { get; set; }
public string OfferedToEmail { get; set; }
public PlanSponsorshipType PlanSponsorshipType { get; set; }
public DateTime? LastSyncDate { get; set; }
public DateTime? ValidUntil { get; set; }
public bool ToDelete { get; set; }
public OrganizationSponsorshipRequestModel() { }
public OrganizationSponsorshipRequestModel(OrganizationSponsorshipData sponsorshipData)
{
public Guid SponsoringOrganizationUserId { get; set; }
public string FriendlyName { get; set; }
public string OfferedToEmail { get; set; }
public PlanSponsorshipType PlanSponsorshipType { get; set; }
public DateTime? LastSyncDate { get; set; }
public DateTime? ValidUntil { get; set; }
public bool ToDelete { get; set; }
SponsoringOrganizationUserId = sponsorshipData.SponsoringOrganizationUserId;
FriendlyName = sponsorshipData.FriendlyName;
OfferedToEmail = sponsorshipData.OfferedToEmail;
PlanSponsorshipType = sponsorshipData.PlanSponsorshipType;
LastSyncDate = sponsorshipData.LastSyncDate;
ValidUntil = sponsorshipData.ValidUntil;
ToDelete = sponsorshipData.ToDelete;
}
public OrganizationSponsorshipRequestModel() { }
public OrganizationSponsorshipRequestModel(OrganizationSponsorship sponsorship)
{
SponsoringOrganizationUserId = sponsorship.SponsoringOrganizationUserId;
FriendlyName = sponsorship.FriendlyName;
OfferedToEmail = sponsorship.OfferedToEmail;
PlanSponsorshipType = sponsorship.PlanSponsorshipType.GetValueOrDefault();
LastSyncDate = sponsorship.LastSyncDate;
ValidUntil = sponsorship.ValidUntil;
ToDelete = sponsorship.ToDelete;
}
public OrganizationSponsorshipRequestModel(OrganizationSponsorshipData sponsorshipData)
public OrganizationSponsorshipData ToOrganizationSponsorship()
{
return new OrganizationSponsorshipData
{
SponsoringOrganizationUserId = sponsorshipData.SponsoringOrganizationUserId;
FriendlyName = sponsorshipData.FriendlyName;
OfferedToEmail = sponsorshipData.OfferedToEmail;
PlanSponsorshipType = sponsorshipData.PlanSponsorshipType;
LastSyncDate = sponsorshipData.LastSyncDate;
ValidUntil = sponsorshipData.ValidUntil;
ToDelete = sponsorshipData.ToDelete;
}
SponsoringOrganizationUserId = SponsoringOrganizationUserId,
FriendlyName = FriendlyName,
OfferedToEmail = OfferedToEmail,
PlanSponsorshipType = PlanSponsorshipType,
LastSyncDate = LastSyncDate,
ValidUntil = ValidUntil,
ToDelete = ToDelete,
};
public OrganizationSponsorshipRequestModel(OrganizationSponsorship sponsorship)
{
SponsoringOrganizationUserId = sponsorship.SponsoringOrganizationUserId;
FriendlyName = sponsorship.FriendlyName;
OfferedToEmail = sponsorship.OfferedToEmail;
PlanSponsorshipType = sponsorship.PlanSponsorshipType.GetValueOrDefault();
LastSyncDate = sponsorship.LastSyncDate;
ValidUntil = sponsorship.ValidUntil;
ToDelete = sponsorship.ToDelete;
}
public OrganizationSponsorshipData ToOrganizationSponsorship()
{
return new OrganizationSponsorshipData
{
SponsoringOrganizationUserId = SponsoringOrganizationUserId,
FriendlyName = FriendlyName,
OfferedToEmail = OfferedToEmail,
PlanSponsorshipType = PlanSponsorshipType,
LastSyncDate = LastSyncDate,
ValidUntil = ValidUntil,
ToDelete = ToDelete,
};
}
}
}

View File

@ -1,40 +1,39 @@
using Bit.Core.Models.Data.Organizations.OrganizationSponsorships;
namespace Bit.Core.Models.Api.Request.OrganizationSponsorships
namespace Bit.Core.Models.Api.Request.OrganizationSponsorships;
public class OrganizationSponsorshipSyncRequestModel
{
public class OrganizationSponsorshipSyncRequestModel
public string BillingSyncKey { get; set; }
public Guid SponsoringOrganizationCloudId { get; set; }
public IEnumerable<OrganizationSponsorshipRequestModel> SponsorshipsBatch { get; set; }
public OrganizationSponsorshipSyncRequestModel() { }
public OrganizationSponsorshipSyncRequestModel(IEnumerable<OrganizationSponsorshipRequestModel> sponsorshipsBatch)
{
public string BillingSyncKey { get; set; }
public Guid SponsoringOrganizationCloudId { get; set; }
public IEnumerable<OrganizationSponsorshipRequestModel> SponsorshipsBatch { get; set; }
public OrganizationSponsorshipSyncRequestModel() { }
public OrganizationSponsorshipSyncRequestModel(IEnumerable<OrganizationSponsorshipRequestModel> sponsorshipsBatch)
{
SponsorshipsBatch = sponsorshipsBatch;
}
public OrganizationSponsorshipSyncRequestModel(OrganizationSponsorshipSyncData syncData)
{
if (syncData == null)
{
return;
}
BillingSyncKey = syncData.BillingSyncKey;
SponsoringOrganizationCloudId = syncData.SponsoringOrganizationCloudId;
SponsorshipsBatch = syncData.SponsorshipsBatch.Select(o => new OrganizationSponsorshipRequestModel(o));
}
public OrganizationSponsorshipSyncData ToOrganizationSponsorshipSync()
{
return new OrganizationSponsorshipSyncData()
{
BillingSyncKey = BillingSyncKey,
SponsoringOrganizationCloudId = SponsoringOrganizationCloudId,
SponsorshipsBatch = SponsorshipsBatch.Select(o => o.ToOrganizationSponsorship())
};
}
SponsorshipsBatch = sponsorshipsBatch;
}
public OrganizationSponsorshipSyncRequestModel(OrganizationSponsorshipSyncData syncData)
{
if (syncData == null)
{
return;
}
BillingSyncKey = syncData.BillingSyncKey;
SponsoringOrganizationCloudId = syncData.SponsoringOrganizationCloudId;
SponsorshipsBatch = syncData.SponsorshipsBatch.Select(o => new OrganizationSponsorshipRequestModel(o));
}
public OrganizationSponsorshipSyncData ToOrganizationSponsorshipSync()
{
return new OrganizationSponsorshipSyncData()
{
BillingSyncKey = BillingSyncKey,
SponsoringOrganizationCloudId = SponsoringOrganizationCloudId,
SponsorshipsBatch = SponsorshipsBatch.Select(o => o.ToOrganizationSponsorship())
};
}
}

View File

@ -1,19 +1,18 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Enums;
namespace Bit.Core.Models.Api
namespace Bit.Core.Models.Api;
public class PushRegistrationRequestModel
{
public class PushRegistrationRequestModel
{
[Required]
public string DeviceId { get; set; }
[Required]
public string PushToken { get; set; }
[Required]
public string UserId { get; set; }
[Required]
public DeviceType Type { get; set; }
[Required]
public string Identifier { get; set; }
}
[Required]
public string DeviceId { get; set; }
[Required]
public string PushToken { get; set; }
[Required]
public string UserId { get; set; }
[Required]
public DeviceType Type { get; set; }
[Required]
public string Identifier { get; set; }
}

View File

@ -1,25 +1,24 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Enums;
namespace Bit.Core.Models.Api
{
public class PushSendRequestModel : IValidatableObject
{
public string UserId { get; set; }
public string OrganizationId { get; set; }
public string DeviceId { get; set; }
public string Identifier { get; set; }
[Required]
public PushType? Type { get; set; }
[Required]
public object Payload { get; set; }
namespace Bit.Core.Models.Api;
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
public class PushSendRequestModel : IValidatableObject
{
public string UserId { get; set; }
public string OrganizationId { get; set; }
public string DeviceId { get; set; }
public string Identifier { get; set; }
[Required]
public PushType? Type { get; set; }
[Required]
public object Payload { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrWhiteSpace(UserId) && string.IsNullOrWhiteSpace(OrganizationId))
{
if (string.IsNullOrWhiteSpace(UserId) && string.IsNullOrWhiteSpace(OrganizationId))
{
yield return new ValidationResult($"{nameof(UserId)} or {nameof(OrganizationId)} is required.");
}
yield return new ValidationResult($"{nameof(UserId)} or {nameof(OrganizationId)} is required.");
}
}
}

View File

@ -1,21 +1,20 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Core.Models.Api
namespace Bit.Core.Models.Api;
public class PushUpdateRequestModel
{
public class PushUpdateRequestModel
public PushUpdateRequestModel()
{ }
public PushUpdateRequestModel(IEnumerable<string> deviceIds, string organizationId)
{
public PushUpdateRequestModel()
{ }
public PushUpdateRequestModel(IEnumerable<string> deviceIds, string organizationId)
{
DeviceIds = deviceIds;
OrganizationId = organizationId;
}
[Required]
public IEnumerable<string> DeviceIds { get; set; }
[Required]
public string OrganizationId { get; set; }
DeviceIds = deviceIds;
OrganizationId = organizationId;
}
[Required]
public IEnumerable<string> DeviceIds { get; set; }
[Required]
public string OrganizationId { get; set; }
}

View File

@ -1,17 +1,16 @@
using Bit.Core.Enums;
using Bit.Core.Models.Data;
namespace Bit.Core.Models.Api.Response.Accounts
{
public class PreloginResponseModel
{
public PreloginResponseModel(UserKdfInformation kdfInformation)
{
Kdf = kdfInformation.Kdf;
KdfIterations = kdfInformation.KdfIterations;
}
namespace Bit.Core.Models.Api.Response.Accounts;
public KdfType Kdf { get; set; }
public int KdfIterations { get; set; }
public class PreloginResponseModel
{
public PreloginResponseModel(UserKdfInformation kdfInformation)
{
Kdf = kdfInformation.Kdf;
KdfIterations = kdfInformation.KdfIterations;
}
public KdfType Kdf { get; set; }
public int KdfIterations { get; set; }
}

View File

@ -1,74 +1,73 @@
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace Bit.Core.Models.Api
namespace Bit.Core.Models.Api;
public class ErrorResponseModel : ResponseModel
{
public class ErrorResponseModel : ResponseModel
public ErrorResponseModel()
: base("error")
{ }
public ErrorResponseModel(string message)
: this()
{
public ErrorResponseModel()
: base("error")
{ }
public ErrorResponseModel(string message)
: this()
{
Message = message;
}
public ErrorResponseModel(ModelStateDictionary modelState)
: this()
{
Message = "The model state is invalid.";
ValidationErrors = 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);
ValidationErrors.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)
: this()
{
Message = message;
ValidationErrors = errors;
}
public string Message { get; set; }
public Dictionary<string, IEnumerable<string>> ValidationErrors { get; set; }
// For use in development environments.
public string ExceptionMessage { get; set; }
public string ExceptionStackTrace { get; set; }
public string InnerExceptionMessage { get; set; }
Message = message;
}
public ErrorResponseModel(ModelStateDictionary modelState)
: this()
{
Message = "The model state is invalid.";
ValidationErrors = 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);
ValidationErrors.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)
: this()
{
Message = message;
ValidationErrors = errors;
}
public string Message { get; set; }
public Dictionary<string, IEnumerable<string>> ValidationErrors { get; set; }
// For use in development environments.
public string ExceptionMessage { get; set; }
public string ExceptionStackTrace { get; set; }
public string InnerExceptionMessage { get; set; }
}

View File

@ -1,48 +1,47 @@
using Bit.Core.Enums;
using Bit.Core.Models.Data.Organizations.OrganizationSponsorships;
namespace Bit.Core.Models.Api.Response.OrganizationSponsorships
namespace Bit.Core.Models.Api.Response.OrganizationSponsorships;
public class OrganizationSponsorshipResponseModel
{
public class OrganizationSponsorshipResponseModel
public Guid SponsoringOrganizationUserId { get; set; }
public string FriendlyName { get; set; }
public string OfferedToEmail { get; set; }
public PlanSponsorshipType PlanSponsorshipType { get; set; }
public DateTime? LastSyncDate { get; set; }
public DateTime? ValidUntil { get; set; }
public bool ToDelete { get; set; }
public bool CloudSponsorshipRemoved { get; set; }
public OrganizationSponsorshipResponseModel() { }
public OrganizationSponsorshipResponseModel(OrganizationSponsorshipData sponsorshipData)
{
public Guid SponsoringOrganizationUserId { get; set; }
public string FriendlyName { get; set; }
public string OfferedToEmail { get; set; }
public PlanSponsorshipType PlanSponsorshipType { get; set; }
public DateTime? LastSyncDate { get; set; }
public DateTime? ValidUntil { get; set; }
public bool ToDelete { get; set; }
SponsoringOrganizationUserId = sponsorshipData.SponsoringOrganizationUserId;
FriendlyName = sponsorshipData.FriendlyName;
OfferedToEmail = sponsorshipData.OfferedToEmail;
PlanSponsorshipType = sponsorshipData.PlanSponsorshipType;
LastSyncDate = sponsorshipData.LastSyncDate;
ValidUntil = sponsorshipData.ValidUntil;
ToDelete = sponsorshipData.ToDelete;
CloudSponsorshipRemoved = sponsorshipData.CloudSponsorshipRemoved;
}
public bool CloudSponsorshipRemoved { get; set; }
public OrganizationSponsorshipResponseModel() { }
public OrganizationSponsorshipResponseModel(OrganizationSponsorshipData sponsorshipData)
public OrganizationSponsorshipData ToOrganizationSponsorship()
{
return new OrganizationSponsorshipData
{
SponsoringOrganizationUserId = sponsorshipData.SponsoringOrganizationUserId;
FriendlyName = sponsorshipData.FriendlyName;
OfferedToEmail = sponsorshipData.OfferedToEmail;
PlanSponsorshipType = sponsorshipData.PlanSponsorshipType;
LastSyncDate = sponsorshipData.LastSyncDate;
ValidUntil = sponsorshipData.ValidUntil;
ToDelete = sponsorshipData.ToDelete;
CloudSponsorshipRemoved = sponsorshipData.CloudSponsorshipRemoved;
}
SponsoringOrganizationUserId = SponsoringOrganizationUserId,
FriendlyName = FriendlyName,
OfferedToEmail = OfferedToEmail,
PlanSponsorshipType = PlanSponsorshipType,
LastSyncDate = LastSyncDate,
ValidUntil = ValidUntil,
ToDelete = ToDelete,
CloudSponsorshipRemoved = CloudSponsorshipRemoved
};
public OrganizationSponsorshipData ToOrganizationSponsorship()
{
return new OrganizationSponsorshipData
{
SponsoringOrganizationUserId = SponsoringOrganizationUserId,
FriendlyName = FriendlyName,
OfferedToEmail = OfferedToEmail,
PlanSponsorshipType = PlanSponsorshipType,
LastSyncDate = LastSyncDate,
ValidUntil = ValidUntil,
ToDelete = ToDelete,
CloudSponsorshipRemoved = CloudSponsorshipRemoved
};
}
}
}

View File

@ -1,30 +1,29 @@
using Bit.Core.Models.Data.Organizations.OrganizationSponsorships;
namespace Bit.Core.Models.Api.Response.OrganizationSponsorships
namespace Bit.Core.Models.Api.Response.OrganizationSponsorships;
public class OrganizationSponsorshipSyncResponseModel
{
public class OrganizationSponsorshipSyncResponseModel
public IEnumerable<OrganizationSponsorshipResponseModel> SponsorshipsBatch { get; set; }
public OrganizationSponsorshipSyncResponseModel() { }
public OrganizationSponsorshipSyncResponseModel(OrganizationSponsorshipSyncData syncData)
{
public IEnumerable<OrganizationSponsorshipResponseModel> SponsorshipsBatch { get; set; }
public OrganizationSponsorshipSyncResponseModel() { }
public OrganizationSponsorshipSyncResponseModel(OrganizationSponsorshipSyncData syncData)
if (syncData == null)
{
if (syncData == null)
{
return;
}
SponsorshipsBatch = syncData.SponsorshipsBatch.Select(o => new OrganizationSponsorshipResponseModel(o));
}
public OrganizationSponsorshipSyncData ToOrganizationSponsorshipSync()
{
return new OrganizationSponsorshipSyncData()
{
SponsorshipsBatch = SponsorshipsBatch.Select(o => o.ToOrganizationSponsorship())
};
return;
}
SponsorshipsBatch = syncData.SponsorshipsBatch.Select(o => new OrganizationSponsorshipResponseModel(o));
}
public OrganizationSponsorshipSyncData ToOrganizationSponsorshipSync()
{
return new OrganizationSponsorshipSyncData()
{
SponsorshipsBatch = SponsorshipsBatch.Select(o => o.ToOrganizationSponsorship())
};
}
}

View File

@ -1,20 +1,19 @@
using Newtonsoft.Json;
namespace Bit.Core.Models.Api
{
public abstract class ResponseModel
{
public ResponseModel(string obj)
{
if (string.IsNullOrWhiteSpace(obj))
{
throw new ArgumentNullException(nameof(obj));
}
namespace Bit.Core.Models.Api;
Object = obj;
public abstract class ResponseModel
{
public ResponseModel(string obj)
{
if (string.IsNullOrWhiteSpace(obj))
{
throw new ArgumentNullException(nameof(obj));
}
[JsonProperty(Order = -200)] // Always the first property
public string Object { get; private set; }
Object = obj;
}
[JsonProperty(Order = -200)] // Always the first property
public string Object { get; private set; }
}

View File

@ -3,133 +3,132 @@ using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Utilities;
namespace Bit.Billing.Models
namespace Bit.Billing.Models;
public class AppleReceiptStatus
{
public class AppleReceiptStatus
[JsonPropertyName("status")]
public int? Status { get; set; }
[JsonPropertyName("environment")]
public string Environment { get; set; }
[JsonPropertyName("latest_receipt")]
public string LatestReceipt { get; set; }
[JsonPropertyName("receipt")]
public AppleReceipt Receipt { get; set; }
[JsonPropertyName("latest_receipt_info")]
public List<AppleTransaction> LatestReceiptInfo { get; set; }
[JsonPropertyName("pending_renewal_info")]
public List<AppleRenewalInfo> PendingRenewalInfo { get; set; }
public string GetOriginalTransactionId()
{
[JsonPropertyName("status")]
public int? Status { get; set; }
[JsonPropertyName("environment")]
public string Environment { get; set; }
[JsonPropertyName("latest_receipt")]
public string LatestReceipt { get; set; }
[JsonPropertyName("receipt")]
public AppleReceipt Receipt { get; set; }
[JsonPropertyName("latest_receipt_info")]
public List<AppleTransaction> LatestReceiptInfo { get; set; }
[JsonPropertyName("pending_renewal_info")]
public List<AppleRenewalInfo> PendingRenewalInfo { get; set; }
return LatestReceiptInfo?.LastOrDefault()?.OriginalTransactionId;
}
public string GetOriginalTransactionId()
{
return LatestReceiptInfo?.LastOrDefault()?.OriginalTransactionId;
}
public string GetLastTransactionId()
{
return LatestReceiptInfo?.LastOrDefault()?.TransactionId;
}
public string GetLastTransactionId()
{
return LatestReceiptInfo?.LastOrDefault()?.TransactionId;
}
public AppleTransaction GetLastTransaction()
{
return LatestReceiptInfo?.LastOrDefault();
}
public AppleTransaction GetLastTransaction()
{
return LatestReceiptInfo?.LastOrDefault();
}
public DateTime? GetLastExpiresDate()
{
return LatestReceiptInfo?.LastOrDefault()?.ExpiresDate;
}
public DateTime? GetLastExpiresDate()
{
return LatestReceiptInfo?.LastOrDefault()?.ExpiresDate;
}
public string GetReceiptData()
{
return LatestReceipt;
}
public string GetReceiptData()
{
return LatestReceipt;
}
public DateTime? GetLastCancellationDate()
{
return LatestReceiptInfo?.LastOrDefault()?.CancellationDate;
}
public DateTime? GetLastCancellationDate()
public bool IsRefunded()
{
var cancellationDate = GetLastCancellationDate();
var expiresDate = GetLastCancellationDate();
if (cancellationDate.HasValue && expiresDate.HasValue)
{
return LatestReceiptInfo?.LastOrDefault()?.CancellationDate;
return cancellationDate.Value <= expiresDate.Value;
}
return false;
}
public bool IsRefunded()
public Transaction BuildTransactionFromLastTransaction(decimal amount, Guid userId)
{
return new Transaction
{
var cancellationDate = GetLastCancellationDate();
var expiresDate = GetLastCancellationDate();
if (cancellationDate.HasValue && expiresDate.HasValue)
{
return cancellationDate.Value <= expiresDate.Value;
}
return false;
}
Amount = amount,
CreationDate = GetLastTransaction().PurchaseDate,
Gateway = GatewayType.AppStore,
GatewayId = GetLastTransactionId(),
UserId = userId,
PaymentMethodType = PaymentMethodType.AppleInApp,
Details = GetLastTransactionId()
};
}
public Transaction BuildTransactionFromLastTransaction(decimal amount, Guid userId)
{
return new Transaction
{
Amount = amount,
CreationDate = GetLastTransaction().PurchaseDate,
Gateway = GatewayType.AppStore,
GatewayId = GetLastTransactionId(),
UserId = userId,
PaymentMethodType = PaymentMethodType.AppleInApp,
Details = GetLastTransactionId()
};
}
public class AppleReceipt
{
[JsonPropertyName("receipt_type")]
public string ReceiptType { get; set; }
[JsonPropertyName("bundle_id")]
public string BundleId { get; set; }
[JsonPropertyName("receipt_creation_date_ms")]
[JsonConverter(typeof(MsEpochConverter))]
public DateTime ReceiptCreationDate { get; set; }
[JsonPropertyName("in_app")]
public List<AppleTransaction> InApp { get; set; }
}
public class AppleReceipt
{
[JsonPropertyName("receipt_type")]
public string ReceiptType { get; set; }
[JsonPropertyName("bundle_id")]
public string BundleId { get; set; }
[JsonPropertyName("receipt_creation_date_ms")]
[JsonConverter(typeof(MsEpochConverter))]
public DateTime ReceiptCreationDate { get; set; }
[JsonPropertyName("in_app")]
public List<AppleTransaction> InApp { get; set; }
}
public class AppleRenewalInfo
{
[JsonPropertyName("expiration_intent")]
public string ExpirationIntent { get; set; }
[JsonPropertyName("auto_renew_product_id")]
public string AutoRenewProductId { get; set; }
[JsonPropertyName("original_transaction_id")]
public string OriginalTransactionId { get; set; }
[JsonPropertyName("is_in_billing_retry_period")]
public string IsInBillingRetryPeriod { get; set; }
[JsonPropertyName("product_id")]
public string ProductId { get; set; }
[JsonPropertyName("auto_renew_status")]
public string AutoRenewStatus { get; set; }
}
public class AppleRenewalInfo
{
[JsonPropertyName("expiration_intent")]
public string ExpirationIntent { get; set; }
[JsonPropertyName("auto_renew_product_id")]
public string AutoRenewProductId { get; set; }
[JsonPropertyName("original_transaction_id")]
public string OriginalTransactionId { get; set; }
[JsonPropertyName("is_in_billing_retry_period")]
public string IsInBillingRetryPeriod { get; set; }
[JsonPropertyName("product_id")]
public string ProductId { get; set; }
[JsonPropertyName("auto_renew_status")]
public string AutoRenewStatus { get; set; }
}
public class AppleTransaction
{
[JsonPropertyName("quantity")]
public string Quantity { get; set; }
[JsonPropertyName("product_id")]
public string ProductId { get; set; }
[JsonPropertyName("transaction_id")]
public string TransactionId { get; set; }
[JsonPropertyName("original_transaction_id")]
public string OriginalTransactionId { get; set; }
[JsonPropertyName("purchase_date_ms")]
[JsonConverter(typeof(MsEpochConverter))]
public DateTime PurchaseDate { get; set; }
[JsonPropertyName("original_purchase_date_ms")]
[JsonConverter(typeof(MsEpochConverter))]
public DateTime OriginalPurchaseDate { get; set; }
[JsonPropertyName("expires_date_ms")]
[JsonConverter(typeof(MsEpochConverter))]
public DateTime ExpiresDate { get; set; }
[JsonPropertyName("cancellation_date_ms")]
[JsonConverter(typeof(MsEpochConverter))]
public DateTime? CancellationDate { get; set; }
[JsonPropertyName("web_order_line_item_id")]
public string WebOrderLineItemId { get; set; }
[JsonPropertyName("cancellation_reason")]
public string CancellationReason { get; set; }
}
public class AppleTransaction
{
[JsonPropertyName("quantity")]
public string Quantity { get; set; }
[JsonPropertyName("product_id")]
public string ProductId { get; set; }
[JsonPropertyName("transaction_id")]
public string TransactionId { get; set; }
[JsonPropertyName("original_transaction_id")]
public string OriginalTransactionId { get; set; }
[JsonPropertyName("purchase_date_ms")]
[JsonConverter(typeof(MsEpochConverter))]
public DateTime PurchaseDate { get; set; }
[JsonPropertyName("original_purchase_date_ms")]
[JsonConverter(typeof(MsEpochConverter))]
public DateTime OriginalPurchaseDate { get; set; }
[JsonPropertyName("expires_date_ms")]
[JsonConverter(typeof(MsEpochConverter))]
public DateTime ExpiresDate { get; set; }
[JsonPropertyName("cancellation_date_ms")]
[JsonConverter(typeof(MsEpochConverter))]
public DateTime? CancellationDate { get; set; }
[JsonPropertyName("web_order_line_item_id")]
public string WebOrderLineItemId { get; set; }
[JsonPropertyName("cancellation_reason")]
public string CancellationReason { get; set; }
}
}

View File

@ -2,155 +2,154 @@
using Bit.Core.Enums;
using Stripe;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class BillingInfo
{
public class BillingInfo
public decimal Balance { get; set; }
public BillingSource PaymentSource { get; set; }
public IEnumerable<BillingInvoice> Invoices { get; set; } = new List<BillingInvoice>();
public IEnumerable<BillingTransaction> Transactions { get; set; } = new List<BillingTransaction>();
public class BillingSource
{
public decimal Balance { get; set; }
public BillingSource PaymentSource { get; set; }
public IEnumerable<BillingInvoice> Invoices { get; set; } = new List<BillingInvoice>();
public IEnumerable<BillingTransaction> Transactions { get; set; } = new List<BillingTransaction>();
public BillingSource() { }
public class BillingSource
public BillingSource(PaymentMethod method)
{
public BillingSource() { }
public BillingSource(PaymentMethod method)
if (method.Card != null)
{
if (method.Card != null)
{
Type = PaymentMethodType.Card;
Description = $"{method.Card.Brand?.ToUpperInvariant()}, *{method.Card.Last4}, " +
string.Format("{0}/{1}",
string.Concat(method.Card.ExpMonth < 10 ?
"0" : string.Empty, method.Card.ExpMonth),
method.Card.ExpYear);
CardBrand = method.Card.Brand;
}
Type = PaymentMethodType.Card;
Description = $"{method.Card.Brand?.ToUpperInvariant()}, *{method.Card.Last4}, " +
string.Format("{0}/{1}",
string.Concat(method.Card.ExpMonth < 10 ?
"0" : string.Empty, method.Card.ExpMonth),
method.Card.ExpYear);
CardBrand = method.Card.Brand;
}
}
public BillingSource(IPaymentSource source)
public BillingSource(IPaymentSource source)
{
if (source is BankAccount bankAccount)
{
if (source is BankAccount bankAccount)
{
Type = PaymentMethodType.BankAccount;
Description = $"{bankAccount.BankName}, *{bankAccount.Last4} - " +
(bankAccount.Status == "verified" ? "verified" :
bankAccount.Status == "errored" ? "invalid" :
bankAccount.Status == "verification_failed" ? "verification failed" : "unverified");
NeedsVerification = bankAccount.Status == "new" || bankAccount.Status == "validated";
}
else if (source is Card card)
{
Type = PaymentMethodType.Card;
Description = $"{card.Brand}, *{card.Last4}, " +
string.Format("{0}/{1}",
string.Concat(card.ExpMonth < 10 ?
"0" : string.Empty, card.ExpMonth),
card.ExpYear);
CardBrand = card.Brand;
}
else if (source is Source src && src.Card != null)
{
Type = PaymentMethodType.Card;
Description = $"{src.Card.Brand}, *{src.Card.Last4}, " +
string.Format("{0}/{1}",
string.Concat(src.Card.ExpMonth < 10 ?
"0" : string.Empty, src.Card.ExpMonth),
src.Card.ExpYear);
CardBrand = src.Card.Brand;
}
Type = PaymentMethodType.BankAccount;
Description = $"{bankAccount.BankName}, *{bankAccount.Last4} - " +
(bankAccount.Status == "verified" ? "verified" :
bankAccount.Status == "errored" ? "invalid" :
bankAccount.Status == "verification_failed" ? "verification failed" : "unverified");
NeedsVerification = bankAccount.Status == "new" || bankAccount.Status == "validated";
}
public BillingSource(Braintree.PaymentMethod method)
else if (source is Card card)
{
if (method is Braintree.PayPalAccount paypal)
{
Type = PaymentMethodType.PayPal;
Description = paypal.Email;
}
else if (method is Braintree.CreditCard card)
{
Type = PaymentMethodType.Card;
Description = $"{card.CardType.ToString()}, *{card.LastFour}, " +
string.Format("{0}/{1}",
string.Concat(card.ExpirationMonth.Length == 1 ?
"0" : string.Empty, card.ExpirationMonth),
card.ExpirationYear);
CardBrand = card.CardType.ToString();
}
else if (method is Braintree.UsBankAccount bank)
{
Type = PaymentMethodType.BankAccount;
Description = $"{bank.BankName}, *{bank.Last4}";
}
else
{
throw new NotSupportedException("Method not supported.");
}
Type = PaymentMethodType.Card;
Description = $"{card.Brand}, *{card.Last4}, " +
string.Format("{0}/{1}",
string.Concat(card.ExpMonth < 10 ?
"0" : string.Empty, card.ExpMonth),
card.ExpYear);
CardBrand = card.Brand;
}
else if (source is Source src && src.Card != null)
{
Type = PaymentMethodType.Card;
Description = $"{src.Card.Brand}, *{src.Card.Last4}, " +
string.Format("{0}/{1}",
string.Concat(src.Card.ExpMonth < 10 ?
"0" : string.Empty, src.Card.ExpMonth),
src.Card.ExpYear);
CardBrand = src.Card.Brand;
}
}
public BillingSource(Braintree.UsBankAccountDetails bank)
public BillingSource(Braintree.PaymentMethod method)
{
if (method is Braintree.PayPalAccount paypal)
{
Type = PaymentMethodType.PayPal;
Description = paypal.Email;
}
else if (method is Braintree.CreditCard card)
{
Type = PaymentMethodType.Card;
Description = $"{card.CardType.ToString()}, *{card.LastFour}, " +
string.Format("{0}/{1}",
string.Concat(card.ExpirationMonth.Length == 1 ?
"0" : string.Empty, card.ExpirationMonth),
card.ExpirationYear);
CardBrand = card.CardType.ToString();
}
else if (method is Braintree.UsBankAccount bank)
{
Type = PaymentMethodType.BankAccount;
Description = $"{bank.BankName}, *{bank.Last4}";
}
public BillingSource(Braintree.PayPalDetails paypal)
else
{
Type = PaymentMethodType.PayPal;
Description = paypal.PayerEmail;
throw new NotSupportedException("Method not supported.");
}
public PaymentMethodType Type { get; set; }
public string CardBrand { get; set; }
public string Description { get; set; }
public bool NeedsVerification { get; set; }
}
public class BillingTransaction
public BillingSource(Braintree.UsBankAccountDetails bank)
{
public BillingTransaction(Transaction transaction)
{
Id = transaction.Id;
CreatedDate = transaction.CreationDate;
Refunded = transaction.Refunded;
Type = transaction.Type;
PaymentMethodType = transaction.PaymentMethodType;
Details = transaction.Details;
Amount = transaction.Amount;
RefundedAmount = transaction.RefundedAmount;
}
public Guid Id { get; set; }
public DateTime CreatedDate { get; set; }
public decimal Amount { get; set; }
public bool? Refunded { get; set; }
public bool? PartiallyRefunded => !Refunded.GetValueOrDefault() && RefundedAmount.GetValueOrDefault() > 0;
public decimal? RefundedAmount { get; set; }
public TransactionType Type { get; set; }
public PaymentMethodType? PaymentMethodType { get; set; }
public string Details { get; set; }
Type = PaymentMethodType.BankAccount;
Description = $"{bank.BankName}, *{bank.Last4}";
}
public class BillingInvoice
public BillingSource(Braintree.PayPalDetails paypal)
{
public BillingInvoice(Invoice inv)
{
Date = inv.Created;
Url = inv.HostedInvoiceUrl;
PdfUrl = inv.InvoicePdf;
Number = inv.Number;
Paid = inv.Paid;
Amount = inv.Total / 100M;
}
public decimal Amount { get; set; }
public DateTime? Date { get; set; }
public string Url { get; set; }
public string PdfUrl { get; set; }
public string Number { get; set; }
public bool Paid { get; set; }
Type = PaymentMethodType.PayPal;
Description = paypal.PayerEmail;
}
public PaymentMethodType Type { get; set; }
public string CardBrand { get; set; }
public string Description { get; set; }
public bool NeedsVerification { get; set; }
}
public class BillingTransaction
{
public BillingTransaction(Transaction transaction)
{
Id = transaction.Id;
CreatedDate = transaction.CreationDate;
Refunded = transaction.Refunded;
Type = transaction.Type;
PaymentMethodType = transaction.PaymentMethodType;
Details = transaction.Details;
Amount = transaction.Amount;
RefundedAmount = transaction.RefundedAmount;
}
public Guid Id { get; set; }
public DateTime CreatedDate { get; set; }
public decimal Amount { get; set; }
public bool? Refunded { get; set; }
public bool? PartiallyRefunded => !Refunded.GetValueOrDefault() && RefundedAmount.GetValueOrDefault() > 0;
public decimal? RefundedAmount { get; set; }
public TransactionType Type { get; set; }
public PaymentMethodType? PaymentMethodType { get; set; }
public string Details { get; set; }
}
public class BillingInvoice
{
public BillingInvoice(Invoice inv)
{
Date = inv.Created;
Url = inv.HostedInvoiceUrl;
PdfUrl = inv.InvoicePdf;
Number = inv.Number;
Paid = inv.Paid;
Amount = inv.Total / 100M;
}
public decimal Amount { get; set; }
public DateTime? Date { get; set; }
public string Url { get; set; }
public string PdfUrl { get; set; }
public string Number { get; set; }
public bool Paid { get; set; }
}
}

View File

@ -1,10 +1,9 @@
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class CaptchaResponse
{
public class CaptchaResponse
{
public bool Success { get; set; }
public bool MaybeBot { get; set; }
public bool IsBot { get; set; }
public double Score { get; set; }
}
public bool Success { get; set; }
public bool MaybeBot { get; set; }
public bool IsBot { get; set; }
public double Score { get; set; }
}

View File

@ -1,14 +1,13 @@
namespace Bit.Core.Models.Business
{
public class ExpiringToken
{
public readonly string Token;
public readonly DateTime ExpirationDate;
namespace Bit.Core.Models.Business;
public ExpiringToken(string token, DateTime expirationDate)
{
Token = token;
ExpirationDate = expirationDate;
}
public class ExpiringToken
{
public readonly string Token;
public readonly DateTime ExpirationDate;
public ExpiringToken(string token, DateTime expirationDate)
{
Token = token;
ExpirationDate = expirationDate;
}
}

View File

@ -1,21 +1,20 @@
using System.Security.Cryptography.X509Certificates;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public interface ILicense
{
public interface ILicense
{
string LicenseKey { get; set; }
int Version { get; set; }
DateTime Issued { get; set; }
DateTime? Refresh { get; set; }
DateTime? Expires { get; set; }
bool Trial { get; set; }
string Hash { get; set; }
string Signature { get; set; }
byte[] SignatureBytes { get; }
byte[] GetDataBytes(bool forHash = false);
byte[] ComputeHash();
bool VerifySignature(X509Certificate2 certificate);
byte[] Sign(X509Certificate2 certificate);
}
string LicenseKey { get; set; }
int Version { get; set; }
DateTime Issued { get; set; }
DateTime? Refresh { get; set; }
DateTime? Expires { get; set; }
bool Trial { get; set; }
string Hash { get; set; }
string Signature { get; set; }
byte[] SignatureBytes { get; }
byte[] GetDataBytes(bool forHash = false);
byte[] ComputeHash();
bool VerifySignature(X509Certificate2 certificate);
byte[] Sign(X509Certificate2 certificate);
}

View File

@ -1,10 +1,9 @@
using Bit.Core.Entities;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class ImportedGroup
{
public class ImportedGroup
{
public Group Group { get; set; }
public HashSet<string> ExternalUserIds { get; set; }
}
public Group Group { get; set; }
public HashSet<string> ExternalUserIds { get; set; }
}

View File

@ -1,8 +1,7 @@
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class ImportedOrganizationUser
{
public class ImportedOrganizationUser
{
public string Email { get; set; }
public string ExternalId { get; set; }
}
public string Email { get; set; }
public string ExternalId { get; set; }
}

View File

@ -8,304 +8,303 @@ using Bit.Core.Enums;
using Bit.Core.Services;
using Bit.Core.Settings;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class OrganizationLicense : ILicense
{
public class OrganizationLicense : ILicense
public OrganizationLicense()
{ }
public OrganizationLicense(Organization org, SubscriptionInfo subscriptionInfo, Guid installationId,
ILicensingService licenseService, int? version = null)
{
public OrganizationLicense()
{ }
Version = version.GetValueOrDefault(CURRENT_LICENSE_FILE_VERSION); // TODO: Remember to change the constant
LicenseType = Enums.LicenseType.Organization;
LicenseKey = org.LicenseKey;
InstallationId = installationId;
Id = org.Id;
Name = org.Name;
BillingEmail = org.BillingEmail;
BusinessName = org.BusinessName;
Enabled = org.Enabled;
Plan = org.Plan;
PlanType = org.PlanType;
Seats = org.Seats;
MaxCollections = org.MaxCollections;
UsePolicies = org.UsePolicies;
UseSso = org.UseSso;
UseKeyConnector = org.UseKeyConnector;
UseScim = org.UseScim;
UseGroups = org.UseGroups;
UseEvents = org.UseEvents;
UseDirectory = org.UseDirectory;
UseTotp = org.UseTotp;
Use2fa = org.Use2fa;
UseApi = org.UseApi;
UseResetPassword = org.UseResetPassword;
MaxStorageGb = org.MaxStorageGb;
SelfHost = org.SelfHost;
UsersGetPremium = org.UsersGetPremium;
Issued = DateTime.UtcNow;
public OrganizationLicense(Organization org, SubscriptionInfo subscriptionInfo, Guid installationId,
ILicensingService licenseService, int? version = null)
if (subscriptionInfo?.Subscription == null)
{
Version = version.GetValueOrDefault(CURRENT_LICENSE_FILE_VERSION); // TODO: Remember to change the constant
LicenseType = Enums.LicenseType.Organization;
LicenseKey = org.LicenseKey;
InstallationId = installationId;
Id = org.Id;
Name = org.Name;
BillingEmail = org.BillingEmail;
BusinessName = org.BusinessName;
Enabled = org.Enabled;
Plan = org.Plan;
PlanType = org.PlanType;
Seats = org.Seats;
MaxCollections = org.MaxCollections;
UsePolicies = org.UsePolicies;
UseSso = org.UseSso;
UseKeyConnector = org.UseKeyConnector;
UseScim = org.UseScim;
UseGroups = org.UseGroups;
UseEvents = org.UseEvents;
UseDirectory = org.UseDirectory;
UseTotp = org.UseTotp;
Use2fa = org.Use2fa;
UseApi = org.UseApi;
UseResetPassword = org.UseResetPassword;
MaxStorageGb = org.MaxStorageGb;
SelfHost = org.SelfHost;
UsersGetPremium = org.UsersGetPremium;
Issued = DateTime.UtcNow;
if (subscriptionInfo?.Subscription == null)
if (org.PlanType == PlanType.Custom && org.ExpirationDate.HasValue)
{
if (org.PlanType == PlanType.Custom && org.ExpirationDate.HasValue)
{
Expires = Refresh = org.ExpirationDate.Value;
Trial = false;
}
else
{
Expires = Refresh = Issued.AddDays(7);
Trial = true;
}
}
else if (subscriptionInfo.Subscription.TrialEndDate.HasValue &&
subscriptionInfo.Subscription.TrialEndDate.Value > DateTime.UtcNow)
{
Expires = Refresh = subscriptionInfo.Subscription.TrialEndDate.Value;
Trial = true;
}
else
{
if (org.ExpirationDate.HasValue && org.ExpirationDate.Value < DateTime.UtcNow)
{
// expired
Expires = Refresh = org.ExpirationDate.Value;
}
else if (subscriptionInfo?.Subscription?.PeriodDuration != null &&
subscriptionInfo.Subscription.PeriodDuration > TimeSpan.FromDays(180))
{
Refresh = DateTime.UtcNow.AddDays(30);
Expires = subscriptionInfo?.Subscription.PeriodEndDate.Value.AddDays(60);
}
else
{
Expires = org.ExpirationDate.HasValue ? org.ExpirationDate.Value.AddMonths(11) : Issued.AddYears(1);
Refresh = DateTime.UtcNow - Expires > TimeSpan.FromDays(30) ? DateTime.UtcNow.AddDays(30) : Expires;
}
Expires = Refresh = org.ExpirationDate.Value;
Trial = false;
}
Hash = Convert.ToBase64String(ComputeHash());
Signature = Convert.ToBase64String(licenseService.SignLicense(this));
}
public string LicenseKey { get; set; }
public Guid InstallationId { get; set; }
public Guid Id { get; set; }
public string Name { get; set; }
public string BillingEmail { get; set; }
public string BusinessName { get; set; }
public bool Enabled { get; set; }
public string Plan { get; set; }
public PlanType PlanType { get; set; }
public int? Seats { get; set; }
public short? MaxCollections { get; set; }
public bool UsePolicies { get; set; }
public bool UseSso { get; set; }
public bool UseKeyConnector { get; set; }
public bool UseScim { get; set; }
public bool UseGroups { get; set; }
public bool UseEvents { get; set; }
public bool UseDirectory { get; set; }
public bool UseTotp { get; set; }
public bool Use2fa { get; set; }
public bool UseApi { get; set; }
public bool UseResetPassword { get; set; }
public short? MaxStorageGb { get; set; }
public bool SelfHost { get; set; }
public bool UsersGetPremium { get; set; }
public int Version { get; set; }
public DateTime Issued { get; set; }
public DateTime? Refresh { get; set; }
public DateTime? Expires { get; set; }
public bool Trial { get; set; }
public LicenseType? LicenseType { get; set; }
public string Hash { get; set; }
public string Signature { get; set; }
[JsonIgnore]
public byte[] SignatureBytes => Convert.FromBase64String(Signature);
/// <summary>
/// Represents the current version of the license format. Should be updated whenever new fields are added.
/// </summary>
private const int CURRENT_LICENSE_FILE_VERSION = 9;
private bool ValidLicenseVersion
{
get => Version is >= 1 and <= 10;
}
public byte[] GetDataBytes(bool forHash = false)
{
string data = null;
if (ValidLicenseVersion)
else
{
var props = typeof(OrganizationLicense)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p =>
!p.Name.Equals(nameof(Signature)) &&
!p.Name.Equals(nameof(SignatureBytes)) &&
!p.Name.Equals(nameof(LicenseType)) &&
// UsersGetPremium was added in Version 2
(Version >= 2 || !p.Name.Equals(nameof(UsersGetPremium))) &&
// UseEvents was added in Version 3
(Version >= 3 || !p.Name.Equals(nameof(UseEvents))) &&
// Use2fa was added in Version 4
(Version >= 4 || !p.Name.Equals(nameof(Use2fa))) &&
// UseApi was added in Version 5
(Version >= 5 || !p.Name.Equals(nameof(UseApi))) &&
// UsePolicies was added in Version 6
(Version >= 6 || !p.Name.Equals(nameof(UsePolicies))) &&
// UseSso was added in Version 7
(Version >= 7 || !p.Name.Equals(nameof(UseSso))) &&
// UseResetPassword was added in Version 8
(Version >= 8 || !p.Name.Equals(nameof(UseResetPassword))) &&
// UseKeyConnector was added in Version 9
(Version >= 9 || !p.Name.Equals(nameof(UseKeyConnector))) &&
// UseScim was added in Version 10
(Version >= 10 || !p.Name.Equals(nameof(UseScim))) &&
Expires = Refresh = Issued.AddDays(7);
Trial = true;
}
}
else if (subscriptionInfo.Subscription.TrialEndDate.HasValue &&
subscriptionInfo.Subscription.TrialEndDate.Value > DateTime.UtcNow)
{
Expires = Refresh = subscriptionInfo.Subscription.TrialEndDate.Value;
Trial = true;
}
else
{
if (org.ExpirationDate.HasValue && org.ExpirationDate.Value < DateTime.UtcNow)
{
// expired
Expires = Refresh = org.ExpirationDate.Value;
}
else if (subscriptionInfo?.Subscription?.PeriodDuration != null &&
subscriptionInfo.Subscription.PeriodDuration > TimeSpan.FromDays(180))
{
Refresh = DateTime.UtcNow.AddDays(30);
Expires = subscriptionInfo?.Subscription.PeriodEndDate.Value.AddDays(60);
}
else
{
Expires = org.ExpirationDate.HasValue ? org.ExpirationDate.Value.AddMonths(11) : Issued.AddYears(1);
Refresh = DateTime.UtcNow - Expires > TimeSpan.FromDays(30) ? DateTime.UtcNow.AddDays(30) : Expires;
}
Trial = false;
}
Hash = Convert.ToBase64String(ComputeHash());
Signature = Convert.ToBase64String(licenseService.SignLicense(this));
}
public string LicenseKey { get; set; }
public Guid InstallationId { get; set; }
public Guid Id { get; set; }
public string Name { get; set; }
public string BillingEmail { get; set; }
public string BusinessName { get; set; }
public bool Enabled { get; set; }
public string Plan { get; set; }
public PlanType PlanType { get; set; }
public int? Seats { get; set; }
public short? MaxCollections { get; set; }
public bool UsePolicies { get; set; }
public bool UseSso { get; set; }
public bool UseKeyConnector { get; set; }
public bool UseScim { get; set; }
public bool UseGroups { get; set; }
public bool UseEvents { get; set; }
public bool UseDirectory { get; set; }
public bool UseTotp { get; set; }
public bool Use2fa { get; set; }
public bool UseApi { get; set; }
public bool UseResetPassword { get; set; }
public short? MaxStorageGb { get; set; }
public bool SelfHost { get; set; }
public bool UsersGetPremium { get; set; }
public int Version { get; set; }
public DateTime Issued { get; set; }
public DateTime? Refresh { get; set; }
public DateTime? Expires { get; set; }
public bool Trial { get; set; }
public LicenseType? LicenseType { get; set; }
public string Hash { get; set; }
public string Signature { get; set; }
[JsonIgnore]
public byte[] SignatureBytes => Convert.FromBase64String(Signature);
/// <summary>
/// Represents the current version of the license format. Should be updated whenever new fields are added.
/// </summary>
private const int CURRENT_LICENSE_FILE_VERSION = 9;
private bool ValidLicenseVersion
{
get => Version is >= 1 and <= 10;
}
public byte[] GetDataBytes(bool forHash = false)
{
string data = null;
if (ValidLicenseVersion)
{
var props = typeof(OrganizationLicense)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p =>
!p.Name.Equals(nameof(Signature)) &&
!p.Name.Equals(nameof(SignatureBytes)) &&
!p.Name.Equals(nameof(LicenseType)) &&
// UsersGetPremium was added in Version 2
(Version >= 2 || !p.Name.Equals(nameof(UsersGetPremium))) &&
// UseEvents was added in Version 3
(Version >= 3 || !p.Name.Equals(nameof(UseEvents))) &&
// Use2fa was added in Version 4
(Version >= 4 || !p.Name.Equals(nameof(Use2fa))) &&
// UseApi was added in Version 5
(Version >= 5 || !p.Name.Equals(nameof(UseApi))) &&
// UsePolicies was added in Version 6
(Version >= 6 || !p.Name.Equals(nameof(UsePolicies))) &&
// UseSso was added in Version 7
(Version >= 7 || !p.Name.Equals(nameof(UseSso))) &&
// UseResetPassword was added in Version 8
(Version >= 8 || !p.Name.Equals(nameof(UseResetPassword))) &&
// UseKeyConnector was added in Version 9
(Version >= 9 || !p.Name.Equals(nameof(UseKeyConnector))) &&
// UseScim was added in Version 10
(Version >= 10 || !p.Name.Equals(nameof(UseScim))) &&
(
!forHash ||
(
!forHash ||
(
!p.Name.Equals(nameof(Hash)) &&
!p.Name.Equals(nameof(Issued)) &&
!p.Name.Equals(nameof(Refresh))
)
))
.OrderBy(p => p.Name)
.Select(p => $"{p.Name}:{Utilities.CoreHelpers.FormatLicenseSignatureValue(p.GetValue(this, null))}")
.Aggregate((c, n) => $"{c}|{n}");
data = $"license:organization|{props}";
}
else
{
throw new NotSupportedException($"Version {Version} is not supported.");
}
return Encoding.UTF8.GetBytes(data);
!p.Name.Equals(nameof(Hash)) &&
!p.Name.Equals(nameof(Issued)) &&
!p.Name.Equals(nameof(Refresh))
)
))
.OrderBy(p => p.Name)
.Select(p => $"{p.Name}:{Utilities.CoreHelpers.FormatLicenseSignatureValue(p.GetValue(this, null))}")
.Aggregate((c, n) => $"{c}|{n}");
data = $"license:organization|{props}";
}
else
{
throw new NotSupportedException($"Version {Version} is not supported.");
}
public byte[] ComputeHash()
return Encoding.UTF8.GetBytes(data);
}
public byte[] ComputeHash()
{
using (var alg = SHA256.Create())
{
using (var alg = SHA256.Create())
{
return alg.ComputeHash(GetDataBytes(true));
}
return alg.ComputeHash(GetDataBytes(true));
}
}
public bool CanUse(IGlobalSettings globalSettings)
{
if (!Enabled || Issued > DateTime.UtcNow || Expires < DateTime.UtcNow)
{
return false;
}
public bool CanUse(IGlobalSettings globalSettings)
if (ValidLicenseVersion)
{
if (!Enabled || Issued > DateTime.UtcNow || Expires < DateTime.UtcNow)
{
return false;
}
return InstallationId == globalSettings.Installation.Id && SelfHost;
}
else
{
throw new NotSupportedException($"Version {Version} is not supported.");
}
}
if (ValidLicenseVersion)
{
return InstallationId == globalSettings.Installation.Id && SelfHost;
}
else
{
throw new NotSupportedException($"Version {Version} is not supported.");
}
public bool VerifyData(Organization organization, IGlobalSettings globalSettings)
{
if (Issued > DateTime.UtcNow || Expires < DateTime.UtcNow)
{
return false;
}
public bool VerifyData(Organization organization, IGlobalSettings globalSettings)
if (ValidLicenseVersion)
{
if (Issued > DateTime.UtcNow || Expires < DateTime.UtcNow)
var valid =
globalSettings.Installation.Id == InstallationId &&
organization.LicenseKey != null && organization.LicenseKey.Equals(LicenseKey) &&
organization.Enabled == Enabled &&
organization.PlanType == PlanType &&
organization.Seats == Seats &&
organization.MaxCollections == MaxCollections &&
organization.UseGroups == UseGroups &&
organization.UseDirectory == UseDirectory &&
organization.UseTotp == UseTotp &&
organization.SelfHost == SelfHost &&
organization.Name.Equals(Name);
if (valid && Version >= 2)
{
return false;
valid = organization.UsersGetPremium == UsersGetPremium;
}
if (ValidLicenseVersion)
if (valid && Version >= 3)
{
var valid =
globalSettings.Installation.Id == InstallationId &&
organization.LicenseKey != null && organization.LicenseKey.Equals(LicenseKey) &&
organization.Enabled == Enabled &&
organization.PlanType == PlanType &&
organization.Seats == Seats &&
organization.MaxCollections == MaxCollections &&
organization.UseGroups == UseGroups &&
organization.UseDirectory == UseDirectory &&
organization.UseTotp == UseTotp &&
organization.SelfHost == SelfHost &&
organization.Name.Equals(Name);
if (valid && Version >= 2)
{
valid = organization.UsersGetPremium == UsersGetPremium;
}
if (valid && Version >= 3)
{
valid = organization.UseEvents == UseEvents;
}
if (valid && Version >= 4)
{
valid = organization.Use2fa == Use2fa;
}
if (valid && Version >= 5)
{
valid = organization.UseApi == UseApi;
}
if (valid && Version >= 6)
{
valid = organization.UsePolicies == UsePolicies;
}
if (valid && Version >= 7)
{
valid = organization.UseSso == UseSso;
}
if (valid && Version >= 8)
{
valid = organization.UseResetPassword == UseResetPassword;
}
if (valid && Version >= 9)
{
valid = organization.UseKeyConnector == UseKeyConnector;
}
if (valid && Version >= 10)
{
valid = organization.UseScim == UseScim;
}
return valid;
valid = organization.UseEvents == UseEvents;
}
else
if (valid && Version >= 4)
{
throw new NotSupportedException($"Version {Version} is not supported.");
valid = organization.Use2fa == Use2fa;
}
if (valid && Version >= 5)
{
valid = organization.UseApi == UseApi;
}
if (valid && Version >= 6)
{
valid = organization.UsePolicies == UsePolicies;
}
if (valid && Version >= 7)
{
valid = organization.UseSso == UseSso;
}
if (valid && Version >= 8)
{
valid = organization.UseResetPassword == UseResetPassword;
}
if (valid && Version >= 9)
{
valid = organization.UseKeyConnector == UseKeyConnector;
}
if (valid && Version >= 10)
{
valid = organization.UseScim == UseScim;
}
return valid;
}
else
{
throw new NotSupportedException($"Version {Version} is not supported.");
}
}
public bool VerifySignature(X509Certificate2 certificate)
{
using (var rsa = certificate.GetRSAPublicKey())
{
return rsa.VerifyData(GetDataBytes(), SignatureBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
}
public byte[] Sign(X509Certificate2 certificate)
{
if (!certificate.HasPrivateKey)
{
throw new InvalidOperationException("You don't have the private key!");
}
public bool VerifySignature(X509Certificate2 certificate)
using (var rsa = certificate.GetRSAPrivateKey())
{
using (var rsa = certificate.GetRSAPublicKey())
{
return rsa.VerifyData(GetDataBytes(), SignatureBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
}
public byte[] Sign(X509Certificate2 certificate)
{
if (!certificate.HasPrivateKey)
{
throw new InvalidOperationException("You don't have the private key!");
}
using (var rsa = certificate.GetRSAPrivateKey())
{
return rsa.SignData(GetDataBytes(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
return rsa.SignData(GetDataBytes(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
}
}

View File

@ -1,17 +1,16 @@
using Bit.Core.Entities;
using Bit.Core.Enums;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class OrganizationSignup : OrganizationUpgrade
{
public class OrganizationSignup : OrganizationUpgrade
{
public string Name { get; set; }
public string BillingEmail { get; set; }
public User Owner { get; set; }
public string OwnerKey { get; set; }
public string CollectionName { get; set; }
public PaymentMethodType? PaymentMethodType { get; set; }
public string PaymentToken { get; set; }
public int? MaxAutoscaleSeats { get; set; } = null;
}
public string Name { get; set; }
public string BillingEmail { get; set; }
public User Owner { get; set; }
public string OwnerKey { get; set; }
public string CollectionName { get; set; }
public PaymentMethodType? PaymentMethodType { get; set; }
public string PaymentToken { get; set; }
public int? MaxAutoscaleSeats { get; set; } = null;
}

View File

@ -1,16 +1,15 @@
using Bit.Core.Enums;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class OrganizationUpgrade
{
public class OrganizationUpgrade
{
public string BusinessName { get; set; }
public PlanType Plan { get; set; }
public int AdditionalSeats { get; set; }
public short AdditionalStorageGb { get; set; }
public bool PremiumAccessAddon { get; set; }
public TaxInfo TaxInfo { get; set; }
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
}
public string BusinessName { get; set; }
public PlanType Plan { get; set; }
public int AdditionalSeats { get; set; }
public short AdditionalStorageGb { get; set; }
public bool PremiumAccessAddon { get; set; }
public TaxInfo TaxInfo { get; set; }
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
}

View File

@ -1,25 +1,24 @@
using Bit.Core.Models.Data;
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class OrganizationUserInvite
{
public class OrganizationUserInvite
public IEnumerable<string> Emails { get; set; }
public Enums.OrganizationUserType? Type { get; set; }
public bool AccessAll { get; set; }
public Permissions Permissions { get; set; }
public IEnumerable<SelectionReadOnly> Collections { get; set; }
public OrganizationUserInvite() { }
public OrganizationUserInvite(OrganizationUserInviteData requestModel)
{
public IEnumerable<string> Emails { get; set; }
public Enums.OrganizationUserType? Type { get; set; }
public bool AccessAll { get; set; }
public Permissions Permissions { get; set; }
public IEnumerable<SelectionReadOnly> Collections { get; set; }
public OrganizationUserInvite() { }
public OrganizationUserInvite(OrganizationUserInviteData requestModel)
{
Emails = requestModel.Emails;
Type = requestModel.Type;
AccessAll = requestModel.AccessAll;
Collections = requestModel.Collections;
Permissions = requestModel.Permissions;
}
Emails = requestModel.Emails;
Type = requestModel.Type;
AccessAll = requestModel.AccessAll;
Collections = requestModel.Collections;
Permissions = requestModel.Permissions;
}
}

View File

@ -1,36 +1,35 @@
using Bit.Core.Enums.Provider;
namespace Bit.Core.Models.Business.Provider
namespace Bit.Core.Models.Business.Provider;
public class ProviderUserInvite<T>
{
public class ProviderUserInvite<T>
public IEnumerable<T> UserIdentifiers { get; set; }
public ProviderUserType Type { get; set; }
public Guid InvitingUserId { get; set; }
public Guid ProviderId { get; set; }
}
public static class ProviderUserInviteFactory
{
public static ProviderUserInvite<string> CreateIntialInvite(IEnumerable<string> inviteeEmails, ProviderUserType type, Guid invitingUserId, Guid providerId)
{
public IEnumerable<T> UserIdentifiers { get; set; }
public ProviderUserType Type { get; set; }
public Guid InvitingUserId { get; set; }
public Guid ProviderId { get; set; }
return new ProviderUserInvite<string>
{
UserIdentifiers = inviteeEmails,
Type = type,
InvitingUserId = invitingUserId,
ProviderId = providerId
};
}
public static class ProviderUserInviteFactory
public static ProviderUserInvite<Guid> CreateReinvite(IEnumerable<Guid> inviteeUserIds, Guid invitingUserId, Guid providerId)
{
public static ProviderUserInvite<string> CreateIntialInvite(IEnumerable<string> inviteeEmails, ProviderUserType type, Guid invitingUserId, Guid providerId)
return new ProviderUserInvite<Guid>
{
return new ProviderUserInvite<string>
{
UserIdentifiers = inviteeEmails,
Type = type,
InvitingUserId = invitingUserId,
ProviderId = providerId
};
}
public static ProviderUserInvite<Guid> CreateReinvite(IEnumerable<Guid> inviteeUserIds, Guid invitingUserId, Guid providerId)
{
return new ProviderUserInvite<Guid>
{
UserIdentifiers = inviteeUserIds,
InvitingUserId = invitingUserId,
ProviderId = providerId
};
}
UserIdentifiers = inviteeUserIds,
InvitingUserId = invitingUserId,
ProviderId = providerId
};
}
}

View File

@ -2,61 +2,60 @@
using Bit.Core.Entities;
using Bit.Core.Enums;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class ReferenceEvent
{
public class ReferenceEvent
public ReferenceEvent() { }
public ReferenceEvent(ReferenceEventType type, IReferenceable source)
{
public ReferenceEvent() { }
public ReferenceEvent(ReferenceEventType type, IReferenceable source)
Type = type;
if (source != null)
{
Type = type;
if (source != null)
{
Source = source.IsUser() ? ReferenceEventSource.User : ReferenceEventSource.Organization;
Id = source.Id;
ReferenceData = source.ReferenceData;
}
Source = source.IsUser() ? ReferenceEventSource.User : ReferenceEventSource.Organization;
Id = source.Id;
ReferenceData = source.ReferenceData;
}
[JsonConverter(typeof(JsonStringEnumConverter))]
public ReferenceEventType Type { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public ReferenceEventSource Source { get; set; }
public Guid Id { get; set; }
public string ReferenceData { get; set; }
public DateTime EventDate { get; set; } = DateTime.UtcNow;
public int? Users { get; set; }
public bool? EndOfPeriod { get; set; }
public string PlanName { get; set; }
public PlanType? PlanType { get; set; }
public string OldPlanName { get; set; }
public PlanType? OldPlanType { get; set; }
public int? Seats { get; set; }
public int? PreviousSeats { get; set; }
public short? Storage { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public SendType? SendType { get; set; }
public int? MaxAccessCount { get; set; }
public bool? HasPassword { get; set; }
public string EventRaisedByUser { get; set; }
public bool? SalesAssistedTrialStarted { get; set; }
}
[JsonConverter(typeof(JsonStringEnumConverter))]
public ReferenceEventType Type { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public ReferenceEventSource Source { get; set; }
public Guid Id { get; set; }
public string ReferenceData { get; set; }
public DateTime EventDate { get; set; } = DateTime.UtcNow;
public int? Users { get; set; }
public bool? EndOfPeriod { get; set; }
public string PlanName { get; set; }
public PlanType? PlanType { get; set; }
public string OldPlanName { get; set; }
public PlanType? OldPlanType { get; set; }
public int? Seats { get; set; }
public int? PreviousSeats { get; set; }
public short? Storage { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public SendType? SendType { get; set; }
public int? MaxAccessCount { get; set; }
public bool? HasPassword { get; set; }
public string EventRaisedByUser { get; set; }
public bool? SalesAssistedTrialStarted { get; set; }
}

View File

@ -1,84 +1,83 @@
using Bit.Core.Entities;
using Stripe;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class OrganizationSubscriptionOptionsBase : Stripe.SubscriptionCreateOptions
{
public class OrganizationSubscriptionOptionsBase : Stripe.SubscriptionCreateOptions
public OrganizationSubscriptionOptionsBase(Organization org, StaticStore.Plan plan, TaxInfo taxInfo, int additionalSeats, int additionalStorageGb, bool premiumAccessAddon)
{
public OrganizationSubscriptionOptionsBase(Organization org, StaticStore.Plan plan, TaxInfo taxInfo, int additionalSeats, int additionalStorageGb, bool premiumAccessAddon)
Items = new List<SubscriptionItemOptions>();
Metadata = new Dictionary<string, string>
{
Items = new List<SubscriptionItemOptions>();
Metadata = new Dictionary<string, string>
{
[org.GatewayIdField()] = org.Id.ToString()
};
[org.GatewayIdField()] = org.Id.ToString()
};
if (plan.StripePlanId != null)
if (plan.StripePlanId != null)
{
Items.Add(new SubscriptionItemOptions
{
Items.Add(new SubscriptionItemOptions
{
Plan = plan.StripePlanId,
Quantity = 1
});
}
if (additionalSeats > 0 && plan.StripeSeatPlanId != null)
{
Items.Add(new SubscriptionItemOptions
{
Plan = plan.StripeSeatPlanId,
Quantity = additionalSeats
});
}
if (additionalStorageGb > 0)
{
Items.Add(new SubscriptionItemOptions
{
Plan = plan.StripeStoragePlanId,
Quantity = additionalStorageGb
});
}
if (premiumAccessAddon && plan.StripePremiumAccessPlanId != null)
{
Items.Add(new SubscriptionItemOptions
{
Plan = plan.StripePremiumAccessPlanId,
Quantity = 1
});
}
if (!string.IsNullOrWhiteSpace(taxInfo?.StripeTaxRateId))
{
DefaultTaxRates = new List<string> { taxInfo.StripeTaxRateId };
}
Plan = plan.StripePlanId,
Quantity = 1
});
}
}
public class OrganizationPurchaseSubscriptionOptions : OrganizationSubscriptionOptionsBase
{
public OrganizationPurchaseSubscriptionOptions(
Organization org, StaticStore.Plan plan,
TaxInfo taxInfo, int additionalSeats = 0,
int additionalStorageGb = 0, bool premiumAccessAddon = false) :
base(org, plan, taxInfo, additionalSeats, additionalStorageGb, premiumAccessAddon)
if (additionalSeats > 0 && plan.StripeSeatPlanId != null)
{
OffSession = true;
TrialPeriodDays = plan.TrialPeriodDays;
Items.Add(new SubscriptionItemOptions
{
Plan = plan.StripeSeatPlanId,
Quantity = additionalSeats
});
}
}
public class OrganizationUpgradeSubscriptionOptions : OrganizationSubscriptionOptionsBase
{
public OrganizationUpgradeSubscriptionOptions(
string customerId, Organization org,
StaticStore.Plan plan, TaxInfo taxInfo,
int additionalSeats = 0, int additionalStorageGb = 0,
bool premiumAccessAddon = false) :
base(org, plan, taxInfo, additionalSeats, additionalStorageGb, premiumAccessAddon)
if (additionalStorageGb > 0)
{
Customer = customerId;
Items.Add(new SubscriptionItemOptions
{
Plan = plan.StripeStoragePlanId,
Quantity = additionalStorageGb
});
}
if (premiumAccessAddon && plan.StripePremiumAccessPlanId != null)
{
Items.Add(new SubscriptionItemOptions
{
Plan = plan.StripePremiumAccessPlanId,
Quantity = 1
});
}
if (!string.IsNullOrWhiteSpace(taxInfo?.StripeTaxRateId))
{
DefaultTaxRates = new List<string> { taxInfo.StripeTaxRateId };
}
}
}
public class OrganizationPurchaseSubscriptionOptions : OrganizationSubscriptionOptionsBase
{
public OrganizationPurchaseSubscriptionOptions(
Organization org, StaticStore.Plan plan,
TaxInfo taxInfo, int additionalSeats = 0,
int additionalStorageGb = 0, bool premiumAccessAddon = false) :
base(org, plan, taxInfo, additionalSeats, additionalStorageGb, premiumAccessAddon)
{
OffSession = true;
TrialPeriodDays = plan.TrialPeriodDays;
}
}
public class OrganizationUpgradeSubscriptionOptions : OrganizationSubscriptionOptionsBase
{
public OrganizationUpgradeSubscriptionOptions(
string customerId, Organization org,
StaticStore.Plan plan, TaxInfo taxInfo,
int additionalSeats = 0, int additionalStorageGb = 0,
bool premiumAccessAddon = false) :
base(org, plan, taxInfo, additionalSeats, additionalStorageGb, premiumAccessAddon)
{
Customer = customerId;
}
}

View File

@ -1,87 +1,86 @@
using Stripe;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class SubscriptionInfo
{
public class SubscriptionInfo
public BillingSubscription Subscription { get; set; }
public BillingUpcomingInvoice UpcomingInvoice { get; set; }
public bool UsingInAppPurchase { get; set; }
public class BillingSubscription
{
public BillingSubscription Subscription { get; set; }
public BillingUpcomingInvoice UpcomingInvoice { get; set; }
public bool UsingInAppPurchase { get; set; }
public class BillingSubscription
public BillingSubscription(Subscription sub)
{
public BillingSubscription(Subscription sub)
Status = sub.Status;
TrialStartDate = sub.TrialStart;
TrialEndDate = sub.TrialEnd;
PeriodStartDate = sub.CurrentPeriodStart;
PeriodEndDate = sub.CurrentPeriodEnd;
CancelledDate = sub.CanceledAt;
CancelAtEndDate = sub.CancelAtPeriodEnd;
Cancelled = sub.Status == "canceled" || sub.Status == "unpaid" || sub.Status == "incomplete_expired";
if (sub.Items?.Data != null)
{
Status = sub.Status;
TrialStartDate = sub.TrialStart;
TrialEndDate = sub.TrialEnd;
PeriodStartDate = sub.CurrentPeriodStart;
PeriodEndDate = sub.CurrentPeriodEnd;
CancelledDate = sub.CanceledAt;
CancelAtEndDate = sub.CancelAtPeriodEnd;
Cancelled = sub.Status == "canceled" || sub.Status == "unpaid" || sub.Status == "incomplete_expired";
if (sub.Items?.Data != null)
{
Items = sub.Items.Data.Select(i => new BillingSubscriptionItem(i));
}
}
public DateTime? TrialStartDate { get; set; }
public DateTime? TrialEndDate { get; set; }
public DateTime? PeriodStartDate { get; set; }
public DateTime? PeriodEndDate { get; set; }
public TimeSpan? PeriodDuration => PeriodEndDate - PeriodStartDate;
public DateTime? CancelledDate { get; set; }
public bool CancelAtEndDate { get; set; }
public string Status { get; set; }
public bool Cancelled { get; set; }
public IEnumerable<BillingSubscriptionItem> Items { get; set; } = new List<BillingSubscriptionItem>();
public class BillingSubscriptionItem
{
public BillingSubscriptionItem(SubscriptionItem item)
{
if (item.Plan != null)
{
Name = item.Plan.Nickname;
Amount = item.Plan.Amount.GetValueOrDefault() / 100M;
Interval = item.Plan.Interval;
}
Quantity = (int)item.Quantity;
SponsoredSubscriptionItem = Utilities.StaticStore.SponsoredPlans.Any(p => p.StripePlanId == item.Plan.Id);
}
public string Name { get; set; }
public decimal Amount { get; set; }
public int Quantity { get; set; }
public string Interval { get; set; }
public bool SponsoredSubscriptionItem { get; set; }
Items = sub.Items.Data.Select(i => new BillingSubscriptionItem(i));
}
}
public class BillingUpcomingInvoice
public DateTime? TrialStartDate { get; set; }
public DateTime? TrialEndDate { get; set; }
public DateTime? PeriodStartDate { get; set; }
public DateTime? PeriodEndDate { get; set; }
public TimeSpan? PeriodDuration => PeriodEndDate - PeriodStartDate;
public DateTime? CancelledDate { get; set; }
public bool CancelAtEndDate { get; set; }
public string Status { get; set; }
public bool Cancelled { get; set; }
public IEnumerable<BillingSubscriptionItem> Items { get; set; } = new List<BillingSubscriptionItem>();
public class BillingSubscriptionItem
{
public BillingUpcomingInvoice() { }
public BillingUpcomingInvoice(Invoice inv)
public BillingSubscriptionItem(SubscriptionItem item)
{
Amount = inv.AmountDue / 100M;
Date = inv.Created;
}
public BillingUpcomingInvoice(Braintree.Subscription sub)
{
Amount = sub.NextBillAmount.GetValueOrDefault() + sub.Balance.GetValueOrDefault();
if (Amount < 0)
if (item.Plan != null)
{
Amount = 0;
Name = item.Plan.Nickname;
Amount = item.Plan.Amount.GetValueOrDefault() / 100M;
Interval = item.Plan.Interval;
}
Date = sub.NextBillingDate;
Quantity = (int)item.Quantity;
SponsoredSubscriptionItem = Utilities.StaticStore.SponsoredPlans.Any(p => p.StripePlanId == item.Plan.Id);
}
public string Name { get; set; }
public decimal Amount { get; set; }
public DateTime? Date { get; set; }
public int Quantity { get; set; }
public string Interval { get; set; }
public bool SponsoredSubscriptionItem { get; set; }
}
}
public class BillingUpcomingInvoice
{
public BillingUpcomingInvoice() { }
public BillingUpcomingInvoice(Invoice inv)
{
Amount = inv.AmountDue / 100M;
Date = inv.Created;
}
public BillingUpcomingInvoice(Braintree.Subscription sub)
{
Amount = sub.NextBillAmount.GetValueOrDefault() + sub.Balance.GetValueOrDefault();
if (Amount < 0)
{
Amount = 0;
}
Date = sub.NextBillingDate;
}
public decimal Amount { get; set; }
public DateTime? Date { get; set; }
}
}

View File

@ -1,210 +1,209 @@
using Bit.Core.Entities;
using Stripe;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public abstract class SubscriptionUpdate
{
public abstract class SubscriptionUpdate
protected abstract List<string> PlanIds { get; }
public abstract List<SubscriptionItemOptions> RevertItemsOptions(Subscription subscription);
public abstract List<SubscriptionItemOptions> UpgradeItemsOptions(Subscription subscription);
public bool UpdateNeeded(Subscription subscription)
{
protected abstract List<string> PlanIds { get; }
public abstract List<SubscriptionItemOptions> RevertItemsOptions(Subscription subscription);
public abstract List<SubscriptionItemOptions> UpgradeItemsOptions(Subscription subscription);
public bool UpdateNeeded(Subscription subscription)
var upgradeItemsOptions = UpgradeItemsOptions(subscription);
foreach (var upgradeItemOptions in upgradeItemsOptions)
{
var upgradeItemsOptions = UpgradeItemsOptions(subscription);
foreach (var upgradeItemOptions in upgradeItemsOptions)
var upgradeQuantity = upgradeItemOptions.Quantity ?? 0;
var existingQuantity = SubscriptionItem(subscription, upgradeItemOptions.Plan)?.Quantity ?? 0;
if (upgradeQuantity != existingQuantity)
{
var upgradeQuantity = upgradeItemOptions.Quantity ?? 0;
var existingQuantity = SubscriptionItem(subscription, upgradeItemOptions.Plan)?.Quantity ?? 0;
if (upgradeQuantity != existingQuantity)
{
return true;
}
return true;
}
return false;
}
protected static SubscriptionItem SubscriptionItem(Subscription subscription, string planId) =>
planId == null ? null : subscription.Items?.Data?.FirstOrDefault(i => i.Plan.Id == planId);
return false;
}
protected static SubscriptionItem SubscriptionItem(Subscription subscription, string planId) =>
planId == null ? null : subscription.Items?.Data?.FirstOrDefault(i => i.Plan.Id == planId);
}
public class SeatSubscriptionUpdate : SubscriptionUpdate
public class SeatSubscriptionUpdate : SubscriptionUpdate
{
private readonly int _previousSeats;
private readonly StaticStore.Plan _plan;
private readonly long? _additionalSeats;
protected override List<string> PlanIds => new() { _plan.StripeSeatPlanId };
public SeatSubscriptionUpdate(Organization organization, StaticStore.Plan plan, long? additionalSeats)
{
private readonly int _previousSeats;
private readonly StaticStore.Plan _plan;
private readonly long? _additionalSeats;
protected override List<string> PlanIds => new() { _plan.StripeSeatPlanId };
public SeatSubscriptionUpdate(Organization organization, StaticStore.Plan plan, long? additionalSeats)
{
_plan = plan;
_additionalSeats = additionalSeats;
_previousSeats = organization.Seats ?? 0;
}
public override List<SubscriptionItemOptions> UpgradeItemsOptions(Subscription subscription)
{
var item = SubscriptionItem(subscription, PlanIds.Single());
return new()
{
new SubscriptionItemOptions
{
Id = item?.Id,
Plan = PlanIds.Single(),
Quantity = _additionalSeats,
Deleted = (item?.Id != null && _additionalSeats == 0) ? true : (bool?)null,
}
};
}
public override List<SubscriptionItemOptions> RevertItemsOptions(Subscription subscription)
{
var item = SubscriptionItem(subscription, PlanIds.Single());
return new()
{
new SubscriptionItemOptions
{
Id = item?.Id,
Plan = PlanIds.Single(),
Quantity = _previousSeats,
Deleted = _previousSeats == 0 ? true : (bool?)null,
}
};
}
_plan = plan;
_additionalSeats = additionalSeats;
_previousSeats = organization.Seats ?? 0;
}
public class StorageSubscriptionUpdate : SubscriptionUpdate
public override List<SubscriptionItemOptions> UpgradeItemsOptions(Subscription subscription)
{
private long? _prevStorage;
private readonly string _plan;
private readonly long? _additionalStorage;
protected override List<string> PlanIds => new() { _plan };
public StorageSubscriptionUpdate(string plan, long? additionalStorage)
var item = SubscriptionItem(subscription, PlanIds.Single());
return new()
{
_plan = plan;
_additionalStorage = additionalStorage;
}
public override List<SubscriptionItemOptions> UpgradeItemsOptions(Subscription subscription)
{
var item = SubscriptionItem(subscription, PlanIds.Single());
_prevStorage = item?.Quantity ?? 0;
return new()
new SubscriptionItemOptions
{
new SubscriptionItemOptions
{
Id = item?.Id,
Plan = _plan,
Quantity = _additionalStorage,
Deleted = (item?.Id != null && _additionalStorage == 0) ? true : (bool?)null,
}
};
}
public override List<SubscriptionItemOptions> RevertItemsOptions(Subscription subscription)
{
if (!_prevStorage.HasValue)
{
throw new Exception("Unknown previous value, must first call UpgradeItemsOptions");
Id = item?.Id,
Plan = PlanIds.Single(),
Quantity = _additionalSeats,
Deleted = (item?.Id != null && _additionalSeats == 0) ? true : (bool?)null,
}
var item = SubscriptionItem(subscription, PlanIds.Single());
return new()
{
new SubscriptionItemOptions
{
Id = item?.Id,
Plan = _plan,
Quantity = _prevStorage.Value,
Deleted = _prevStorage.Value == 0 ? true : (bool?)null,
}
};
}
};
}
public class SponsorOrganizationSubscriptionUpdate : SubscriptionUpdate
public override List<SubscriptionItemOptions> RevertItemsOptions(Subscription subscription)
{
private readonly string _existingPlanStripeId;
private readonly string _sponsoredPlanStripeId;
private readonly bool _applySponsorship;
protected override List<string> PlanIds => new() { _existingPlanStripeId, _sponsoredPlanStripeId };
public SponsorOrganizationSubscriptionUpdate(StaticStore.Plan existingPlan, StaticStore.SponsoredPlan sponsoredPlan, bool applySponsorship)
var item = SubscriptionItem(subscription, PlanIds.Single());
return new()
{
_existingPlanStripeId = existingPlan.StripePlanId;
_sponsoredPlanStripeId = sponsoredPlan?.StripePlanId;
_applySponsorship = applySponsorship;
}
public override List<SubscriptionItemOptions> RevertItemsOptions(Subscription subscription)
{
var result = new List<SubscriptionItemOptions>();
if (!string.IsNullOrWhiteSpace(AddStripePlanId))
new SubscriptionItemOptions
{
result.Add(new SubscriptionItemOptions
{
Id = AddStripeItem(subscription)?.Id,
Plan = AddStripePlanId,
Quantity = 0,
Deleted = true,
});
Id = item?.Id,
Plan = PlanIds.Single(),
Quantity = _previousSeats,
Deleted = _previousSeats == 0 ? true : (bool?)null,
}
if (!string.IsNullOrWhiteSpace(RemoveStripePlanId))
{
result.Add(new SubscriptionItemOptions
{
Id = RemoveStripeItem(subscription)?.Id,
Plan = RemoveStripePlanId,
Quantity = 1,
Deleted = false,
});
}
return result;
}
public override List<SubscriptionItemOptions> UpgradeItemsOptions(Subscription subscription)
{
var result = new List<SubscriptionItemOptions>();
if (RemoveStripeItem(subscription) != null)
{
result.Add(new SubscriptionItemOptions
{
Id = RemoveStripeItem(subscription)?.Id,
Plan = RemoveStripePlanId,
Quantity = 0,
Deleted = true,
});
}
if (!string.IsNullOrWhiteSpace(AddStripePlanId))
{
result.Add(new SubscriptionItemOptions
{
Id = AddStripeItem(subscription)?.Id,
Plan = AddStripePlanId,
Quantity = 1,
Deleted = false,
});
}
return result;
}
private string RemoveStripePlanId => _applySponsorship ? _existingPlanStripeId : _sponsoredPlanStripeId;
private string AddStripePlanId => _applySponsorship ? _sponsoredPlanStripeId : _existingPlanStripeId;
private Stripe.SubscriptionItem RemoveStripeItem(Subscription subscription) =>
_applySponsorship ?
SubscriptionItem(subscription, _existingPlanStripeId) :
SubscriptionItem(subscription, _sponsoredPlanStripeId);
private Stripe.SubscriptionItem AddStripeItem(Subscription subscription) =>
_applySponsorship ?
SubscriptionItem(subscription, _sponsoredPlanStripeId) :
SubscriptionItem(subscription, _existingPlanStripeId);
};
}
}
public class StorageSubscriptionUpdate : SubscriptionUpdate
{
private long? _prevStorage;
private readonly string _plan;
private readonly long? _additionalStorage;
protected override List<string> PlanIds => new() { _plan };
public StorageSubscriptionUpdate(string plan, long? additionalStorage)
{
_plan = plan;
_additionalStorage = additionalStorage;
}
public override List<SubscriptionItemOptions> UpgradeItemsOptions(Subscription subscription)
{
var item = SubscriptionItem(subscription, PlanIds.Single());
_prevStorage = item?.Quantity ?? 0;
return new()
{
new SubscriptionItemOptions
{
Id = item?.Id,
Plan = _plan,
Quantity = _additionalStorage,
Deleted = (item?.Id != null && _additionalStorage == 0) ? true : (bool?)null,
}
};
}
public override List<SubscriptionItemOptions> RevertItemsOptions(Subscription subscription)
{
if (!_prevStorage.HasValue)
{
throw new Exception("Unknown previous value, must first call UpgradeItemsOptions");
}
var item = SubscriptionItem(subscription, PlanIds.Single());
return new()
{
new SubscriptionItemOptions
{
Id = item?.Id,
Plan = _plan,
Quantity = _prevStorage.Value,
Deleted = _prevStorage.Value == 0 ? true : (bool?)null,
}
};
}
}
public class SponsorOrganizationSubscriptionUpdate : SubscriptionUpdate
{
private readonly string _existingPlanStripeId;
private readonly string _sponsoredPlanStripeId;
private readonly bool _applySponsorship;
protected override List<string> PlanIds => new() { _existingPlanStripeId, _sponsoredPlanStripeId };
public SponsorOrganizationSubscriptionUpdate(StaticStore.Plan existingPlan, StaticStore.SponsoredPlan sponsoredPlan, bool applySponsorship)
{
_existingPlanStripeId = existingPlan.StripePlanId;
_sponsoredPlanStripeId = sponsoredPlan?.StripePlanId;
_applySponsorship = applySponsorship;
}
public override List<SubscriptionItemOptions> RevertItemsOptions(Subscription subscription)
{
var result = new List<SubscriptionItemOptions>();
if (!string.IsNullOrWhiteSpace(AddStripePlanId))
{
result.Add(new SubscriptionItemOptions
{
Id = AddStripeItem(subscription)?.Id,
Plan = AddStripePlanId,
Quantity = 0,
Deleted = true,
});
}
if (!string.IsNullOrWhiteSpace(RemoveStripePlanId))
{
result.Add(new SubscriptionItemOptions
{
Id = RemoveStripeItem(subscription)?.Id,
Plan = RemoveStripePlanId,
Quantity = 1,
Deleted = false,
});
}
return result;
}
public override List<SubscriptionItemOptions> UpgradeItemsOptions(Subscription subscription)
{
var result = new List<SubscriptionItemOptions>();
if (RemoveStripeItem(subscription) != null)
{
result.Add(new SubscriptionItemOptions
{
Id = RemoveStripeItem(subscription)?.Id,
Plan = RemoveStripePlanId,
Quantity = 0,
Deleted = true,
});
}
if (!string.IsNullOrWhiteSpace(AddStripePlanId))
{
result.Add(new SubscriptionItemOptions
{
Id = AddStripeItem(subscription)?.Id,
Plan = AddStripePlanId,
Quantity = 1,
Deleted = false,
});
}
return result;
}
private string RemoveStripePlanId => _applySponsorship ? _existingPlanStripeId : _sponsoredPlanStripeId;
private string AddStripePlanId => _applySponsorship ? _sponsoredPlanStripeId : _existingPlanStripeId;
private Stripe.SubscriptionItem RemoveStripeItem(Subscription subscription) =>
_applySponsorship ?
SubscriptionItem(subscription, _existingPlanStripeId) :
SubscriptionItem(subscription, _sponsoredPlanStripeId);
private Stripe.SubscriptionItem AddStripeItem(Subscription subscription) =>
_applySponsorship ?
SubscriptionItem(subscription, _sponsoredPlanStripeId) :
SubscriptionItem(subscription, _existingPlanStripeId);
}

View File

@ -1,154 +1,153 @@
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class TaxInfo
{
public class TaxInfo
private string _taxIdNumber = null;
private string _taxIdType = null;
public string TaxIdNumber
{
private string _taxIdNumber = null;
private string _taxIdType = null;
public string TaxIdNumber
get => _taxIdNumber;
set
{
get => _taxIdNumber;
set
{
_taxIdNumber = value;
_taxIdType = null;
}
}
public string StripeTaxRateId { 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; }
public string BillingAddressCountry { get; set; } = "US";
public string TaxIdType
{
get
{
if (string.IsNullOrWhiteSpace(BillingAddressCountry) ||
string.IsNullOrWhiteSpace(TaxIdNumber))
{
return null;
}
if (!string.IsNullOrWhiteSpace(_taxIdType))
{
return _taxIdType;
}
switch (BillingAddressCountry)
{
case "AE":
_taxIdType = "ae_trn";
break;
case "AU":
_taxIdType = "au_abn";
break;
case "BR":
_taxIdType = "br_cnpj";
break;
case "CA":
// May break for those in Québec given the assumption of QST
if (BillingAddressState?.Contains("bec") ?? false)
{
_taxIdType = "ca_qst";
break;
}
_taxIdType = "ca_bn";
break;
case "CL":
_taxIdType = "cl_tin";
break;
case "AT":
case "BE":
case "BG":
case "CY":
case "CZ":
case "DE":
case "DK":
case "EE":
case "ES":
case "FI":
case "FR":
case "GB":
case "GR":
case "HR":
case "HU":
case "IE":
case "IT":
case "LT":
case "LU":
case "LV":
case "MT":
case "NL":
case "PL":
case "PT":
case "RO":
case "SE":
case "SI":
case "SK":
_taxIdType = "eu_vat";
break;
case "HK":
_taxIdType = "hk_br";
break;
case "IN":
_taxIdType = "in_gst";
break;
case "JP":
_taxIdType = "jp_cn";
break;
case "KR":
_taxIdType = "kr_brn";
break;
case "LI":
_taxIdType = "li_uid";
break;
case "MX":
_taxIdType = "mx_rfc";
break;
case "MY":
_taxIdType = "my_sst";
break;
case "NO":
_taxIdType = "no_vat";
break;
case "NZ":
_taxIdType = "nz_gst";
break;
case "RU":
_taxIdType = "ru_inn";
break;
case "SA":
_taxIdType = "sa_vat";
break;
case "SG":
_taxIdType = "sg_gst";
break;
case "TH":
_taxIdType = "th_vat";
break;
case "TW":
_taxIdType = "tw_vat";
break;
case "US":
_taxIdType = "us_ein";
break;
case "ZA":
_taxIdType = "za_vat";
break;
default:
_taxIdType = null;
break;
}
return _taxIdType;
}
}
public bool HasTaxId
{
get => !string.IsNullOrWhiteSpace(TaxIdNumber) &&
!string.IsNullOrWhiteSpace(TaxIdType);
_taxIdNumber = value;
_taxIdType = null;
}
}
public string StripeTaxRateId { 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; }
public string BillingAddressCountry { get; set; } = "US";
public string TaxIdType
{
get
{
if (string.IsNullOrWhiteSpace(BillingAddressCountry) ||
string.IsNullOrWhiteSpace(TaxIdNumber))
{
return null;
}
if (!string.IsNullOrWhiteSpace(_taxIdType))
{
return _taxIdType;
}
switch (BillingAddressCountry)
{
case "AE":
_taxIdType = "ae_trn";
break;
case "AU":
_taxIdType = "au_abn";
break;
case "BR":
_taxIdType = "br_cnpj";
break;
case "CA":
// May break for those in Québec given the assumption of QST
if (BillingAddressState?.Contains("bec") ?? false)
{
_taxIdType = "ca_qst";
break;
}
_taxIdType = "ca_bn";
break;
case "CL":
_taxIdType = "cl_tin";
break;
case "AT":
case "BE":
case "BG":
case "CY":
case "CZ":
case "DE":
case "DK":
case "EE":
case "ES":
case "FI":
case "FR":
case "GB":
case "GR":
case "HR":
case "HU":
case "IE":
case "IT":
case "LT":
case "LU":
case "LV":
case "MT":
case "NL":
case "PL":
case "PT":
case "RO":
case "SE":
case "SI":
case "SK":
_taxIdType = "eu_vat";
break;
case "HK":
_taxIdType = "hk_br";
break;
case "IN":
_taxIdType = "in_gst";
break;
case "JP":
_taxIdType = "jp_cn";
break;
case "KR":
_taxIdType = "kr_brn";
break;
case "LI":
_taxIdType = "li_uid";
break;
case "MX":
_taxIdType = "mx_rfc";
break;
case "MY":
_taxIdType = "my_sst";
break;
case "NO":
_taxIdType = "no_vat";
break;
case "NZ":
_taxIdType = "nz_gst";
break;
case "RU":
_taxIdType = "ru_inn";
break;
case "SA":
_taxIdType = "sa_vat";
break;
case "SG":
_taxIdType = "sg_gst";
break;
case "TH":
_taxIdType = "th_vat";
break;
case "TW":
_taxIdType = "tw_vat";
break;
case "US":
_taxIdType = "us_ein";
break;
case "ZA":
_taxIdType = "za_vat";
break;
default:
_taxIdType = null;
break;
}
return _taxIdType;
}
}
public bool HasTaxId
{
get => !string.IsNullOrWhiteSpace(TaxIdNumber) &&
!string.IsNullOrWhiteSpace(TaxIdType);
}
}

View File

@ -1,36 +1,35 @@
using System.Text.Json.Serialization;
using Bit.Core.Entities;
namespace Bit.Core.Models.Business.Tokenables
namespace Bit.Core.Models.Business.Tokenables;
public class EmergencyAccessInviteTokenable : Tokens.ExpiringTokenable
{
public class EmergencyAccessInviteTokenable : Tokens.ExpiringTokenable
public const string ClearTextPrefix = "";
public const string DataProtectorPurpose = "EmergencyAccessServiceDataProtector";
public const string TokenIdentifier = "EmergencyAccessInvite";
public string Identifier { get; set; } = TokenIdentifier;
public Guid Id { get; set; }
public string Email { get; set; }
[JsonConstructor]
public EmergencyAccessInviteTokenable(DateTime expirationDate)
{
public const string ClearTextPrefix = "";
public const string DataProtectorPurpose = "EmergencyAccessServiceDataProtector";
public const string TokenIdentifier = "EmergencyAccessInvite";
public string Identifier { get; set; } = TokenIdentifier;
public Guid Id { get; set; }
public string Email { get; set; }
[JsonConstructor]
public EmergencyAccessInviteTokenable(DateTime expirationDate)
{
ExpirationDate = expirationDate;
}
public EmergencyAccessInviteTokenable(EmergencyAccess user, int hoursTillExpiration)
{
Id = user.Id;
Email = user.Email;
ExpirationDate = DateTime.UtcNow.AddHours(hoursTillExpiration);
}
public bool IsValid(Guid id, string email)
{
return Id == id &&
Email.Equals(email, StringComparison.InvariantCultureIgnoreCase);
}
protected override bool TokenIsValid() => Identifier == TokenIdentifier && Id != default && !string.IsNullOrWhiteSpace(Email);
ExpirationDate = expirationDate;
}
public EmergencyAccessInviteTokenable(EmergencyAccess user, int hoursTillExpiration)
{
Id = user.Id;
Email = user.Email;
ExpirationDate = DateTime.UtcNow.AddHours(hoursTillExpiration);
}
public bool IsValid(Guid id, string email)
{
return Id == id &&
Email.Equals(email, StringComparison.InvariantCultureIgnoreCase);
}
protected override bool TokenIsValid() => Identifier == TokenIdentifier && Id != default && !string.IsNullOrWhiteSpace(Email);
}

View File

@ -2,43 +2,42 @@
using Bit.Core.Entities;
using Bit.Core.Tokens;
namespace Bit.Core.Models.Business.Tokenables
namespace Bit.Core.Models.Business.Tokenables;
public class HCaptchaTokenable : ExpiringTokenable
{
public class HCaptchaTokenable : ExpiringTokenable
private const double _tokenLifetimeInHours = (double)5 / 60; // 5 minutes
public const string ClearTextPrefix = "BWCaptchaBypass_";
public const string DataProtectorPurpose = "CaptchaServiceDataProtector";
public const string TokenIdentifier = "CaptchaBypassToken";
public string Identifier { get; set; } = TokenIdentifier;
public Guid Id { get; set; }
public string Email { get; set; }
[JsonConstructor]
public HCaptchaTokenable()
{
private const double _tokenLifetimeInHours = (double)5 / 60; // 5 minutes
public const string ClearTextPrefix = "BWCaptchaBypass_";
public const string DataProtectorPurpose = "CaptchaServiceDataProtector";
public const string TokenIdentifier = "CaptchaBypassToken";
public string Identifier { get; set; } = TokenIdentifier;
public Guid Id { get; set; }
public string Email { get; set; }
[JsonConstructor]
public HCaptchaTokenable()
{
ExpirationDate = DateTime.UtcNow.AddHours(_tokenLifetimeInHours);
}
public HCaptchaTokenable(User user) : this()
{
Id = user?.Id ?? default;
Email = user?.Email;
}
public bool TokenIsValid(User user)
{
if (Id == default || Email == default || user == null)
{
return false;
}
return Id == user.Id &&
Email.Equals(user.Email, StringComparison.InvariantCultureIgnoreCase);
}
// Validates deserialized
protected override bool TokenIsValid() => Identifier == TokenIdentifier && Id != default && !string.IsNullOrWhiteSpace(Email);
ExpirationDate = DateTime.UtcNow.AddHours(_tokenLifetimeInHours);
}
public HCaptchaTokenable(User user) : this()
{
Id = user?.Id ?? default;
Email = user?.Email;
}
public bool TokenIsValid(User user)
{
if (Id == default || Email == default || user == null)
{
return false;
}
return Id == user.Id &&
Email.Equals(user.Email, StringComparison.InvariantCultureIgnoreCase);
}
// Validates deserialized
protected override bool TokenIsValid() => Identifier == TokenIdentifier && Id != default && !string.IsNullOrWhiteSpace(Email);
}

View File

@ -3,55 +3,54 @@ using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Tokens;
namespace Bit.Core.Models.Business.Tokenables
namespace Bit.Core.Models.Business.Tokenables;
public class OrganizationSponsorshipOfferTokenable : Tokenable
{
public class OrganizationSponsorshipOfferTokenable : Tokenable
public const string ClearTextPrefix = "BWOrganizationSponsorship_";
public const string DataProtectorPurpose = "OrganizationSponsorshipDataProtector";
public const string TokenIdentifier = "OrganizationSponsorshipOfferToken";
public string Identifier { get; set; } = TokenIdentifier;
public Guid Id { get; set; }
public PlanSponsorshipType SponsorshipType { get; set; }
public string Email { get; set; }
public override bool Valid => !string.IsNullOrWhiteSpace(Email) &&
Identifier == TokenIdentifier &&
Id != default;
[JsonConstructor]
public OrganizationSponsorshipOfferTokenable() { }
public OrganizationSponsorshipOfferTokenable(OrganizationSponsorship sponsorship)
{
public const string ClearTextPrefix = "BWOrganizationSponsorship_";
public const string DataProtectorPurpose = "OrganizationSponsorshipDataProtector";
public const string TokenIdentifier = "OrganizationSponsorshipOfferToken";
public string Identifier { get; set; } = TokenIdentifier;
public Guid Id { get; set; }
public PlanSponsorshipType SponsorshipType { get; set; }
public string Email { get; set; }
public override bool Valid => !string.IsNullOrWhiteSpace(Email) &&
Identifier == TokenIdentifier &&
Id != default;
[JsonConstructor]
public OrganizationSponsorshipOfferTokenable() { }
public OrganizationSponsorshipOfferTokenable(OrganizationSponsorship sponsorship)
if (string.IsNullOrWhiteSpace(sponsorship.OfferedToEmail))
{
if (string.IsNullOrWhiteSpace(sponsorship.OfferedToEmail))
{
throw new ArgumentException("Invalid OrganizationSponsorship to create a token, OfferedToEmail is required", nameof(sponsorship));
}
Email = sponsorship.OfferedToEmail;
if (!sponsorship.PlanSponsorshipType.HasValue)
{
throw new ArgumentException("Invalid OrganizationSponsorship to create a token, PlanSponsorshipType is required", nameof(sponsorship));
}
SponsorshipType = sponsorship.PlanSponsorshipType.Value;
if (sponsorship.Id == default)
{
throw new ArgumentException("Invalid OrganizationSponsorship to create a token, Id is required", nameof(sponsorship));
}
Id = sponsorship.Id;
throw new ArgumentException("Invalid OrganizationSponsorship to create a token, OfferedToEmail is required", nameof(sponsorship));
}
Email = sponsorship.OfferedToEmail;
public bool IsValid(OrganizationSponsorship sponsorship, string currentUserEmail) =>
sponsorship != null &&
sponsorship.PlanSponsorshipType.HasValue &&
SponsorshipType == sponsorship.PlanSponsorshipType.Value &&
Id == sponsorship.Id &&
!string.IsNullOrWhiteSpace(sponsorship.OfferedToEmail) &&
Email.Equals(currentUserEmail, StringComparison.InvariantCultureIgnoreCase) &&
Email.Equals(sponsorship.OfferedToEmail, StringComparison.InvariantCultureIgnoreCase);
if (!sponsorship.PlanSponsorshipType.HasValue)
{
throw new ArgumentException("Invalid OrganizationSponsorship to create a token, PlanSponsorshipType is required", nameof(sponsorship));
}
SponsorshipType = sponsorship.PlanSponsorshipType.Value;
if (sponsorship.Id == default)
{
throw new ArgumentException("Invalid OrganizationSponsorship to create a token, Id is required", nameof(sponsorship));
}
Id = sponsorship.Id;
}
public bool IsValid(OrganizationSponsorship sponsorship, string currentUserEmail) =>
sponsorship != null &&
sponsorship.PlanSponsorshipType.HasValue &&
SponsorshipType == sponsorship.PlanSponsorshipType.Value &&
Id == sponsorship.Id &&
!string.IsNullOrWhiteSpace(sponsorship.OfferedToEmail) &&
Email.Equals(currentUserEmail, StringComparison.InvariantCultureIgnoreCase) &&
Email.Equals(sponsorship.OfferedToEmail, StringComparison.InvariantCultureIgnoreCase);
}

View File

@ -2,43 +2,42 @@
using Bit.Core.Entities;
using Bit.Core.Tokens;
namespace Bit.Core.Models.Business.Tokenables
namespace Bit.Core.Models.Business.Tokenables;
public class SsoTokenable : ExpiringTokenable
{
public class SsoTokenable : ExpiringTokenable
public const string ClearTextPrefix = "BWUserPrefix_";
public const string DataProtectorPurpose = "SsoTokenDataProtector";
public const string TokenIdentifier = "ssoToken";
public Guid OrganizationId { get; set; }
public string DomainHint { get; set; }
public string Identifier { get; set; } = TokenIdentifier;
[JsonConstructor]
public SsoTokenable() { }
public SsoTokenable(Organization organization, double tokenLifetimeInSeconds) : this()
{
public const string ClearTextPrefix = "BWUserPrefix_";
public const string DataProtectorPurpose = "SsoTokenDataProtector";
public const string TokenIdentifier = "ssoToken";
public Guid OrganizationId { get; set; }
public string DomainHint { get; set; }
public string Identifier { get; set; } = TokenIdentifier;
[JsonConstructor]
public SsoTokenable() { }
public SsoTokenable(Organization organization, double tokenLifetimeInSeconds) : this()
{
OrganizationId = organization?.Id ?? default;
DomainHint = organization?.Identifier;
ExpirationDate = DateTime.UtcNow.AddSeconds(tokenLifetimeInSeconds);
}
public bool TokenIsValid(Organization organization)
{
if (OrganizationId == default || DomainHint == default || organization == null || !Valid)
{
return false;
}
return organization.Identifier.Equals(DomainHint, StringComparison.InvariantCultureIgnoreCase)
&& organization.Id.Equals(OrganizationId);
}
// Validates deserialized
protected override bool TokenIsValid() =>
Identifier == TokenIdentifier
&& OrganizationId != default
&& !string.IsNullOrWhiteSpace(DomainHint);
OrganizationId = organization?.Id ?? default;
DomainHint = organization?.Identifier;
ExpirationDate = DateTime.UtcNow.AddSeconds(tokenLifetimeInSeconds);
}
public bool TokenIsValid(Organization organization)
{
if (OrganizationId == default || DomainHint == default || organization == null || !Valid)
{
return false;
}
return organization.Identifier.Equals(DomainHint, StringComparison.InvariantCultureIgnoreCase)
&& organization.Id.Equals(OrganizationId);
}
// Validates deserialized
protected override bool TokenIsValid() =>
Identifier == TokenIdentifier
&& OrganizationId != default
&& !string.IsNullOrWhiteSpace(DomainHint);
}

View File

@ -7,168 +7,167 @@ using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Services;
namespace Bit.Core.Models.Business
namespace Bit.Core.Models.Business;
public class UserLicense : ILicense
{
public class UserLicense : ILicense
public UserLicense()
{ }
public UserLicense(User user, SubscriptionInfo subscriptionInfo, ILicensingService licenseService,
int? version = null)
{
public UserLicense()
{ }
LicenseType = Enums.LicenseType.User;
LicenseKey = user.LicenseKey;
Id = user.Id;
Name = user.Name;
Email = user.Email;
Version = version.GetValueOrDefault(1);
Premium = user.Premium;
MaxStorageGb = user.MaxStorageGb;
Issued = DateTime.UtcNow;
Expires = subscriptionInfo?.UpcomingInvoice?.Date != null ?
subscriptionInfo.UpcomingInvoice.Date.Value.AddDays(7) :
user.PremiumExpirationDate?.AddDays(7);
Refresh = subscriptionInfo?.UpcomingInvoice?.Date;
Trial = (subscriptionInfo?.Subscription?.TrialEndDate.HasValue ?? false) &&
subscriptionInfo.Subscription.TrialEndDate.Value > DateTime.UtcNow;
public UserLicense(User user, SubscriptionInfo subscriptionInfo, ILicensingService licenseService,
int? version = null)
Hash = Convert.ToBase64String(ComputeHash());
Signature = Convert.ToBase64String(licenseService.SignLicense(this));
}
public UserLicense(User user, ILicensingService licenseService, int? version = null)
{
LicenseType = Enums.LicenseType.User;
LicenseKey = user.LicenseKey;
Id = user.Id;
Name = user.Name;
Email = user.Email;
Version = version.GetValueOrDefault(1);
Premium = user.Premium;
MaxStorageGb = user.MaxStorageGb;
Issued = DateTime.UtcNow;
Expires = user.PremiumExpirationDate?.AddDays(7);
Refresh = user.PremiumExpirationDate?.Date;
Trial = false;
Hash = Convert.ToBase64String(ComputeHash());
Signature = Convert.ToBase64String(licenseService.SignLicense(this));
}
public string LicenseKey { get; set; }
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public bool Premium { get; set; }
public short? MaxStorageGb { get; set; }
public int Version { get; set; }
public DateTime Issued { get; set; }
public DateTime? Refresh { get; set; }
public DateTime? Expires { get; set; }
public bool Trial { get; set; }
public LicenseType? LicenseType { get; set; }
public string Hash { get; set; }
public string Signature { get; set; }
[JsonIgnore]
public byte[] SignatureBytes => Convert.FromBase64String(Signature);
public byte[] GetDataBytes(bool forHash = false)
{
string data = null;
if (Version == 1)
{
LicenseType = Enums.LicenseType.User;
LicenseKey = user.LicenseKey;
Id = user.Id;
Name = user.Name;
Email = user.Email;
Version = version.GetValueOrDefault(1);
Premium = user.Premium;
MaxStorageGb = user.MaxStorageGb;
Issued = DateTime.UtcNow;
Expires = subscriptionInfo?.UpcomingInvoice?.Date != null ?
subscriptionInfo.UpcomingInvoice.Date.Value.AddDays(7) :
user.PremiumExpirationDate?.AddDays(7);
Refresh = subscriptionInfo?.UpcomingInvoice?.Date;
Trial = (subscriptionInfo?.Subscription?.TrialEndDate.HasValue ?? false) &&
subscriptionInfo.Subscription.TrialEndDate.Value > DateTime.UtcNow;
Hash = Convert.ToBase64String(ComputeHash());
Signature = Convert.ToBase64String(licenseService.SignLicense(this));
}
public UserLicense(User user, ILicensingService licenseService, int? version = null)
{
LicenseType = Enums.LicenseType.User;
LicenseKey = user.LicenseKey;
Id = user.Id;
Name = user.Name;
Email = user.Email;
Version = version.GetValueOrDefault(1);
Premium = user.Premium;
MaxStorageGb = user.MaxStorageGb;
Issued = DateTime.UtcNow;
Expires = user.PremiumExpirationDate?.AddDays(7);
Refresh = user.PremiumExpirationDate?.Date;
Trial = false;
Hash = Convert.ToBase64String(ComputeHash());
Signature = Convert.ToBase64String(licenseService.SignLicense(this));
}
public string LicenseKey { get; set; }
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public bool Premium { get; set; }
public short? MaxStorageGb { get; set; }
public int Version { get; set; }
public DateTime Issued { get; set; }
public DateTime? Refresh { get; set; }
public DateTime? Expires { get; set; }
public bool Trial { get; set; }
public LicenseType? LicenseType { get; set; }
public string Hash { get; set; }
public string Signature { get; set; }
[JsonIgnore]
public byte[] SignatureBytes => Convert.FromBase64String(Signature);
public byte[] GetDataBytes(bool forHash = false)
{
string data = null;
if (Version == 1)
{
var props = typeof(UserLicense)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p =>
!p.Name.Equals(nameof(Signature)) &&
!p.Name.Equals(nameof(SignatureBytes)) &&
!p.Name.Equals(nameof(LicenseType)) &&
var props = typeof(UserLicense)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p =>
!p.Name.Equals(nameof(Signature)) &&
!p.Name.Equals(nameof(SignatureBytes)) &&
!p.Name.Equals(nameof(LicenseType)) &&
(
!forHash ||
(
!forHash ||
(
!p.Name.Equals(nameof(Hash)) &&
!p.Name.Equals(nameof(Issued)) &&
!p.Name.Equals(nameof(Refresh))
)
))
.OrderBy(p => p.Name)
.Select(p => $"{p.Name}:{Utilities.CoreHelpers.FormatLicenseSignatureValue(p.GetValue(this, null))}")
.Aggregate((c, n) => $"{c}|{n}");
data = $"license:user|{props}";
}
else
{
throw new NotSupportedException($"Version {Version} is not supported.");
}
return Encoding.UTF8.GetBytes(data);
!p.Name.Equals(nameof(Hash)) &&
!p.Name.Equals(nameof(Issued)) &&
!p.Name.Equals(nameof(Refresh))
)
))
.OrderBy(p => p.Name)
.Select(p => $"{p.Name}:{Utilities.CoreHelpers.FormatLicenseSignatureValue(p.GetValue(this, null))}")
.Aggregate((c, n) => $"{c}|{n}");
data = $"license:user|{props}";
}
else
{
throw new NotSupportedException($"Version {Version} is not supported.");
}
public byte[] ComputeHash()
return Encoding.UTF8.GetBytes(data);
}
public byte[] ComputeHash()
{
using (var alg = SHA256.Create())
{
using (var alg = SHA256.Create())
{
return alg.ComputeHash(GetDataBytes(true));
}
return alg.ComputeHash(GetDataBytes(true));
}
}
public bool CanUse(User user)
{
if (Issued > DateTime.UtcNow || Expires < DateTime.UtcNow)
{
return false;
}
public bool CanUse(User user)
if (Version == 1)
{
if (Issued > DateTime.UtcNow || Expires < DateTime.UtcNow)
{
return false;
}
return user.EmailVerified && user.Email.Equals(Email, StringComparison.InvariantCultureIgnoreCase);
}
else
{
throw new NotSupportedException($"Version {Version} is not supported.");
}
}
if (Version == 1)
{
return user.EmailVerified && user.Email.Equals(Email, StringComparison.InvariantCultureIgnoreCase);
}
else
{
throw new NotSupportedException($"Version {Version} is not supported.");
}
public bool VerifyData(User user)
{
if (Issued > DateTime.UtcNow || Expires < DateTime.UtcNow)
{
return false;
}
public bool VerifyData(User user)
if (Version == 1)
{
if (Issued > DateTime.UtcNow || Expires < DateTime.UtcNow)
{
return false;
}
return
user.LicenseKey != null && user.LicenseKey.Equals(LicenseKey) &&
user.Premium == Premium &&
user.Email.Equals(Email, StringComparison.InvariantCultureIgnoreCase);
}
else
{
throw new NotSupportedException($"Version {Version} is not supported.");
}
}
if (Version == 1)
{
return
user.LicenseKey != null && user.LicenseKey.Equals(LicenseKey) &&
user.Premium == Premium &&
user.Email.Equals(Email, StringComparison.InvariantCultureIgnoreCase);
}
else
{
throw new NotSupportedException($"Version {Version} is not supported.");
}
public bool VerifySignature(X509Certificate2 certificate)
{
using (var rsa = certificate.GetRSAPublicKey())
{
return rsa.VerifyData(GetDataBytes(), SignatureBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
}
public byte[] Sign(X509Certificate2 certificate)
{
if (!certificate.HasPrivateKey)
{
throw new InvalidOperationException("You don't have the private key!");
}
public bool VerifySignature(X509Certificate2 certificate)
using (var rsa = certificate.GetRSAPrivateKey())
{
using (var rsa = certificate.GetRSAPublicKey())
{
return rsa.VerifyData(GetDataBytes(), SignatureBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
}
public byte[] Sign(X509Certificate2 certificate)
{
if (!certificate.HasPrivateKey)
{
throw new InvalidOperationException("You don't have the private key!");
}
using (var rsa = certificate.GetRSAPrivateKey())
{
return rsa.SignData(GetDataBytes(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
return rsa.SignData(GetDataBytes(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
}
}

View File

@ -1,12 +1,11 @@
using Bit.Core.Entities;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class AttachmentResponseData
{
public class AttachmentResponseData
{
public string Id { get; set; }
public CipherAttachment.MetaData Data { get; set; }
public Cipher Cipher { get; set; }
public string Url { get; set; }
}
public string Id { get; set; }
public CipherAttachment.MetaData Data { get; set; }
public Cipher Cipher { get; set; }
public string Url { get; set; }
}

View File

@ -1,36 +1,35 @@
using System.Text.Json.Serialization;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class CipherAttachment
{
public class CipherAttachment
public Guid Id { get; set; }
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public string AttachmentId { get; set; }
public string AttachmentData { get; set; }
public class MetaData
{
public Guid Id { get; set; }
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public string AttachmentId { get; set; }
public string AttachmentData { get; set; }
private long _size;
public class MetaData
// We serialize Size as a string since JSON (or Javascript) doesn't support full precision for long numbers
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
public long Size
{
private long _size;
// We serialize Size as a string since JSON (or Javascript) doesn't support full precision for long numbers
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
public long Size
{
get { return _size; }
set { _size = value; }
}
public string FileName { get; set; }
public string Key { get; set; }
public string ContainerName { get; set; } = "attachments";
public bool Validated { get; set; } = true;
// This is stored alongside metadata as an identifier. It does not need repeating in serialization
[JsonIgnore]
public string AttachmentId { get; set; }
get { return _size; }
set { _size = value; }
}
public string FileName { get; set; }
public string Key { get; set; }
public string ContainerName { get; set; } = "attachments";
public bool Validated { get; set; } = true;
// This is stored alongside metadata as an identifier. It does not need repeating in serialization
[JsonIgnore]
public string AttachmentId { get; set; }
}
}

View File

@ -1,14 +1,13 @@
namespace Bit.Core.Models.Data
{
public class CipherCardData : CipherData
{
public CipherCardData() { }
namespace Bit.Core.Models.Data;
public string CardholderName { get; set; }
public string Brand { get; set; }
public string Number { get; set; }
public string ExpMonth { get; set; }
public string ExpYear { get; set; }
public string Code { get; set; }
}
public class CipherCardData : CipherData
{
public CipherCardData() { }
public string CardholderName { get; set; }
public string Brand { get; set; }
public string Number { get; set; }
public string ExpMonth { get; set; }
public string ExpYear { get; set; }
public string Code { get; set; }
}

View File

@ -1,12 +1,11 @@
namespace Bit.Core.Models.Data
{
public abstract class CipherData
{
public CipherData() { }
namespace Bit.Core.Models.Data;
public string Name { get; set; }
public string Notes { get; set; }
public IEnumerable<CipherFieldData> Fields { get; set; }
public IEnumerable<CipherPasswordHistoryData> PasswordHistory { get; set; }
}
public abstract class CipherData
{
public CipherData() { }
public string Name { get; set; }
public string Notes { get; set; }
public IEnumerable<CipherFieldData> Fields { get; set; }
public IEnumerable<CipherPasswordHistoryData> PasswordHistory { get; set; }
}

View File

@ -1,10 +1,9 @@
namespace Core.Models.Data
namespace Core.Models.Data;
public class CipherDetails : CipherOrganizationDetails
{
public class CipherDetails : CipherOrganizationDetails
{
public Guid? FolderId { get; set; }
public bool Favorite { get; set; }
public bool Edit { get; set; }
public bool ViewPassword { get; set; }
}
public Guid? FolderId { get; set; }
public bool Favorite { get; set; }
public bool Edit { get; set; }
public bool ViewPassword { get; set; }
}

View File

@ -1,14 +1,13 @@
using Bit.Core.Enums;
namespace Bit.Core.Models.Data
{
public class CipherFieldData
{
public CipherFieldData() { }
namespace Bit.Core.Models.Data;
public FieldType Type { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public int? LinkedId { get; set; }
}
public class CipherFieldData
{
public CipherFieldData() { }
public FieldType Type { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public int? LinkedId { get; set; }
}

View File

@ -1,26 +1,25 @@
namespace Bit.Core.Models.Data
{
public class CipherIdentityData : CipherData
{
public CipherIdentityData() { }
namespace Bit.Core.Models.Data;
public string Title { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Company { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string SSN { get; set; }
public string Username { get; set; }
public string PassportNumber { get; set; }
public string LicenseNumber { get; set; }
}
public class CipherIdentityData : CipherData
{
public CipherIdentityData() { }
public string Title { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Company { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string SSN { get; set; }
public string Username { get; set; }
public string PassportNumber { get; set; }
public string LicenseNumber { get; set; }
}

View File

@ -1,31 +1,30 @@
using Bit.Core.Enums;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class CipherLoginData : CipherData
{
public class CipherLoginData : CipherData
private string _uri;
public CipherLoginData() { }
public string Uri
{
private string _uri;
get => Uris?.FirstOrDefault()?.Uri ?? _uri;
set { _uri = value; }
}
public IEnumerable<CipherLoginUriData> Uris { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public DateTime? PasswordRevisionDate { get; set; }
public string Totp { get; set; }
public bool? AutofillOnPageLoad { get; set; }
public CipherLoginData() { }
public class CipherLoginUriData
{
public CipherLoginUriData() { }
public string Uri
{
get => Uris?.FirstOrDefault()?.Uri ?? _uri;
set { _uri = value; }
}
public IEnumerable<CipherLoginUriData> Uris { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public DateTime? PasswordRevisionDate { get; set; }
public string Totp { get; set; }
public bool? AutofillOnPageLoad { get; set; }
public class CipherLoginUriData
{
public CipherLoginUriData() { }
public string Uri { get; set; }
public UriMatchType? Match { get; set; } = null;
}
public string Uri { get; set; }
public UriMatchType? Match { get; set; } = null;
}
}

View File

@ -1,9 +1,8 @@
using Bit.Core.Entities;
namespace Core.Models.Data
namespace Core.Models.Data;
public class CipherOrganizationDetails : Cipher
{
public class CipherOrganizationDetails : Cipher
{
public bool OrganizationUseTotp { get; set; }
}
public bool OrganizationUseTotp { get; set; }
}

View File

@ -1,10 +1,9 @@
namespace Bit.Core.Models.Data
{
public class CipherPasswordHistoryData
{
public CipherPasswordHistoryData() { }
namespace Bit.Core.Models.Data;
public string Password { get; set; }
public DateTime LastUsedDate { get; set; }
}
public class CipherPasswordHistoryData
{
public CipherPasswordHistoryData() { }
public string Password { get; set; }
public DateTime LastUsedDate { get; set; }
}

View File

@ -1,11 +1,10 @@
using Bit.Core.Enums;
namespace Bit.Core.Models.Data
{
public class CipherSecureNoteData : CipherData
{
public CipherSecureNoteData() { }
namespace Bit.Core.Models.Data;
public SecureNoteType Type { get; set; }
}
public class CipherSecureNoteData : CipherData
{
public CipherSecureNoteData() { }
public SecureNoteType Type { get; set; }
}

View File

@ -1,10 +1,9 @@
using Bit.Core.Entities;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class CollectionDetails : Collection
{
public class CollectionDetails : Collection
{
public bool ReadOnly { get; set; }
public bool HidePasswords { get; set; }
}
public bool ReadOnly { get; set; }
public bool HidePasswords { get; set; }
}

View File

@ -1,135 +1,134 @@
using System.Collections;
using Microsoft.Azure.Cosmos.Table;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class DictionaryEntity : TableEntity, IDictionary<string, EntityProperty>
{
public class DictionaryEntity : TableEntity, IDictionary<string, EntityProperty>
private IDictionary<string, EntityProperty> _properties = new Dictionary<string, EntityProperty>();
public ICollection<EntityProperty> Values => _properties.Values;
public EntityProperty this[string key]
{
private IDictionary<string, EntityProperty> _properties = new Dictionary<string, EntityProperty>();
get => _properties[key];
set => _properties[key] = value;
}
public ICollection<EntityProperty> Values => _properties.Values;
public int Count => _properties.Count;
public EntityProperty this[string key]
{
get => _properties[key];
set => _properties[key] = value;
}
public bool IsReadOnly => _properties.IsReadOnly;
public int Count => _properties.Count;
public ICollection<string> Keys => _properties.Keys;
public bool IsReadOnly => _properties.IsReadOnly;
public override void ReadEntity(IDictionary<string, EntityProperty> properties,
OperationContext operationContext)
{
_properties = properties;
}
public ICollection<string> Keys => _properties.Keys;
public override IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
{
return _properties;
}
public override void ReadEntity(IDictionary<string, EntityProperty> properties,
OperationContext operationContext)
{
_properties = properties;
}
public void Add(string key, EntityProperty value)
{
_properties.Add(key, value);
}
public override IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
{
return _properties;
}
public void Add(string key, bool value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, EntityProperty value)
{
_properties.Add(key, value);
}
public void Add(string key, byte[] value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, bool value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, DateTime? value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, byte[] value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, DateTimeOffset? value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, DateTime? value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, double value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, DateTimeOffset? value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, Guid value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, double value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, int value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, Guid value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, long value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, int value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, string value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(string key, long value)
{
_properties.Add(key, new EntityProperty(value));
}
public void Add(KeyValuePair<string, EntityProperty> item)
{
_properties.Add(item);
}
public void Add(string key, string value)
{
_properties.Add(key, new EntityProperty(value));
}
public bool ContainsKey(string key)
{
return _properties.ContainsKey(key);
}
public void Add(KeyValuePair<string, EntityProperty> item)
{
_properties.Add(item);
}
public bool Remove(string key)
{
return _properties.Remove(key);
}
public bool ContainsKey(string key)
{
return _properties.ContainsKey(key);
}
public bool TryGetValue(string key, out EntityProperty value)
{
return _properties.TryGetValue(key, out value);
}
public bool Remove(string key)
{
return _properties.Remove(key);
}
public void Clear()
{
_properties.Clear();
}
public bool TryGetValue(string key, out EntityProperty value)
{
return _properties.TryGetValue(key, out value);
}
public bool Contains(KeyValuePair<string, EntityProperty> item)
{
return _properties.Contains(item);
}
public void Clear()
{
_properties.Clear();
}
public void CopyTo(KeyValuePair<string, EntityProperty>[] array, int arrayIndex)
{
_properties.CopyTo(array, arrayIndex);
}
public bool Contains(KeyValuePair<string, EntityProperty> item)
{
return _properties.Contains(item);
}
public bool Remove(KeyValuePair<string, EntityProperty> item)
{
return _properties.Remove(item);
}
public void CopyTo(KeyValuePair<string, EntityProperty>[] array, int arrayIndex)
{
_properties.CopyTo(array, arrayIndex);
}
public IEnumerator<KeyValuePair<string, EntityProperty>> GetEnumerator()
{
return _properties.GetEnumerator();
}
public bool Remove(KeyValuePair<string, EntityProperty> item)
{
return _properties.Remove(item);
}
public IEnumerator<KeyValuePair<string, EntityProperty>> GetEnumerator()
{
return _properties.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _properties.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _properties.GetEnumerator();
}
}

View File

@ -1,12 +1,11 @@
using Bit.Core.Entities;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class EmergencyAccessDetails : EmergencyAccess
{
public class EmergencyAccessDetails : EmergencyAccess
{
public string GranteeName { get; set; }
public string GranteeEmail { get; set; }
public string GrantorName { get; set; }
public string GrantorEmail { get; set; }
}
public string GranteeName { get; set; }
public string GranteeEmail { get; set; }
public string GrantorName { get; set; }
public string GrantorEmail { get; set; }
}

View File

@ -1,11 +1,10 @@
using Bit.Core.Entities;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class EmergencyAccessNotify : EmergencyAccess
{
public class EmergencyAccessNotify : EmergencyAccess
{
public string GrantorEmail { get; set; }
public string GranteeName { get; set; }
public string GranteeEmail { get; set; }
}
public string GrantorEmail { get; set; }
public string GranteeName { get; set; }
public string GranteeEmail { get; set; }
}

View File

@ -1,11 +1,10 @@
using Bit.Core.Entities;
using Core.Models.Data;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class EmergencyAccessViewData
{
public class EmergencyAccessViewData
{
public EmergencyAccess EmergencyAccess { get; set; }
public IEnumerable<CipherDetails> Ciphers { get; set; }
}
public EmergencyAccess EmergencyAccess { get; set; }
public IEnumerable<CipherDetails> Ciphers { get; set; }
}

View File

@ -1,35 +1,34 @@
using Bit.Core.Context;
using Bit.Core.Enums;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class EventMessage : IEvent
{
public class EventMessage : IEvent
public EventMessage() { }
public EventMessage(ICurrentContext currentContext)
: base()
{
public EventMessage() { }
public EventMessage(ICurrentContext currentContext)
: base()
{
IpAddress = currentContext.IpAddress;
DeviceType = currentContext.DeviceType;
}
public DateTime Date { get; set; }
public EventType Type { get; set; }
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public Guid? InstallationId { get; set; }
public Guid? ProviderId { get; set; }
public Guid? CipherId { get; set; }
public Guid? CollectionId { get; set; }
public Guid? GroupId { get; set; }
public Guid? PolicyId { get; set; }
public Guid? OrganizationUserId { get; set; }
public Guid? ProviderUserId { get; set; }
public Guid? ProviderOrganizationId { get; set; }
public Guid? ActingUserId { get; set; }
public DeviceType? DeviceType { get; set; }
public string IpAddress { get; set; }
public Guid? IdempotencyId { get; private set; } = Guid.NewGuid();
IpAddress = currentContext.IpAddress;
DeviceType = currentContext.DeviceType;
}
public DateTime Date { get; set; }
public EventType Type { get; set; }
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public Guid? InstallationId { get; set; }
public Guid? ProviderId { get; set; }
public Guid? CipherId { get; set; }
public Guid? CollectionId { get; set; }
public Guid? GroupId { get; set; }
public Guid? PolicyId { get; set; }
public Guid? OrganizationUserId { get; set; }
public Guid? ProviderUserId { get; set; }
public Guid? ProviderOrganizationId { get; set; }
public Guid? ActingUserId { get; set; }
public DeviceType? DeviceType { get; set; }
public string IpAddress { get; set; }
public Guid? IdempotencyId { get; private set; } = Guid.NewGuid();
}

View File

@ -2,154 +2,153 @@
using Bit.Core.Utilities;
using Microsoft.Azure.Cosmos.Table;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class EventTableEntity : TableEntity, IEvent
{
public class EventTableEntity : TableEntity, IEvent
public EventTableEntity() { }
private EventTableEntity(IEvent e)
{
public EventTableEntity() { }
Date = e.Date;
Type = e.Type;
UserId = e.UserId;
OrganizationId = e.OrganizationId;
InstallationId = e.InstallationId;
ProviderId = e.ProviderId;
CipherId = e.CipherId;
CollectionId = e.CollectionId;
PolicyId = e.PolicyId;
GroupId = e.GroupId;
OrganizationUserId = e.OrganizationUserId;
ProviderUserId = e.ProviderUserId;
ProviderOrganizationId = e.ProviderOrganizationId;
DeviceType = e.DeviceType;
IpAddress = e.IpAddress;
ActingUserId = e.ActingUserId;
}
private EventTableEntity(IEvent e)
public DateTime Date { get; set; }
public EventType Type { get; set; }
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public Guid? InstallationId { get; set; }
public Guid? ProviderId { get; set; }
public Guid? CipherId { get; set; }
public Guid? CollectionId { get; set; }
public Guid? PolicyId { get; set; }
public Guid? GroupId { get; set; }
public Guid? OrganizationUserId { get; set; }
public Guid? ProviderUserId { get; set; }
public Guid? ProviderOrganizationId { get; set; }
public DeviceType? DeviceType { get; set; }
public string IpAddress { get; set; }
public Guid? ActingUserId { get; set; }
public override IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
{
var result = base.WriteEntity(operationContext);
var typeName = nameof(Type);
if (result.ContainsKey(typeName))
{
Date = e.Date;
Type = e.Type;
UserId = e.UserId;
OrganizationId = e.OrganizationId;
InstallationId = e.InstallationId;
ProviderId = e.ProviderId;
CipherId = e.CipherId;
CollectionId = e.CollectionId;
PolicyId = e.PolicyId;
GroupId = e.GroupId;
OrganizationUserId = e.OrganizationUserId;
ProviderUserId = e.ProviderUserId;
ProviderOrganizationId = e.ProviderOrganizationId;
DeviceType = e.DeviceType;
IpAddress = e.IpAddress;
ActingUserId = e.ActingUserId;
result[typeName] = new EntityProperty((int)Type);
}
else
{
result.Add(typeName, new EntityProperty((int)Type));
}
public DateTime Date { get; set; }
public EventType Type { get; set; }
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public Guid? InstallationId { get; set; }
public Guid? ProviderId { get; set; }
public Guid? CipherId { get; set; }
public Guid? CollectionId { get; set; }
public Guid? PolicyId { get; set; }
public Guid? GroupId { get; set; }
public Guid? OrganizationUserId { get; set; }
public Guid? ProviderUserId { get; set; }
public Guid? ProviderOrganizationId { get; set; }
public DeviceType? DeviceType { get; set; }
public string IpAddress { get; set; }
public Guid? ActingUserId { get; set; }
public override IDictionary<string, EntityProperty> WriteEntity(OperationContext operationContext)
var deviceTypeName = nameof(DeviceType);
if (result.ContainsKey(deviceTypeName))
{
var result = base.WriteEntity(operationContext);
var typeName = nameof(Type);
if (result.ContainsKey(typeName))
{
result[typeName] = new EntityProperty((int)Type);
}
else
{
result.Add(typeName, new EntityProperty((int)Type));
}
var deviceTypeName = nameof(DeviceType);
if (result.ContainsKey(deviceTypeName))
{
result[deviceTypeName] = new EntityProperty((int?)DeviceType);
}
else
{
result.Add(deviceTypeName, new EntityProperty((int?)DeviceType));
}
return result;
result[deviceTypeName] = new EntityProperty((int?)DeviceType);
}
else
{
result.Add(deviceTypeName, new EntityProperty((int?)DeviceType));
}
public override void ReadEntity(IDictionary<string, EntityProperty> properties,
OperationContext operationContext)
return result;
}
public override void ReadEntity(IDictionary<string, EntityProperty> properties,
OperationContext operationContext)
{
base.ReadEntity(properties, operationContext);
var typeName = nameof(Type);
if (properties.ContainsKey(typeName) && properties[typeName].Int32Value.HasValue)
{
base.ReadEntity(properties, operationContext);
var typeName = nameof(Type);
if (properties.ContainsKey(typeName) && properties[typeName].Int32Value.HasValue)
{
Type = (EventType)properties[typeName].Int32Value.Value;
}
var deviceTypeName = nameof(DeviceType);
if (properties.ContainsKey(deviceTypeName) && properties[deviceTypeName].Int32Value.HasValue)
{
DeviceType = (DeviceType)properties[deviceTypeName].Int32Value.Value;
}
Type = (EventType)properties[typeName].Int32Value.Value;
}
public static List<EventTableEntity> IndexEvent(EventMessage e)
var deviceTypeName = nameof(DeviceType);
if (properties.ContainsKey(deviceTypeName) && properties[deviceTypeName].Int32Value.HasValue)
{
var uniquifier = e.IdempotencyId.GetValueOrDefault(Guid.NewGuid());
var pKey = GetPartitionKey(e);
var dateKey = CoreHelpers.DateTimeToTableStorageKey(e.Date);
var entities = new List<EventTableEntity>
{
new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"Date={dateKey}__Uniquifier={uniquifier}"
}
};
if (e.OrganizationId.HasValue && e.ActingUserId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"ActingUserId={e.ActingUserId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
if (!e.OrganizationId.HasValue && e.ProviderId.HasValue && e.ActingUserId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"ActingUserId={e.ActingUserId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
if (e.CipherId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"CipherId={e.CipherId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
return entities;
}
private static string GetPartitionKey(EventMessage e)
{
if (e.OrganizationId.HasValue)
{
return $"OrganizationId={e.OrganizationId}";
}
if (e.ProviderId.HasValue)
{
return $"ProviderId={e.ProviderId}";
}
return $"UserId={e.UserId}";
DeviceType = (DeviceType)properties[deviceTypeName].Int32Value.Value;
}
}
public static List<EventTableEntity> IndexEvent(EventMessage e)
{
var uniquifier = e.IdempotencyId.GetValueOrDefault(Guid.NewGuid());
var pKey = GetPartitionKey(e);
var dateKey = CoreHelpers.DateTimeToTableStorageKey(e.Date);
var entities = new List<EventTableEntity>
{
new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"Date={dateKey}__Uniquifier={uniquifier}"
}
};
if (e.OrganizationId.HasValue && e.ActingUserId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"ActingUserId={e.ActingUserId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
if (!e.OrganizationId.HasValue && e.ProviderId.HasValue && e.ActingUserId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"ActingUserId={e.ActingUserId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
if (e.CipherId.HasValue)
{
entities.Add(new EventTableEntity(e)
{
PartitionKey = pKey,
RowKey = $"CipherId={e.CipherId}__Date={dateKey}__Uniquifier={uniquifier}"
});
}
return entities;
}
private static string GetPartitionKey(EventMessage e)
{
if (e.OrganizationId.HasValue)
{
return $"OrganizationId={e.OrganizationId}";
}
if (e.ProviderId.HasValue)
{
return $"ProviderId={e.ProviderId}";
}
return $"UserId={e.UserId}";
}
}

View File

@ -1,10 +1,9 @@
using System.Data;
using Bit.Core.Entities;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class GroupWithCollections : Group
{
public class GroupWithCollections : Group
{
public DataTable Collections { get; set; }
}
public DataTable Collections { get; set; }
}

View File

@ -1,24 +1,23 @@
using Bit.Core.Enums;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public interface IEvent
{
public interface IEvent
{
EventType Type { get; set; }
Guid? UserId { get; set; }
Guid? OrganizationId { get; set; }
Guid? InstallationId { get; set; }
Guid? ProviderId { get; set; }
Guid? CipherId { get; set; }
Guid? CollectionId { get; set; }
Guid? GroupId { get; set; }
Guid? PolicyId { get; set; }
Guid? OrganizationUserId { get; set; }
Guid? ProviderUserId { get; set; }
Guid? ProviderOrganizationId { get; set; }
Guid? ActingUserId { get; set; }
DeviceType? DeviceType { get; set; }
string IpAddress { get; set; }
DateTime Date { get; set; }
}
EventType Type { get; set; }
Guid? UserId { get; set; }
Guid? OrganizationId { get; set; }
Guid? InstallationId { get; set; }
Guid? ProviderId { get; set; }
Guid? CipherId { get; set; }
Guid? CollectionId { get; set; }
Guid? GroupId { get; set; }
Guid? PolicyId { get; set; }
Guid? OrganizationUserId { get; set; }
Guid? ProviderUserId { get; set; }
Guid? ProviderOrganizationId { get; set; }
Guid? ActingUserId { get; set; }
DeviceType? DeviceType { get; set; }
string IpAddress { get; set; }
DateTime Date { get; set; }
}

View File

@ -1,35 +1,34 @@
using Microsoft.Azure.Cosmos.Table;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class InstallationDeviceEntity : TableEntity
{
public class InstallationDeviceEntity : TableEntity
public InstallationDeviceEntity() { }
public InstallationDeviceEntity(Guid installationId, Guid deviceId)
{
public InstallationDeviceEntity() { }
PartitionKey = installationId.ToString();
RowKey = deviceId.ToString();
}
public InstallationDeviceEntity(Guid installationId, Guid deviceId)
public InstallationDeviceEntity(string prefixedDeviceId)
{
var parts = prefixedDeviceId.Split("_");
if (parts.Length < 2)
{
PartitionKey = installationId.ToString();
RowKey = deviceId.ToString();
throw new ArgumentException("Not enough parts.");
}
if (!Guid.TryParse(parts[0], out var installationId) || !Guid.TryParse(parts[1], out var deviceId))
{
throw new ArgumentException("Could not parse parts.");
}
PartitionKey = parts[0];
RowKey = parts[1];
}
public InstallationDeviceEntity(string prefixedDeviceId)
{
var parts = prefixedDeviceId.Split("_");
if (parts.Length < 2)
{
throw new ArgumentException("Not enough parts.");
}
if (!Guid.TryParse(parts[0], out var installationId) || !Guid.TryParse(parts[1], out var deviceId))
{
throw new ArgumentException("Could not parse parts.");
}
PartitionKey = parts[0];
RowKey = parts[1];
}
public static bool IsInstallationDeviceId(string deviceId)
{
return deviceId != null && deviceId.Length == 73 && deviceId[36] == '_';
}
public static bool IsInstallationDeviceId(string deviceId)
{
return deviceId != null && deviceId.Length == 73 && deviceId[36] == '_';
}
}

View File

@ -1,35 +1,34 @@
using Bit.Core.Entities;
namespace Bit.Core.Models.Data.Organizations
namespace Bit.Core.Models.Data.Organizations;
public class OrganizationAbility
{
public class OrganizationAbility
public OrganizationAbility() { }
public OrganizationAbility(Organization organization)
{
public OrganizationAbility() { }
public OrganizationAbility(Organization organization)
{
Id = organization.Id;
UseEvents = organization.UseEvents;
Use2fa = organization.Use2fa;
Using2fa = organization.Use2fa && organization.TwoFactorProviders != null &&
organization.TwoFactorProviders != "{}";
UsersGetPremium = organization.UsersGetPremium;
Enabled = organization.Enabled;
UseSso = organization.UseSso;
UseKeyConnector = organization.UseKeyConnector;
UseScim = organization.UseScim;
UseResetPassword = organization.UseResetPassword;
}
public Guid Id { get; set; }
public bool UseEvents { get; set; }
public bool Use2fa { get; set; }
public bool Using2fa { get; set; }
public bool UsersGetPremium { get; set; }
public bool Enabled { get; set; }
public bool UseSso { get; set; }
public bool UseKeyConnector { get; set; }
public bool UseScim { get; set; }
public bool UseResetPassword { get; set; }
Id = organization.Id;
UseEvents = organization.UseEvents;
Use2fa = organization.Use2fa;
Using2fa = organization.Use2fa && organization.TwoFactorProviders != null &&
organization.TwoFactorProviders != "{}";
UsersGetPremium = organization.UsersGetPremium;
Enabled = organization.Enabled;
UseSso = organization.UseSso;
UseKeyConnector = organization.UseKeyConnector;
UseScim = organization.UseScim;
UseResetPassword = organization.UseResetPassword;
}
public Guid Id { get; set; }
public bool UseEvents { get; set; }
public bool Use2fa { get; set; }
public bool Using2fa { get; set; }
public bool UsersGetPremium { get; set; }
public bool Enabled { get; set; }
public bool UseSso { get; set; }
public bool UseKeyConnector { get; set; }
public bool UseScim { get; set; }
public bool UseResetPassword { get; set; }
}

View File

@ -1,32 +1,31 @@
using Bit.Core.Entities;
using Bit.Core.Enums;
namespace Bit.Core.Models.Data.Organizations.OrganizationConnections
namespace Bit.Core.Models.Data.Organizations.OrganizationConnections;
public class OrganizationConnectionData<T> where T : new()
{
public class OrganizationConnectionData<T> where T : new()
public Guid? Id { get; set; }
public OrganizationConnectionType Type { get; set; }
public Guid OrganizationId { get; set; }
public bool Enabled { get; set; }
public T Config { get; set; }
public OrganizationConnection ToEntity()
{
public Guid? Id { get; set; }
public OrganizationConnectionType Type { get; set; }
public Guid OrganizationId { get; set; }
public bool Enabled { get; set; }
public T Config { get; set; }
public OrganizationConnection ToEntity()
var result = new OrganizationConnection()
{
var result = new OrganizationConnection()
{
Type = Type,
OrganizationId = OrganizationId,
Enabled = Enabled,
};
result.SetConfig(Config);
Type = Type,
OrganizationId = OrganizationId,
Enabled = Enabled,
};
result.SetConfig(Config);
if (Id.HasValue)
{
result.Id = Id.Value;
}
return result;
if (Id.HasValue)
{
result.Id = Id.Value;
}
return result;
}
}

View File

@ -1,31 +1,30 @@
using Bit.Core.Entities;
using Bit.Core.Enums;
namespace Bit.Core.Models.Data.Organizations.OrganizationSponsorships
{
public class OrganizationSponsorshipData
{
public OrganizationSponsorshipData() { }
public OrganizationSponsorshipData(OrganizationSponsorship sponsorship)
{
SponsoringOrganizationUserId = sponsorship.SponsoringOrganizationUserId;
SponsoredOrganizationId = sponsorship.SponsoredOrganizationId;
FriendlyName = sponsorship.FriendlyName;
OfferedToEmail = sponsorship.OfferedToEmail;
PlanSponsorshipType = sponsorship.PlanSponsorshipType.GetValueOrDefault();
LastSyncDate = sponsorship.LastSyncDate;
ValidUntil = sponsorship.ValidUntil;
ToDelete = sponsorship.ToDelete;
}
public Guid SponsoringOrganizationUserId { get; set; }
public Guid? SponsoredOrganizationId { get; set; }
public string FriendlyName { get; set; }
public string OfferedToEmail { get; set; }
public PlanSponsorshipType PlanSponsorshipType { get; set; }
public DateTime? LastSyncDate { get; set; }
public DateTime? ValidUntil { get; set; }
public bool ToDelete { get; set; }
namespace Bit.Core.Models.Data.Organizations.OrganizationSponsorships;
public bool CloudSponsorshipRemoved { get; set; }
public class OrganizationSponsorshipData
{
public OrganizationSponsorshipData() { }
public OrganizationSponsorshipData(OrganizationSponsorship sponsorship)
{
SponsoringOrganizationUserId = sponsorship.SponsoringOrganizationUserId;
SponsoredOrganizationId = sponsorship.SponsoredOrganizationId;
FriendlyName = sponsorship.FriendlyName;
OfferedToEmail = sponsorship.OfferedToEmail;
PlanSponsorshipType = sponsorship.PlanSponsorshipType.GetValueOrDefault();
LastSyncDate = sponsorship.LastSyncDate;
ValidUntil = sponsorship.ValidUntil;
ToDelete = sponsorship.ToDelete;
}
public Guid SponsoringOrganizationUserId { get; set; }
public Guid? SponsoredOrganizationId { get; set; }
public string FriendlyName { get; set; }
public string OfferedToEmail { get; set; }
public PlanSponsorshipType PlanSponsorshipType { get; set; }
public DateTime? LastSyncDate { get; set; }
public DateTime? ValidUntil { get; set; }
public bool ToDelete { get; set; }
public bool CloudSponsorshipRemoved { get; set; }
}

View File

@ -1,9 +1,8 @@
namespace Bit.Core.Models.Data.Organizations.OrganizationSponsorships
namespace Bit.Core.Models.Data.Organizations.OrganizationSponsorships;
public class OrganizationSponsorshipSyncData
{
public class OrganizationSponsorshipSyncData
{
public string BillingSyncKey { get; set; }
public Guid SponsoringOrganizationCloudId { get; set; }
public IEnumerable<OrganizationSponsorshipData> SponsorshipsBatch { get; set; }
}
public string BillingSyncKey { get; set; }
public Guid SponsoringOrganizationCloudId { get; set; }
public IEnumerable<OrganizationSponsorshipData> SponsorshipsBatch { get; set; }
}

View File

@ -1,13 +1,12 @@
using Bit.Core.Enums;
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers;
public class OrganizationUserInviteData
{
public class OrganizationUserInviteData
{
public IEnumerable<string> Emails { get; set; }
public OrganizationUserType? Type { get; set; }
public bool AccessAll { get; set; }
public IEnumerable<SelectionReadOnly> Collections { get; set; }
public Permissions Permissions { get; set; }
}
public IEnumerable<string> Emails { get; set; }
public OrganizationUserType? Type { get; set; }
public bool AccessAll { get; set; }
public IEnumerable<SelectionReadOnly> Collections { get; set; }
public Permissions Permissions { get; set; }
}

View File

@ -1,43 +1,42 @@
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers;
public class OrganizationUserOrganizationDetails
{
public class OrganizationUserOrganizationDetails
{
public Guid OrganizationId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public bool UsePolicies { get; set; }
public bool UseSso { get; set; }
public bool UseKeyConnector { get; set; }
public bool UseScim { get; set; }
public bool UseGroups { get; set; }
public bool UseDirectory { get; set; }
public bool UseEvents { get; set; }
public bool UseTotp { get; set; }
public bool Use2fa { get; set; }
public bool UseApi { get; set; }
public bool UseResetPassword { get; set; }
public bool SelfHost { get; set; }
public bool UsersGetPremium { get; set; }
public int? Seats { get; set; }
public short? MaxCollections { get; set; }
public short? MaxStorageGb { get; set; }
public string Key { get; set; }
public Enums.OrganizationUserStatusType Status { get; set; }
public Enums.OrganizationUserType Type { get; set; }
public bool Enabled { get; set; }
public Enums.PlanType PlanType { get; set; }
public string SsoExternalId { get; set; }
public string Identifier { get; set; }
public string Permissions { get; set; }
public string ResetPasswordKey { get; set; }
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
public Guid? ProviderId { get; set; }
public string ProviderName { get; set; }
public string FamilySponsorshipFriendlyName { get; set; }
public string SsoConfig { get; set; }
public DateTime? FamilySponsorshipLastSyncDate { get; set; }
public DateTime? FamilySponsorshipValidUntil { get; set; }
public bool? FamilySponsorshipToDelete { get; set; }
}
public Guid OrganizationId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public bool UsePolicies { get; set; }
public bool UseSso { get; set; }
public bool UseKeyConnector { get; set; }
public bool UseScim { get; set; }
public bool UseGroups { get; set; }
public bool UseDirectory { get; set; }
public bool UseEvents { get; set; }
public bool UseTotp { get; set; }
public bool Use2fa { get; set; }
public bool UseApi { get; set; }
public bool UseResetPassword { get; set; }
public bool SelfHost { get; set; }
public bool UsersGetPremium { get; set; }
public int? Seats { get; set; }
public short? MaxCollections { get; set; }
public short? MaxStorageGb { get; set; }
public string Key { get; set; }
public Enums.OrganizationUserStatusType Status { get; set; }
public Enums.OrganizationUserType Type { get; set; }
public bool Enabled { get; set; }
public Enums.PlanType PlanType { get; set; }
public string SsoExternalId { get; set; }
public string Identifier { get; set; }
public string Permissions { get; set; }
public string ResetPasswordKey { get; set; }
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
public Guid? ProviderId { get; set; }
public string ProviderName { get; set; }
public string FamilySponsorshipFriendlyName { get; set; }
public string SsoConfig { get; set; }
public DateTime? FamilySponsorshipLastSyncDate { get; set; }
public DateTime? FamilySponsorshipValidUntil { get; set; }
public bool? FamilySponsorshipToDelete { get; set; }
}

View File

@ -1,9 +1,8 @@
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers;
public class OrganizationUserPublicKey
{
public class OrganizationUserPublicKey
{
public Guid Id { get; set; }
public Guid UserId { get; set; }
public string PublicKey { get; set; }
}
public Guid Id { get; set; }
public Guid UserId { get; set; }
public string PublicKey { get; set; }
}

View File

@ -1,35 +1,34 @@
using Bit.Core.Entities;
using Bit.Core.Enums;
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers;
public class OrganizationUserResetPasswordDetails
{
public class OrganizationUserResetPasswordDetails
public OrganizationUserResetPasswordDetails(OrganizationUser orgUser, User user, Organization org)
{
public OrganizationUserResetPasswordDetails(OrganizationUser orgUser, User user, Organization org)
if (orgUser == null)
{
if (orgUser == null)
{
throw new ArgumentNullException(nameof(orgUser));
}
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
if (org == null)
{
throw new ArgumentNullException(nameof(org));
}
Kdf = user.Kdf;
KdfIterations = user.KdfIterations;
ResetPasswordKey = orgUser.ResetPasswordKey;
EncryptedPrivateKey = org.PrivateKey;
throw new ArgumentNullException(nameof(orgUser));
}
public KdfType Kdf { get; set; }
public int KdfIterations { get; set; }
public string ResetPasswordKey { get; set; }
public string EncryptedPrivateKey { get; set; }
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
if (org == null)
{
throw new ArgumentNullException(nameof(org));
}
Kdf = user.Kdf;
KdfIterations = user.KdfIterations;
ResetPasswordKey = orgUser.ResetPasswordKey;
EncryptedPrivateKey = org.PrivateKey;
}
public KdfType Kdf { get; set; }
public int KdfIterations { get; set; }
public string ResetPasswordKey { get; set; }
public string EncryptedPrivateKey { get; set; }
}

View File

@ -1,60 +1,59 @@
using Bit.Core.Enums;
using Bit.Core.Utilities;
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers;
public class OrganizationUserUserDetails : IExternal, ITwoFactorProvidersUser
{
public class OrganizationUserUserDetails : IExternal, ITwoFactorProvidersUser
private Dictionary<TwoFactorProviderType, TwoFactorProvider> _twoFactorProviders;
public Guid Id { get; set; }
public Guid OrganizationId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string TwoFactorProviders { get; set; }
public bool? Premium { get; set; }
public OrganizationUserStatusType Status { get; set; }
public OrganizationUserType Type { get; set; }
public bool AccessAll { get; set; }
public string ExternalId { get; set; }
public string SsoExternalId { get; set; }
public string Permissions { get; set; }
public string ResetPasswordKey { get; set; }
public bool UsesKeyConnector { get; set; }
public Dictionary<TwoFactorProviderType, TwoFactorProvider> GetTwoFactorProviders()
{
private Dictionary<TwoFactorProviderType, TwoFactorProvider> _twoFactorProviders;
public Guid Id { get; set; }
public Guid OrganizationId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string TwoFactorProviders { get; set; }
public bool? Premium { get; set; }
public OrganizationUserStatusType Status { get; set; }
public OrganizationUserType Type { get; set; }
public bool AccessAll { get; set; }
public string ExternalId { get; set; }
public string SsoExternalId { get; set; }
public string Permissions { get; set; }
public string ResetPasswordKey { get; set; }
public bool UsesKeyConnector { get; set; }
public Dictionary<TwoFactorProviderType, TwoFactorProvider> GetTwoFactorProviders()
if (string.IsNullOrWhiteSpace(TwoFactorProviders))
{
if (string.IsNullOrWhiteSpace(TwoFactorProviders))
{
return null;
}
try
{
if (_twoFactorProviders == null)
{
_twoFactorProviders =
JsonHelpers.LegacyDeserialize<Dictionary<TwoFactorProviderType, TwoFactorProvider>>(
TwoFactorProviders);
}
return _twoFactorProviders;
}
catch (Newtonsoft.Json.JsonException)
{
return null;
}
return null;
}
public Guid? GetUserId()
try
{
return UserId;
}
if (_twoFactorProviders == null)
{
_twoFactorProviders =
JsonHelpers.LegacyDeserialize<Dictionary<TwoFactorProviderType, TwoFactorProvider>>(
TwoFactorProviders);
}
public bool GetPremium()
return _twoFactorProviders;
}
catch (Newtonsoft.Json.JsonException)
{
return Premium.GetValueOrDefault(false);
return null;
}
}
public Guid? GetUserId()
{
return UserId;
}
public bool GetPremium()
{
return Premium.GetValueOrDefault(false);
}
}

View File

@ -1,10 +1,9 @@
using System.Data;
using Bit.Core.Entities;
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers
namespace Bit.Core.Models.Data.Organizations.OrganizationUsers;
public class OrganizationUserWithCollections : OrganizationUser
{
public class OrganizationUserWithCollections : OrganizationUser
{
public DataTable Collections { get; set; }
}
public DataTable Collections { get; set; }
}

View File

@ -1,6 +1,5 @@
namespace Bit.Core.Models.Data.Organizations.Policies
namespace Bit.Core.Models.Data.Organizations.Policies;
public interface IPolicyDataModel
{
public interface IPolicyDataModel
{
}
}

View File

@ -1,10 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Core.Models.Data.Organizations.Policies
namespace Bit.Core.Models.Data.Organizations.Policies;
public class ResetPasswordDataModel : IPolicyDataModel
{
public class ResetPasswordDataModel : IPolicyDataModel
{
[Display(Name = "ResetPasswordAutoEnrollCheckbox")]
public bool AutoEnrollEnabled { get; set; }
}
[Display(Name = "ResetPasswordAutoEnrollCheckbox")]
public bool AutoEnrollEnabled { get; set; }
}

View File

@ -1,10 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Core.Models.Data.Organizations.Policies
namespace Bit.Core.Models.Data.Organizations.Policies;
public class SendOptionsPolicyData : IPolicyDataModel
{
public class SendOptionsPolicyData : IPolicyDataModel
{
[Display(Name = "DisableHideEmail")]
public bool DisableHideEmail { get; set; }
}
[Display(Name = "DisableHideEmail")]
public bool DisableHideEmail { get; set; }
}

View File

@ -1,8 +1,7 @@
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class PageOptions
{
public class PageOptions
{
public string ContinuationToken { get; set; }
public int PageSize { get; set; } = 50;
}
public string ContinuationToken { get; set; }
public int PageSize { get; set; } = 50;
}

View File

@ -1,8 +1,7 @@
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class PagedResult<T>
{
public class PagedResult<T>
{
public List<T> Data { get; set; } = new List<T>();
public string ContinuationToken { get; set; }
}
public List<T> Data { get; set; } = new List<T>();
public string ContinuationToken { get; set; }
}

View File

@ -1,45 +1,44 @@
using System.Text.Json.Serialization;
namespace Bit.Core.Models.Data
{
public class Permissions
{
public bool AccessEventLogs { get; set; }
public bool AccessImportExport { get; set; }
public bool AccessReports { get; set; }
[Obsolete("This permission exists for client backwards-compatibility. It should not be used to determine permissions in this repository", true)]
public bool ManageAllCollections => CreateNewCollections && EditAnyCollection && DeleteAnyCollection;
public bool CreateNewCollections { get; set; }
public bool EditAnyCollection { get; set; }
public bool DeleteAnyCollection { get; set; }
[Obsolete("This permission exists for client backwards-compatibility. It should not be used to determine permissions in this repository", true)]
public bool ManageAssignedCollections => EditAssignedCollections && DeleteAssignedCollections;
public bool EditAssignedCollections { get; set; }
public bool DeleteAssignedCollections { get; set; }
public bool ManageGroups { get; set; }
public bool ManagePolicies { get; set; }
public bool ManageSso { get; set; }
public bool ManageUsers { get; set; }
public bool ManageResetPassword { get; set; }
public bool ManageScim { get; set; }
namespace Bit.Core.Models.Data;
[JsonIgnore]
public List<(bool Permission, string ClaimName)> ClaimsMap => new()
{
(AccessEventLogs, "accesseventlogs"),
(AccessImportExport, "accessimportexport"),
(AccessReports, "accessreports"),
(CreateNewCollections, "createnewcollections"),
(EditAnyCollection, "editanycollection"),
(DeleteAnyCollection, "deleteanycollection"),
(EditAssignedCollections, "editassignedcollections"),
(DeleteAssignedCollections, "deleteassignedcollections"),
(ManageGroups, "managegroups"),
(ManagePolicies, "managepolicies"),
(ManageSso, "managesso"),
(ManageUsers, "manageusers"),
(ManageResetPassword, "manageresetpassword"),
(ManageScim, "managescim"),
};
}
public class Permissions
{
public bool AccessEventLogs { get; set; }
public bool AccessImportExport { get; set; }
public bool AccessReports { get; set; }
[Obsolete("This permission exists for client backwards-compatibility. It should not be used to determine permissions in this repository", true)]
public bool ManageAllCollections => CreateNewCollections && EditAnyCollection && DeleteAnyCollection;
public bool CreateNewCollections { get; set; }
public bool EditAnyCollection { get; set; }
public bool DeleteAnyCollection { get; set; }
[Obsolete("This permission exists for client backwards-compatibility. It should not be used to determine permissions in this repository", true)]
public bool ManageAssignedCollections => EditAssignedCollections && DeleteAssignedCollections;
public bool EditAssignedCollections { get; set; }
public bool DeleteAssignedCollections { get; set; }
public bool ManageGroups { get; set; }
public bool ManagePolicies { get; set; }
public bool ManageSso { get; set; }
public bool ManageUsers { get; set; }
public bool ManageResetPassword { get; set; }
public bool ManageScim { get; set; }
[JsonIgnore]
public List<(bool Permission, string ClaimName)> ClaimsMap => new()
{
(AccessEventLogs, "accesseventlogs"),
(AccessImportExport, "accessimportexport"),
(AccessReports, "accessreports"),
(CreateNewCollections, "createnewcollections"),
(EditAnyCollection, "editanycollection"),
(DeleteAnyCollection, "deleteanycollection"),
(EditAssignedCollections, "editassignedcollections"),
(DeleteAssignedCollections, "deleteassignedcollections"),
(ManageGroups, "managegroups"),
(ManagePolicies, "managepolicies"),
(ManageSso, "managesso"),
(ManageUsers, "manageusers"),
(ManageResetPassword, "manageresetpassword"),
(ManageScim, "managescim"),
};
}

View File

@ -1,20 +1,19 @@
using Bit.Core.Entities.Provider;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class ProviderAbility
{
public class ProviderAbility
public ProviderAbility() { }
public ProviderAbility(Provider provider)
{
public ProviderAbility() { }
public ProviderAbility(Provider provider)
{
Id = provider.Id;
UseEvents = provider.UseEvents;
Enabled = provider.Enabled;
}
public Guid Id { get; set; }
public bool UseEvents { get; set; }
public bool Enabled { get; set; }
Id = provider.Id;
UseEvents = provider.UseEvents;
Enabled = provider.Enabled;
}
public Guid Id { get; set; }
public bool UseEvents { get; set; }
public bool Enabled { get; set; }
}

View File

@ -1,17 +1,16 @@
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class ProviderOrganizationOrganizationDetails
{
public class ProviderOrganizationOrganizationDetails
{
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid OrganizationId { get; set; }
public string OrganizationName { get; set; }
public string Key { get; set; }
public string Settings { get; set; }
public DateTime CreationDate { get; set; }
public DateTime RevisionDate { get; set; }
public int UserCount { get; set; }
public int? Seats { get; set; }
public string Plan { get; set; }
}
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid OrganizationId { get; set; }
public string OrganizationName { get; set; }
public string Key { get; set; }
public string Settings { get; set; }
public DateTime CreationDate { get; set; }
public DateTime RevisionDate { get; set; }
public int UserCount { get; set; }
public int? Seats { get; set; }
public string Plan { get; set; }
}

View File

@ -1,37 +1,36 @@
using Bit.Core.Enums.Provider;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class ProviderUserOrganizationDetails
{
public class ProviderUserOrganizationDetails
{
public Guid OrganizationId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public bool UsePolicies { get; set; }
public bool UseSso { get; set; }
public bool UseKeyConnector { get; set; }
public bool UseScim { get; set; }
public bool UseGroups { get; set; }
public bool UseDirectory { get; set; }
public bool UseEvents { get; set; }
public bool UseTotp { get; set; }
public bool Use2fa { get; set; }
public bool UseApi { get; set; }
public bool UseResetPassword { get; set; }
public bool SelfHost { get; set; }
public bool UsersGetPremium { get; set; }
public int? Seats { get; set; }
public short? MaxCollections { get; set; }
public short? MaxStorageGb { get; set; }
public string Key { get; set; }
public ProviderUserStatusType Status { get; set; }
public ProviderUserType Type { get; set; }
public bool Enabled { get; set; }
public string Identifier { get; set; }
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
public Guid? ProviderId { get; set; }
public Guid? ProviderUserId { get; set; }
public string ProviderName { get; set; }
}
public Guid OrganizationId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public bool UsePolicies { get; set; }
public bool UseSso { get; set; }
public bool UseKeyConnector { get; set; }
public bool UseScim { get; set; }
public bool UseGroups { get; set; }
public bool UseDirectory { get; set; }
public bool UseEvents { get; set; }
public bool UseTotp { get; set; }
public bool Use2fa { get; set; }
public bool UseApi { get; set; }
public bool UseResetPassword { get; set; }
public bool SelfHost { get; set; }
public bool UsersGetPremium { get; set; }
public int? Seats { get; set; }
public short? MaxCollections { get; set; }
public short? MaxStorageGb { get; set; }
public string Key { get; set; }
public ProviderUserStatusType Status { get; set; }
public ProviderUserType Type { get; set; }
public bool Enabled { get; set; }
public string Identifier { get; set; }
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
public Guid? ProviderId { get; set; }
public Guid? ProviderUserId { get; set; }
public string ProviderName { get; set; }
}

View File

@ -1,18 +1,17 @@
using Bit.Core.Enums.Provider;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class ProviderUserProviderDetails
{
public class ProviderUserProviderDetails
{
public Guid ProviderId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public string Key { get; set; }
public ProviderUserStatusType Status { get; set; }
public ProviderUserType Type { get; set; }
public bool Enabled { get; set; }
public string Permissions { get; set; }
public bool UseEvents { get; set; }
public ProviderStatusType ProviderStatus { get; set; }
}
public Guid ProviderId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public string Key { get; set; }
public ProviderUserStatusType Status { get; set; }
public ProviderUserType Type { get; set; }
public bool Enabled { get; set; }
public string Permissions { get; set; }
public bool UseEvents { get; set; }
public ProviderStatusType ProviderStatus { get; set; }
}

View File

@ -1,9 +1,8 @@
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class ProviderUserPublicKey
{
public class ProviderUserPublicKey
{
public Guid Id { get; set; }
public Guid UserId { get; set; }
public string PublicKey { get; set; }
}
public Guid Id { get; set; }
public Guid UserId { get; set; }
public string PublicKey { get; set; }
}

View File

@ -1,16 +1,15 @@
using Bit.Core.Enums.Provider;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class ProviderUserUserDetails
{
public class ProviderUserUserDetails
{
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public ProviderUserStatusType Status { get; set; }
public ProviderUserType Type { get; set; }
public string Permissions { get; set; }
}
public Guid Id { get; set; }
public Guid ProviderId { get; set; }
public Guid? UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public ProviderUserStatusType Status { get; set; }
public ProviderUserType Type { get; set; }
public string Permissions { get; set; }
}

View File

@ -1,9 +1,8 @@
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class SelectionReadOnly
{
public class SelectionReadOnly
{
public Guid Id { get; set; }
public bool ReadOnly { get; set; }
public bool HidePasswords { get; set; }
}
public Guid Id { get; set; }
public bool ReadOnly { get; set; }
public bool HidePasswords { get; set; }
}

View File

@ -1,16 +1,15 @@
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public abstract class SendData
{
public abstract class SendData
public SendData() { }
public SendData(string name, string notes)
{
public SendData() { }
public SendData(string name, string notes)
{
Name = name;
Notes = notes;
}
public string Name { get; set; }
public string Notes { get; set; }
Name = name;
Notes = notes;
}
public string Name { get; set; }
public string Notes { get; set; }
}

View File

@ -1,23 +1,22 @@
using System.Text.Json.Serialization;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class SendFileData : SendData
{
public class SendFileData : SendData
public SendFileData() { }
public SendFileData(string name, string notes, string fileName)
: base(name, notes)
{
public SendFileData() { }
public SendFileData(string name, string notes, string fileName)
: base(name, notes)
{
FileName = fileName;
}
// We serialize Size as a string since JSON (or Javascript) doesn't support full precision for long numbers
[JsonNumberHandling(JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowReadingFromString)]
public long Size { get; set; }
public string Id { get; set; }
public string FileName { get; set; }
public bool Validated { get; set; } = true;
FileName = fileName;
}
// We serialize Size as a string since JSON (or Javascript) doesn't support full precision for long numbers
[JsonNumberHandling(JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowReadingFromString)]
public long Size { get; set; }
public string Id { get; set; }
public string FileName { get; set; }
public bool Validated { get; set; } = true;
}

View File

@ -1,17 +1,16 @@
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class SendTextData : SendData
{
public class SendTextData : SendData
public SendTextData() { }
public SendTextData(string name, string notes, string text, bool hidden)
: base(name, notes)
{
public SendTextData() { }
public SendTextData(string name, string notes, string text, bool hidden)
: base(name, notes)
{
Text = text;
Hidden = hidden;
}
public string Text { get; set; }
public bool Hidden { get; set; }
Text = text;
Hidden = hidden;
}
public string Text { get; set; }
public bool Hidden { get; set; }
}

View File

@ -2,125 +2,124 @@
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class SsoConfigurationData
{
public class SsoConfigurationData
private static string _oidcSigninPath = "/oidc-signin";
private static string _oidcSignedOutPath = "/oidc-signedout";
private static string _saml2ModulePath = "/saml2";
public static SsoConfigurationData Deserialize(string data)
{
private static string _oidcSigninPath = "/oidc-signin";
private static string _oidcSignedOutPath = "/oidc-signedout";
private static string _saml2ModulePath = "/saml2";
return CoreHelpers.LoadClassFromJsonData<SsoConfigurationData>(data);
}
public static SsoConfigurationData Deserialize(string data)
public string Serialize()
{
return CoreHelpers.ClassToJsonData(this);
}
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 IDP
public string IdpEntityId { get; set; }
public string IdpSingleSignOnServiceUrl { get; set; }
public string IdpSingleLogoutServiceUrl { get; set; }
public string IdpX509PublicCert { get; set; }
public Saml2BindingType IdpBindingType { get; set; }
public bool IdpAllowUnsolicitedAuthnResponse { get; set; }
public string IdpArtifactResolutionServiceUrl { get => null; set { /*IGNORE*/ } }
public bool IdpDisableOutboundLogoutRequests { get; set; }
public string IdpOutboundSigningAlgorithm { get; set; }
public bool IdpWantAuthnRequestsSigned { 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; }
public static string BuildCallbackPath(string ssoUri = null)
{
return BuildSsoUrl(_oidcSigninPath, ssoUri);
}
public static string BuildSignedOutCallbackPath(string ssoUri = null)
{
return BuildSsoUrl(_oidcSignedOutPath, ssoUri);
}
public static string BuildSaml2ModulePath(string ssoUri = null, string scheme = null)
{
return string.Concat(BuildSsoUrl(_saml2ModulePath, ssoUri),
string.IsNullOrWhiteSpace(scheme) ? string.Empty : $"/{scheme}");
}
public static string BuildSaml2AcsUrl(string ssoUri = null, string scheme = null)
{
return string.Concat(BuildSaml2ModulePath(ssoUri, scheme), "/Acs");
}
public static string BuildSaml2MetadataUrl(string ssoUri = null, string scheme = null)
{
return BuildSaml2ModulePath(ssoUri, scheme);
}
public IEnumerable<string> GetAdditionalScopes() => AdditionalScopes?
.Split(',')?
.Where(c => !string.IsNullOrWhiteSpace(c))?
.Select(c => c.Trim()) ??
Array.Empty<string>();
public IEnumerable<string> GetAdditionalUserIdClaimTypes() => AdditionalUserIdClaimTypes?
.Split(',')?
.Where(c => !string.IsNullOrWhiteSpace(c))?
.Select(c => c.Trim()) ??
Array.Empty<string>();
public IEnumerable<string> GetAdditionalEmailClaimTypes() => AdditionalEmailClaimTypes?
.Split(',')?
.Where(c => !string.IsNullOrWhiteSpace(c))?
.Select(c => c.Trim()) ??
Array.Empty<string>();
public IEnumerable<string> GetAdditionalNameClaimTypes() => AdditionalNameClaimTypes?
.Split(',')?
.Where(c => !string.IsNullOrWhiteSpace(c))?
.Select(c => c.Trim()) ??
Array.Empty<string>();
private static string BuildSsoUrl(string relativePath, string ssoUri)
{
if (string.IsNullOrWhiteSpace(ssoUri) ||
!Uri.IsWellFormedUriString(ssoUri, UriKind.Absolute))
{
return CoreHelpers.LoadClassFromJsonData<SsoConfigurationData>(data);
}
public string Serialize()
{
return CoreHelpers.ClassToJsonData(this);
}
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 IDP
public string IdpEntityId { get; set; }
public string IdpSingleSignOnServiceUrl { get; set; }
public string IdpSingleLogoutServiceUrl { get; set; }
public string IdpX509PublicCert { get; set; }
public Saml2BindingType IdpBindingType { get; set; }
public bool IdpAllowUnsolicitedAuthnResponse { get; set; }
public string IdpArtifactResolutionServiceUrl { get => null; set { /*IGNORE*/ } }
public bool IdpDisableOutboundLogoutRequests { get; set; }
public string IdpOutboundSigningAlgorithm { get; set; }
public bool IdpWantAuthnRequestsSigned { 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; }
public static string BuildCallbackPath(string ssoUri = null)
{
return BuildSsoUrl(_oidcSigninPath, ssoUri);
}
public static string BuildSignedOutCallbackPath(string ssoUri = null)
{
return BuildSsoUrl(_oidcSignedOutPath, ssoUri);
}
public static string BuildSaml2ModulePath(string ssoUri = null, string scheme = null)
{
return string.Concat(BuildSsoUrl(_saml2ModulePath, ssoUri),
string.IsNullOrWhiteSpace(scheme) ? string.Empty : $"/{scheme}");
}
public static string BuildSaml2AcsUrl(string ssoUri = null, string scheme = null)
{
return string.Concat(BuildSaml2ModulePath(ssoUri, scheme), "/Acs");
}
public static string BuildSaml2MetadataUrl(string ssoUri = null, string scheme = null)
{
return BuildSaml2ModulePath(ssoUri, scheme);
}
public IEnumerable<string> GetAdditionalScopes() => AdditionalScopes?
.Split(',')?
.Where(c => !string.IsNullOrWhiteSpace(c))?
.Select(c => c.Trim()) ??
Array.Empty<string>();
public IEnumerable<string> GetAdditionalUserIdClaimTypes() => AdditionalUserIdClaimTypes?
.Split(',')?
.Where(c => !string.IsNullOrWhiteSpace(c))?
.Select(c => c.Trim()) ??
Array.Empty<string>();
public IEnumerable<string> GetAdditionalEmailClaimTypes() => AdditionalEmailClaimTypes?
.Split(',')?
.Where(c => !string.IsNullOrWhiteSpace(c))?
.Select(c => c.Trim()) ??
Array.Empty<string>();
public IEnumerable<string> GetAdditionalNameClaimTypes() => AdditionalNameClaimTypes?
.Split(',')?
.Where(c => !string.IsNullOrWhiteSpace(c))?
.Select(c => c.Trim()) ??
Array.Empty<string>();
private static string BuildSsoUrl(string relativePath, string ssoUri)
{
if (string.IsNullOrWhiteSpace(ssoUri) ||
!Uri.IsWellFormedUriString(ssoUri, UriKind.Absolute))
{
return relativePath;
}
if (Uri.TryCreate(string.Concat(ssoUri.TrimEnd('/'), relativePath), UriKind.Absolute, out var newUri))
{
return newUri.ToString();
}
return relativePath;
}
if (Uri.TryCreate(string.Concat(ssoUri.TrimEnd('/'), relativePath), UriKind.Absolute, out var newUri))
{
return newUri.ToString();
}
return relativePath;
}
}

View File

@ -1,10 +1,9 @@
using Bit.Core.Enums;
namespace Bit.Core.Models.Data
namespace Bit.Core.Models.Data;
public class UserKdfInformation
{
public class UserKdfInformation
{
public KdfType Kdf { get; set; }
public int KdfIterations { get; set; }
}
public KdfType Kdf { get; set; }
public int KdfIterations { get; set; }
}

View File

@ -1,7 +1,6 @@
namespace Bit.Core.Models
namespace Bit.Core.Models;
public interface IExternal
{
public interface IExternal
{
string ExternalId { get; }
}
string ExternalId { get; }
}

View File

@ -1,12 +1,11 @@
using Bit.Core.Enums;
namespace Bit.Core.Models
namespace Bit.Core.Models;
public interface ITwoFactorProvidersUser
{
public interface ITwoFactorProvidersUser
{
string TwoFactorProviders { get; }
Dictionary<TwoFactorProviderType, TwoFactorProvider> GetTwoFactorProviders();
Guid? GetUserId();
bool GetPremium();
}
string TwoFactorProviders { get; }
Dictionary<TwoFactorProviderType, TwoFactorProvider> GetTwoFactorProviders();
Guid? GetUserId();
bool GetPremium();
}

View File

@ -1,7 +1,6 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class AddedCreditViewModel : BaseMailModel
{
public class AddedCreditViewModel : BaseMailModel
{
public decimal Amount { get; set; }
}
public decimal Amount { get; set; }
}

View File

@ -1,8 +1,7 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class AdminResetPasswordViewModel : BaseMailModel
{
public class AdminResetPasswordViewModel : BaseMailModel
{
public string UserName { get; set; }
public string OrgName { get; set; }
}
public string UserName { get; set; }
public string OrgName { get; set; }
}

View File

@ -1,27 +1,26 @@
namespace Bit.Core.Models.Mail
{
public class BaseMailModel
{
public string SiteName { get; set; }
public string WebVaultUrl { get; set; }
public string WebVaultUrlHostname
{
get
{
if (Uri.TryCreate(WebVaultUrl, UriKind.Absolute, out Uri uri))
{
return uri.Host;
}
namespace Bit.Core.Models.Mail;
return WebVaultUrl;
}
}
public string CurrentYear
public class BaseMailModel
{
public string SiteName { get; set; }
public string WebVaultUrl { get; set; }
public string WebVaultUrlHostname
{
get
{
get
if (Uri.TryCreate(WebVaultUrl, UriKind.Absolute, out Uri uri))
{
return DateTime.UtcNow.Year.ToString();
return uri.Host;
}
return WebVaultUrl;
}
}
public string CurrentYear
{
get
{
return DateTime.UtcNow.Year.ToString();
}
}
}

View File

@ -1,8 +1,7 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class ChangeEmailExistsViewModel : BaseMailModel
{
public class ChangeEmailExistsViewModel : BaseMailModel
{
public string FromEmail { get; set; }
public string ToEmail { get; set; }
}
public string FromEmail { get; set; }
public string ToEmail { get; set; }
}

View File

@ -1,7 +1,6 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class EmailTokenViewModel : BaseMailModel
{
public class EmailTokenViewModel : BaseMailModel
{
public string Token { get; set; }
}
public string Token { get; set; }
}

View File

@ -1,7 +1,6 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class EmergencyAccessAcceptedViewModel : BaseMailModel
{
public class EmergencyAccessAcceptedViewModel : BaseMailModel
{
public string GranteeEmail { get; set; }
}
public string GranteeEmail { get; set; }
}

View File

@ -1,7 +1,6 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class EmergencyAccessApprovedViewModel : BaseMailModel
{
public class EmergencyAccessApprovedViewModel : BaseMailModel
{
public string Name { get; set; }
}
public string Name { get; set; }
}

View File

@ -1,7 +1,6 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class EmergencyAccessConfirmedViewModel : BaseMailModel
{
public class EmergencyAccessConfirmedViewModel : BaseMailModel
{
public string Name { get; set; }
}
public string Name { get; set; }
}

View File

@ -1,11 +1,10 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class EmergencyAccessInvitedViewModel : BaseMailModel
{
public class EmergencyAccessInvitedViewModel : BaseMailModel
{
public string Name { get; set; }
public string Id { get; set; }
public string Email { get; set; }
public string Token { get; set; }
public string Url => $"{WebVaultUrl}/accept-emergency?id={Id}&name={Name}&email={Email}&token={Token}";
}
public string Name { get; set; }
public string Id { get; set; }
public string Email { get; set; }
public string Token { get; set; }
public string Url => $"{WebVaultUrl}/accept-emergency?id={Id}&name={Name}&email={Email}&token={Token}";
}

View File

@ -1,8 +1,7 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class EmergencyAccessRecoveryTimedOutViewModel : BaseMailModel
{
public class EmergencyAccessRecoveryTimedOutViewModel : BaseMailModel
{
public string Name { get; set; }
public string Action { get; set; }
}
public string Name { get; set; }
public string Action { get; set; }
}

View File

@ -1,9 +1,8 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class EmergencyAccessRecoveryViewModel : BaseMailModel
{
public class EmergencyAccessRecoveryViewModel : BaseMailModel
{
public string Name { get; set; }
public string Action { get; set; }
public int DaysLeft { get; set; }
}
public string Name { get; set; }
public string Action { get; set; }
public int DaysLeft { get; set; }
}

View File

@ -1,7 +1,6 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class EmergencyAccessRejectedViewModel : BaseMailModel
{
public class EmergencyAccessRejectedViewModel : BaseMailModel
{
public string Name { get; set; }
}
public string Name { get; set; }
}

View File

@ -1,7 +1,6 @@
namespace Bit.Core.Models.Mail
namespace Bit.Core.Models.Mail;
public class FailedAuthAttemptsModel : NewDeviceLoggedInModel
{
public class FailedAuthAttemptsModel : NewDeviceLoggedInModel
{
public string AffectedEmail { get; set; }
}
public string AffectedEmail { get; set; }
}

Some files were not shown because too many files have changed in this diff Show More