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,21 +1,20 @@
using Bit.Core.Models.Data;
using Bit.Core.Utilities;
namespace Bit.Api.Models
namespace Bit.Api.Models;
public class CipherAttachmentModel
{
public class CipherAttachmentModel
public CipherAttachmentModel() { }
public CipherAttachmentModel(CipherAttachment.MetaData data)
{
public CipherAttachmentModel() { }
public CipherAttachmentModel(CipherAttachment.MetaData data)
{
FileName = data.FileName;
Key = data.Key;
}
[EncryptedStringLength(1000)]
public string FileName { get; set; }
[EncryptedStringLength(1000)]
public string Key { get; set; }
FileName = data.FileName;
Key = data.Key;
}
[EncryptedStringLength(1000)]
public string FileName { get; set; }
[EncryptedStringLength(1000)]
public string Key { get; set; }
}

View File

@ -2,39 +2,38 @@
using Bit.Core.Models.Data;
using Bit.Core.Utilities;
namespace Bit.Api.Models
namespace Bit.Api.Models;
public class CipherCardModel
{
public class CipherCardModel
public CipherCardModel() { }
public CipherCardModel(CipherCardData data)
{
public CipherCardModel() { }
public CipherCardModel(CipherCardData data)
{
CardholderName = data.CardholderName;
Brand = data.Brand;
Number = data.Number;
ExpMonth = data.ExpMonth;
ExpYear = data.ExpYear;
Code = data.Code;
}
[EncryptedString]
[EncryptedStringLength(1000)]
public string CardholderName { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Brand { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Number { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string ExpMonth { get; set; }
[EncryptedString]
[StringLength(1000)]
public string ExpYear { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Code { get; set; }
CardholderName = data.CardholderName;
Brand = data.Brand;
Number = data.Number;
ExpMonth = data.ExpMonth;
ExpYear = data.ExpYear;
Code = data.Code;
}
[EncryptedString]
[EncryptedStringLength(1000)]
public string CardholderName { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Brand { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Number { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string ExpMonth { get; set; }
[EncryptedString]
[StringLength(1000)]
public string ExpYear { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Code { get; set; }
}

View File

@ -2,36 +2,35 @@
using Bit.Core.Models.Data;
using Bit.Core.Utilities;
namespace Bit.Api.Models
namespace Bit.Api.Models;
public class CipherFieldModel
{
public class CipherFieldModel
public CipherFieldModel() { }
public CipherFieldModel(CipherFieldData data)
{
public CipherFieldModel() { }
Type = data.Type;
Name = data.Name;
Value = data.Value;
LinkedId = data.LinkedId ?? null;
}
public CipherFieldModel(CipherFieldData data)
public FieldType Type { get; set; }
[EncryptedStringLength(1000)]
public string Name { get; set; }
[EncryptedStringLength(5000)]
public string Value { get; set; }
public int? LinkedId { get; set; }
public CipherFieldData ToCipherFieldData()
{
return new CipherFieldData
{
Type = data.Type;
Name = data.Name;
Value = data.Value;
LinkedId = data.LinkedId ?? null;
}
public FieldType Type { get; set; }
[EncryptedStringLength(1000)]
public string Name { get; set; }
[EncryptedStringLength(5000)]
public string Value { get; set; }
public int? LinkedId { get; set; }
public CipherFieldData ToCipherFieldData()
{
return new CipherFieldData
{
Type = Type,
Name = Name,
Value = Value,
LinkedId = LinkedId ?? null,
};
}
Type = Type,
Name = Name,
Value = Value,
LinkedId = LinkedId ?? null,
};
}
}

View File

@ -2,87 +2,86 @@
using Bit.Core.Models.Data;
using Bit.Core.Utilities;
namespace Bit.Api.Models
namespace Bit.Api.Models;
public class CipherIdentityModel
{
public class CipherIdentityModel
public CipherIdentityModel() { }
public CipherIdentityModel(CipherIdentityData data)
{
public CipherIdentityModel() { }
public CipherIdentityModel(CipherIdentityData data)
{
Title = data.Title;
FirstName = data.FirstName;
MiddleName = data.MiddleName;
LastName = data.LastName;
Address1 = data.Address1;
Address2 = data.Address2;
Address3 = data.Address3;
City = data.City;
State = data.State;
PostalCode = data.PostalCode;
Country = data.Country;
Company = data.Company;
Email = data.Email;
Phone = data.Phone;
SSN = data.SSN;
Username = data.Username;
PassportNumber = data.PassportNumber;
LicenseNumber = data.LicenseNumber;
}
[EncryptedString]
[EncryptedStringLength(1000)]
public string Title { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string FirstName { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string MiddleName { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string LastName { get; set; }
[EncryptedString]
[StringLength(1000)]
public string Address1 { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Address2 { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Address3 { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string City { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string State { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string PostalCode { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Country { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Company { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Email { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Phone { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string SSN { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Username { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string PassportNumber { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string LicenseNumber { get; set; }
Title = data.Title;
FirstName = data.FirstName;
MiddleName = data.MiddleName;
LastName = data.LastName;
Address1 = data.Address1;
Address2 = data.Address2;
Address3 = data.Address3;
City = data.City;
State = data.State;
PostalCode = data.PostalCode;
Country = data.Country;
Company = data.Company;
Email = data.Email;
Phone = data.Phone;
SSN = data.SSN;
Username = data.Username;
PassportNumber = data.PassportNumber;
LicenseNumber = data.LicenseNumber;
}
[EncryptedString]
[EncryptedStringLength(1000)]
public string Title { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string FirstName { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string MiddleName { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string LastName { get; set; }
[EncryptedString]
[StringLength(1000)]
public string Address1 { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Address2 { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Address3 { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string City { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string State { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string PostalCode { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Country { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Company { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Email { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Phone { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string SSN { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Username { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string PassportNumber { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string LicenseNumber { get; set; }
}

View File

@ -2,84 +2,83 @@
using Bit.Core.Models.Data;
using Bit.Core.Utilities;
namespace Bit.Api.Models
{
public class CipherLoginModel
{
public CipherLoginModel() { }
namespace Bit.Api.Models;
public CipherLoginModel(CipherLoginData data)
public class CipherLoginModel
{
public CipherLoginModel() { }
public CipherLoginModel(CipherLoginData data)
{
Uris = data.Uris?.Select(u => new CipherLoginUriModel(u))?.ToList();
if (!Uris?.Any() ?? true)
{
Uris = data.Uris?.Select(u => new CipherLoginUriModel(u))?.ToList();
if (!Uris?.Any() ?? true)
Uri = data.Uri;
}
Username = data.Username;
Password = data.Password;
PasswordRevisionDate = data.PasswordRevisionDate;
Totp = data.Totp;
AutofillOnPageLoad = data.AutofillOnPageLoad;
}
[EncryptedString]
[EncryptedStringLength(10000)]
public string Uri
{
get => Uris?.FirstOrDefault()?.Uri;
set
{
if (string.IsNullOrWhiteSpace(value))
{
Uri = data.Uri;
return;
}
Username = data.Username;
Password = data.Password;
PasswordRevisionDate = data.PasswordRevisionDate;
Totp = data.Totp;
AutofillOnPageLoad = data.AutofillOnPageLoad;
if (Uris == null)
{
Uris = new List<CipherLoginUriModel>();
}
Uris.Add(new CipherLoginUriModel(value));
}
}
public List<CipherLoginUriModel> Uris { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Username { get; set; }
[EncryptedString]
[EncryptedStringLength(5000)]
public string Password { get; set; }
public DateTime? PasswordRevisionDate { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Totp { get; set; }
public bool? AutofillOnPageLoad { get; set; }
public class CipherLoginUriModel
{
public CipherLoginUriModel() { }
public CipherLoginUriModel(string uri)
{
Uri = uri;
}
public CipherLoginUriModel(CipherLoginData.CipherLoginUriData uri)
{
Uri = uri.Uri;
Match = uri.Match;
}
[EncryptedString]
[EncryptedStringLength(10000)]
public string Uri
public string Uri { get; set; }
public UriMatchType? Match { get; set; } = null;
public CipherLoginData.CipherLoginUriData ToCipherLoginUriData()
{
get => Uris?.FirstOrDefault()?.Uri;
set
{
if (string.IsNullOrWhiteSpace(value))
{
return;
}
if (Uris == null)
{
Uris = new List<CipherLoginUriModel>();
}
Uris.Add(new CipherLoginUriModel(value));
}
}
public List<CipherLoginUriModel> Uris { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Username { get; set; }
[EncryptedString]
[EncryptedStringLength(5000)]
public string Password { get; set; }
public DateTime? PasswordRevisionDate { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Totp { get; set; }
public bool? AutofillOnPageLoad { get; set; }
public class CipherLoginUriModel
{
public CipherLoginUriModel() { }
public CipherLoginUriModel(string uri)
{
Uri = uri;
}
public CipherLoginUriModel(CipherLoginData.CipherLoginUriData uri)
{
Uri = uri.Uri;
Match = uri.Match;
}
[EncryptedString]
[EncryptedStringLength(10000)]
public string Uri { get; set; }
public UriMatchType? Match { get; set; } = null;
public CipherLoginData.CipherLoginUriData ToCipherLoginUriData()
{
return new CipherLoginData.CipherLoginUriData { Uri = Uri, Match = Match, };
}
return new CipherLoginData.CipherLoginUriData { Uri = Uri, Match = Match, };
}
}
}

View File

@ -2,28 +2,27 @@
using Bit.Core.Models.Data;
using Bit.Core.Utilities;
namespace Bit.Api.Models
namespace Bit.Api.Models;
public class CipherPasswordHistoryModel
{
public class CipherPasswordHistoryModel
public CipherPasswordHistoryModel() { }
public CipherPasswordHistoryModel(CipherPasswordHistoryData data)
{
public CipherPasswordHistoryModel() { }
Password = data.Password;
LastUsedDate = data.LastUsedDate;
}
public CipherPasswordHistoryModel(CipherPasswordHistoryData data)
{
Password = data.Password;
LastUsedDate = data.LastUsedDate;
}
[EncryptedString]
[EncryptedStringLength(5000)]
[Required]
public string Password { get; set; }
[Required]
public DateTime? LastUsedDate { get; set; }
[EncryptedString]
[EncryptedStringLength(5000)]
[Required]
public string Password { get; set; }
[Required]
public DateTime? LastUsedDate { get; set; }
public CipherPasswordHistoryData ToCipherPasswordHistoryData()
{
return new CipherPasswordHistoryData { Password = Password, LastUsedDate = LastUsedDate.Value, };
}
public CipherPasswordHistoryData ToCipherPasswordHistoryData()
{
return new CipherPasswordHistoryData { Password = Password, LastUsedDate = LastUsedDate.Value, };
}
}

View File

@ -1,17 +1,16 @@
using Bit.Core.Enums;
using Bit.Core.Models.Data;
namespace Bit.Api.Models
namespace Bit.Api.Models;
public class CipherSecureNoteModel
{
public class CipherSecureNoteModel
public CipherSecureNoteModel() { }
public CipherSecureNoteModel(CipherSecureNoteData data)
{
public CipherSecureNoteModel() { }
public CipherSecureNoteModel(CipherSecureNoteData data)
{
Type = data.Type;
}
public SecureNoteType Type { get; set; }
Type = data.Type;
}
public SecureNoteType Type { get; set; }
}

View File

@ -1,19 +1,18 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Public
namespace Bit.Api.Models.Public;
public abstract class AssociationWithPermissionsBaseModel
{
public abstract class AssociationWithPermissionsBaseModel
{
/// <summary>
/// The associated object's unique identifier.
/// </summary>
/// <example>bfbc8338-e329-4dc0-b0c9-317c2ebf1a09</example>
[Required]
public Guid? Id { get; set; }
/// <summary>
/// When true, the read only permission will not allow the user or group to make changes to items.
/// </summary>
[Required]
public bool? ReadOnly { get; set; }
}
/// <summary>
/// The associated object's unique identifier.
/// </summary>
/// <example>bfbc8338-e329-4dc0-b0c9-317c2ebf1a09</example>
[Required]
public Guid? Id { get; set; }
/// <summary>
/// When true, the read only permission will not allow the user or group to make changes to items.
/// </summary>
[Required]
public bool? ReadOnly { get; set; }
}

View File

@ -1,14 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Public
namespace Bit.Api.Models.Public;
public abstract class CollectionBaseModel
{
public abstract class CollectionBaseModel
{
/// <summary>
/// External identifier for reference or linking this collection to another system.
/// </summary>
/// <example>external_id_123456</example>
[StringLength(300)]
public string ExternalId { get; set; }
}
/// <summary>
/// External identifier for reference or linking this collection to another system.
/// </summary>
/// <example>external_id_123456</example>
[StringLength(300)]
public string ExternalId { get; set; }
}

View File

@ -1,27 +1,26 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Public
namespace Bit.Api.Models.Public;
public abstract class GroupBaseModel
{
public abstract class GroupBaseModel
{
/// <summary>
/// The name of the group.
/// </summary>
/// <example>Development Team</example>
[Required]
[StringLength(100)]
public string Name { get; set; }
/// <summary>
/// Determines if this group can access all collections within the organization, or only the associated
/// collections. If set to <c>true</c>, this option overrides any collection assignments.
/// </summary>
[Required]
public bool? AccessAll { get; set; }
/// <summary>
/// External identifier for reference or linking this group to another system, such as a user directory.
/// </summary>
/// <example>external_id_123456</example>
[StringLength(300)]
public string ExternalId { get; set; }
}
/// <summary>
/// The name of the group.
/// </summary>
/// <example>Development Team</example>
[Required]
[StringLength(100)]
public string Name { get; set; }
/// <summary>
/// Determines if this group can access all collections within the organization, or only the associated
/// collections. If set to <c>true</c>, this option overrides any collection assignments.
/// </summary>
[Required]
public bool? AccessAll { get; set; }
/// <summary>
/// External identifier for reference or linking this group to another system, such as a user directory.
/// </summary>
/// <example>external_id_123456</example>
[StringLength(300)]
public string ExternalId { get; set; }
}

View File

@ -3,59 +3,58 @@ using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
namespace Bit.Api.Models.Public
namespace Bit.Api.Models.Public;
public abstract class MemberBaseModel
{
public abstract class MemberBaseModel
public MemberBaseModel() { }
public MemberBaseModel(OrganizationUser user)
{
public MemberBaseModel() { }
public MemberBaseModel(OrganizationUser user)
if (user == null)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
Type = user.Type;
AccessAll = user.AccessAll;
ExternalId = user.ExternalId;
ResetPasswordEnrolled = user.ResetPasswordKey != null;
throw new ArgumentNullException(nameof(user));
}
public MemberBaseModel(OrganizationUserUserDetails user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
Type = user.Type;
AccessAll = user.AccessAll;
ExternalId = user.ExternalId;
ResetPasswordEnrolled = user.ResetPasswordKey != null;
}
/// <summary>
/// The member's type (or role) within the organization.
/// </summary>
[Required]
public OrganizationUserType? Type { get; set; }
/// <summary>
/// Determines if this member can access all collections within the organization, or only the associated
/// collections. If set to <c>true</c>, this option overrides any collection assignments.
/// </summary>
[Required]
public bool? AccessAll { get; set; }
/// <summary>
/// External identifier for reference or linking this member to another system, such as a user directory.
/// </summary>
/// <example>external_id_123456</example>
[StringLength(300)]
public string ExternalId { get; set; }
/// <summary>
/// Returns <c>true</c> if the member has enrolled in Password Reset assistance within the organization
/// </summary>
[Required]
public bool ResetPasswordEnrolled { get; set; }
Type = user.Type;
AccessAll = user.AccessAll;
ExternalId = user.ExternalId;
ResetPasswordEnrolled = user.ResetPasswordKey != null;
}
public MemberBaseModel(OrganizationUserUserDetails user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
Type = user.Type;
AccessAll = user.AccessAll;
ExternalId = user.ExternalId;
ResetPasswordEnrolled = user.ResetPasswordKey != null;
}
/// <summary>
/// The member's type (or role) within the organization.
/// </summary>
[Required]
public OrganizationUserType? Type { get; set; }
/// <summary>
/// Determines if this member can access all collections within the organization, or only the associated
/// collections. If set to <c>true</c>, this option overrides any collection assignments.
/// </summary>
[Required]
public bool? AccessAll { get; set; }
/// <summary>
/// External identifier for reference or linking this member to another system, such as a user directory.
/// </summary>
/// <example>external_id_123456</example>
[StringLength(300)]
public string ExternalId { get; set; }
/// <summary>
/// Returns <c>true</c> if the member has enrolled in Password Reset assistance within the organization
/// </summary>
[Required]
public bool ResetPasswordEnrolled { get; set; }
}

View File

@ -1,17 +1,16 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Public
namespace Bit.Api.Models.Public;
public abstract class PolicyBaseModel
{
public abstract class PolicyBaseModel
{
/// <summary>
/// Determines if this policy is enabled and enforced.
/// </summary>
[Required]
public bool? Enabled { get; set; }
/// <summary>
/// Data for the policy.
/// </summary>
public Dictionary<string, object> Data { get; set; }
}
/// <summary>
/// Determines if this policy is enabled and enforced.
/// </summary>
[Required]
public bool? Enabled { get; set; }
/// <summary>
/// Data for the policy.
/// </summary>
public Dictionary<string, object> Data { get; set; }
}

View File

@ -1,16 +1,15 @@
using Bit.Core.Models.Data;
namespace Bit.Api.Models.Public.Request
namespace Bit.Api.Models.Public.Request;
public class AssociationWithPermissionsRequestModel : AssociationWithPermissionsBaseModel
{
public class AssociationWithPermissionsRequestModel : AssociationWithPermissionsBaseModel
public SelectionReadOnly ToSelectionReadOnly()
{
public SelectionReadOnly ToSelectionReadOnly()
return new SelectionReadOnly
{
return new SelectionReadOnly
{
Id = Id.Value,
ReadOnly = ReadOnly.Value
};
}
Id = Id.Value,
ReadOnly = ReadOnly.Value
};
}
}

View File

@ -1,18 +1,17 @@
using Bit.Core.Entities;
namespace Bit.Api.Models.Public.Request
{
public class CollectionUpdateRequestModel : CollectionBaseModel
{
/// <summary>
/// The associated groups that this collection is assigned to.
/// </summary>
public IEnumerable<AssociationWithPermissionsRequestModel> Groups { get; set; }
namespace Bit.Api.Models.Public.Request;
public Collection ToCollection(Collection existingCollection)
{
existingCollection.ExternalId = ExternalId;
return existingCollection;
}
public class CollectionUpdateRequestModel : CollectionBaseModel
{
/// <summary>
/// The associated groups that this collection is assigned to.
/// </summary>
public IEnumerable<AssociationWithPermissionsRequestModel> Groups { get; set; }
public Collection ToCollection(Collection existingCollection)
{
existingCollection.ExternalId = ExternalId;
return existingCollection;
}
}

View File

@ -1,50 +1,49 @@
using Bit.Core.Exceptions;
namespace Bit.Api.Models.Public.Request
namespace Bit.Api.Models.Public.Request;
public class EventFilterRequestModel
{
public class EventFilterRequestModel
/// <summary>
/// The start date. Must be less than the end date.
/// </summary>
public DateTime? Start { get; set; }
/// <summary>
/// The end date. Must be greater than the start date.
/// </summary>
public DateTime? End { get; set; }
/// <summary>
/// The unique identifier of the user that performed the event.
/// </summary>
public Guid? ActingUserId { get; set; }
/// <summary>
/// The unique identifier of the related item that the event describes.
/// </summary>
public Guid? ItemId { get; set; }
/// <summary>
/// A cursor for use in pagination.
/// </summary>
public string ContinuationToken { get; set; }
public Tuple<DateTime, DateTime> ToDateRange()
{
/// <summary>
/// The start date. Must be less than the end date.
/// </summary>
public DateTime? Start { get; set; }
/// <summary>
/// The end date. Must be greater than the start date.
/// </summary>
public DateTime? End { get; set; }
/// <summary>
/// The unique identifier of the user that performed the event.
/// </summary>
public Guid? ActingUserId { get; set; }
/// <summary>
/// The unique identifier of the related item that the event describes.
/// </summary>
public Guid? ItemId { get; set; }
/// <summary>
/// A cursor for use in pagination.
/// </summary>
public string ContinuationToken { get; set; }
public Tuple<DateTime, DateTime> ToDateRange()
if (!End.HasValue || !Start.HasValue)
{
if (!End.HasValue || !Start.HasValue)
{
End = DateTime.UtcNow.Date.AddDays(1).AddMilliseconds(-1);
Start = DateTime.UtcNow.Date.AddDays(-30);
}
else if (Start.Value > End.Value)
{
var newEnd = Start;
Start = End;
End = newEnd;
}
if ((End.Value - Start.Value) > TimeSpan.FromDays(367))
{
throw new BadRequestException("Date range must be < 367 days.");
}
return new Tuple<DateTime, DateTime>(Start.Value, End.Value);
End = DateTime.UtcNow.Date.AddDays(1).AddMilliseconds(-1);
Start = DateTime.UtcNow.Date.AddDays(-30);
}
else if (Start.Value > End.Value)
{
var newEnd = Start;
Start = End;
End = newEnd;
}
if ((End.Value - Start.Value) > TimeSpan.FromDays(367))
{
throw new BadRequestException("Date range must be < 367 days.");
}
return new Tuple<DateTime, DateTime>(Start.Value, End.Value);
}
}

View File

@ -1,28 +1,27 @@
using Bit.Core.Entities;
namespace Bit.Api.Models.Public.Request
namespace Bit.Api.Models.Public.Request;
public class GroupCreateUpdateRequestModel : GroupBaseModel
{
public class GroupCreateUpdateRequestModel : GroupBaseModel
/// <summary>
/// The associated collections that this group can access.
/// </summary>
public IEnumerable<AssociationWithPermissionsRequestModel> Collections { get; set; }
public Group ToGroup(Guid orgId)
{
/// <summary>
/// The associated collections that this group can access.
/// </summary>
public IEnumerable<AssociationWithPermissionsRequestModel> Collections { get; set; }
public Group ToGroup(Guid orgId)
return ToGroup(new Group
{
return ToGroup(new Group
{
OrganizationId = orgId
});
}
OrganizationId = orgId
});
}
public Group ToGroup(Group existingGroup)
{
existingGroup.Name = Name;
existingGroup.AccessAll = AccessAll.Value;
existingGroup.ExternalId = ExternalId;
return existingGroup;
}
public Group ToGroup(Group existingGroup)
{
existingGroup.Name = Name;
existingGroup.AccessAll = AccessAll.Value;
existingGroup.ExternalId = ExternalId;
return existingGroup;
}
}

View File

@ -2,22 +2,21 @@
using Bit.Core.Entities;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Public.Request
{
public class MemberCreateRequestModel : MemberUpdateRequestModel
{
/// <summary>
/// The member's email address.
/// </summary>
/// <example>jsmith@example.com</example>
[Required]
[StringLength(256)]
[StrictEmailAddress]
public string Email { get; set; }
namespace Bit.Api.Models.Public.Request;
public override OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
{
throw new NotImplementedException();
}
public class MemberCreateRequestModel : MemberUpdateRequestModel
{
/// <summary>
/// The member's email address.
/// </summary>
/// <example>jsmith@example.com</example>
[Required]
[StringLength(256)]
[StrictEmailAddress]
public string Email { get; set; }
public override OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
{
throw new NotImplementedException();
}
}

View File

@ -1,20 +1,19 @@
using Bit.Core.Entities;
namespace Bit.Api.Models.Public.Request
{
public class MemberUpdateRequestModel : MemberBaseModel
{
/// <summary>
/// The associated collections that this member can access.
/// </summary>
public IEnumerable<AssociationWithPermissionsRequestModel> Collections { get; set; }
namespace Bit.Api.Models.Public.Request;
public virtual OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
{
existingUser.Type = Type.Value;
existingUser.AccessAll = AccessAll.Value;
existingUser.ExternalId = ExternalId;
return existingUser;
}
public class MemberUpdateRequestModel : MemberBaseModel
{
/// <summary>
/// The associated collections that this member can access.
/// </summary>
public IEnumerable<AssociationWithPermissionsRequestModel> Collections { get; set; }
public virtual OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
{
existingUser.Type = Type.Value;
existingUser.AccessAll = AccessAll.Value;
existingUser.ExternalId = ExternalId;
return existingUser;
}
}

View File

@ -4,108 +4,107 @@ using Bit.Core.Entities;
using Bit.Core.Models.Business;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Public.Request
namespace Bit.Api.Models.Public.Request;
public class OrganizationImportRequestModel
{
public class OrganizationImportRequestModel
/// <summary>
/// Groups to import.
/// </summary>
public OrganizationImportGroupRequestModel[] Groups { get; set; }
/// <summary>
/// Members to import.
/// </summary>
public OrganizationImportMemberRequestModel[] Members { get; set; }
/// <summary>
/// Determines if the data in this request should overwrite or append to the existing organization data.
/// </summary>
[Required]
public bool? OverwriteExisting { get; set; }
/// <summary>
/// Indicates an import of over 2000 users and/or groups is expected
/// </summary>
public bool LargeImport { get; set; } = false;
public class OrganizationImportGroupRequestModel
{
/// <summary>
/// Groups to import.
/// </summary>
public OrganizationImportGroupRequestModel[] Groups { get; set; }
/// <summary>
/// Members to import.
/// </summary>
public OrganizationImportMemberRequestModel[] Members { get; set; }
/// <summary>
/// Determines if the data in this request should overwrite or append to the existing organization data.
/// The name of the group.
/// </summary>
/// <example>Development Team</example>
[Required]
public bool? OverwriteExisting { get; set; }
[StringLength(100)]
public string Name { get; set; }
/// <summary>
/// Indicates an import of over 2000 users and/or groups is expected
/// External identifier for reference or linking this group to another system, such as a user directory.
/// </summary>
public bool LargeImport { get; set; } = false;
/// <example>external_id_123456</example>
[Required]
[StringLength(300)]
[JsonConverter(typeof(PermissiveStringConverter))]
public string ExternalId { get; set; }
/// <summary>
/// The associated external ids for members in this group.
/// </summary>
[JsonConverter(typeof(PermissiveStringEnumerableConverter))]
public IEnumerable<string> MemberExternalIds { get; set; }
public class OrganizationImportGroupRequestModel
public ImportedGroup ToImportedGroup(Guid organizationId)
{
/// <summary>
/// The name of the group.
/// </summary>
/// <example>Development Team</example>
[Required]
[StringLength(100)]
public string Name { get; set; }
/// <summary>
/// External identifier for reference or linking this group to another system, such as a user directory.
/// </summary>
/// <example>external_id_123456</example>
[Required]
[StringLength(300)]
[JsonConverter(typeof(PermissiveStringConverter))]
public string ExternalId { get; set; }
/// <summary>
/// The associated external ids for members in this group.
/// </summary>
[JsonConverter(typeof(PermissiveStringEnumerableConverter))]
public IEnumerable<string> MemberExternalIds { get; set; }
public ImportedGroup ToImportedGroup(Guid organizationId)
var importedGroup = new ImportedGroup
{
var importedGroup = new ImportedGroup
Group = new Group
{
Group = new Group
{
OrganizationId = organizationId,
Name = Name,
ExternalId = ExternalId
},
ExternalUserIds = new HashSet<string>(MemberExternalIds)
};
OrganizationId = organizationId,
Name = Name,
ExternalId = ExternalId
},
ExternalUserIds = new HashSet<string>(MemberExternalIds)
};
return importedGroup;
}
return importedGroup;
}
}
public class OrganizationImportMemberRequestModel : IValidatableObject
{
/// <summary>
/// The member's email address. Required for non-deleted users.
/// </summary>
/// <example>jsmith@example.com</example>
[EmailAddress]
[StringLength(256)]
public string Email { get; set; }
/// <summary>
/// External identifier for reference or linking this member to another system, such as a user directory.
/// </summary>
/// <example>external_id_123456</example>
[Required]
[StringLength(300)]
[JsonConverter(typeof(PermissiveStringConverter))]
public string ExternalId { get; set; }
/// <summary>
/// Determines if this member should be removed from the organization during import.
/// </summary>
public bool Deleted { get; set; }
public ImportedOrganizationUser ToImportedOrganizationUser()
{
var importedUser = new ImportedOrganizationUser
{
Email = Email.ToLowerInvariant(),
ExternalId = ExternalId
};
return importedUser;
}
public class OrganizationImportMemberRequestModel : IValidatableObject
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
/// <summary>
/// The member's email address. Required for non-deleted users.
/// </summary>
/// <example>jsmith@example.com</example>
[EmailAddress]
[StringLength(256)]
public string Email { get; set; }
/// <summary>
/// External identifier for reference or linking this member to another system, such as a user directory.
/// </summary>
/// <example>external_id_123456</example>
[Required]
[StringLength(300)]
[JsonConverter(typeof(PermissiveStringConverter))]
public string ExternalId { get; set; }
/// <summary>
/// Determines if this member should be removed from the organization during import.
/// </summary>
public bool Deleted { get; set; }
public ImportedOrganizationUser ToImportedOrganizationUser()
if (string.IsNullOrWhiteSpace(Email) && !Deleted)
{
var importedUser = new ImportedOrganizationUser
{
Email = Email.ToLowerInvariant(),
ExternalId = ExternalId
};
return importedUser;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrWhiteSpace(Email) && !Deleted)
{
yield return new ValidationResult("Email is required for enabled members.",
new string[] { nameof(Email) });
}
yield return new ValidationResult("Email is required for enabled members.",
new string[] { nameof(Email) });
}
}
}

View File

@ -1,23 +1,22 @@
using System.Text.Json;
using Bit.Core.Entities;
namespace Bit.Api.Models.Public.Request
{
public class PolicyUpdateRequestModel : PolicyBaseModel
{
public Policy ToPolicy(Guid orgId)
{
return ToPolicy(new Policy
{
OrganizationId = orgId
});
}
namespace Bit.Api.Models.Public.Request;
public virtual Policy ToPolicy(Policy existingPolicy)
public class PolicyUpdateRequestModel : PolicyBaseModel
{
public Policy ToPolicy(Guid orgId)
{
return ToPolicy(new Policy
{
existingPolicy.Enabled = Enabled.GetValueOrDefault();
existingPolicy.Data = Data != null ? JsonSerializer.Serialize(Data) : null;
return existingPolicy;
}
OrganizationId = orgId
});
}
public virtual Policy ToPolicy(Policy existingPolicy)
{
existingPolicy.Enabled = Enabled.GetValueOrDefault();
existingPolicy.Data = Data != null ? JsonSerializer.Serialize(Data) : null;
return existingPolicy;
}
}

View File

@ -1,10 +1,9 @@
namespace Bit.Api.Models.Public.Request
namespace Bit.Api.Models.Public.Request;
public class UpdateGroupIdsRequestModel
{
public class UpdateGroupIdsRequestModel
{
/// <summary>
/// The associated group ids that this object can access.
/// </summary>
public IEnumerable<Guid> GroupIds { get; set; }
}
/// <summary>
/// The associated group ids that this object can access.
/// </summary>
public IEnumerable<Guid> GroupIds { get; set; }
}

View File

@ -1,10 +1,9 @@
namespace Bit.Api.Models.Public.Request
namespace Bit.Api.Models.Public.Request;
public class UpdateMemberIdsRequestModel
{
public class UpdateMemberIdsRequestModel
{
/// <summary>
/// The associated member ids that have access to this object.
/// </summary>
public IEnumerable<Guid> MemberIds { get; set; }
}
/// <summary>
/// The associated member ids that have access to this object.
/// </summary>
public IEnumerable<Guid> MemberIds { get; set; }
}

View File

@ -1,17 +1,16 @@
using Bit.Core.Models.Data;
namespace Bit.Api.Models.Public.Response
namespace Bit.Api.Models.Public.Response;
public class AssociationWithPermissionsResponseModel : AssociationWithPermissionsBaseModel
{
public class AssociationWithPermissionsResponseModel : AssociationWithPermissionsBaseModel
public AssociationWithPermissionsResponseModel(SelectionReadOnly selection)
{
public AssociationWithPermissionsResponseModel(SelectionReadOnly selection)
if (selection == null)
{
if (selection == null)
{
throw new ArgumentNullException(nameof(selection));
}
Id = selection.Id;
ReadOnly = selection.ReadOnly;
throw new ArgumentNullException(nameof(selection));
}
Id = selection.Id;
ReadOnly = selection.ReadOnly;
}
}

View File

@ -2,40 +2,39 @@
using Bit.Core.Entities;
using Bit.Core.Models.Data;
namespace Bit.Api.Models.Public.Response
{
/// <summary>
/// A collection.
/// </summary>
public class CollectionResponseModel : CollectionBaseModel, IResponseModel
{
public CollectionResponseModel(Collection collection, IEnumerable<SelectionReadOnly> groups)
{
if (collection == null)
{
throw new ArgumentNullException(nameof(collection));
}
namespace Bit.Api.Models.Public.Response;
Id = collection.Id;
ExternalId = collection.ExternalId;
Groups = groups?.Select(c => new AssociationWithPermissionsResponseModel(c));
/// <summary>
/// A collection.
/// </summary>
public class CollectionResponseModel : CollectionBaseModel, IResponseModel
{
public CollectionResponseModel(Collection collection, IEnumerable<SelectionReadOnly> groups)
{
if (collection == null)
{
throw new ArgumentNullException(nameof(collection));
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>collection</example>
[Required]
public string Object => "collection";
/// <summary>
/// The collection's unique identifier.
/// </summary>
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
[Required]
public Guid Id { get; set; }
/// <summary>
/// The associated groups that this collection is assigned to.
/// </summary>
public IEnumerable<AssociationWithPermissionsResponseModel> Groups { get; set; }
Id = collection.Id;
ExternalId = collection.ExternalId;
Groups = groups?.Select(c => new AssociationWithPermissionsResponseModel(c));
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>collection</example>
[Required]
public string Object => "collection";
/// <summary>
/// The collection's unique identifier.
/// </summary>
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
[Required]
public Guid Id { get; set; }
/// <summary>
/// The associated groups that this collection is assigned to.
/// </summary>
public IEnumerable<AssociationWithPermissionsResponseModel> Groups { get; set; }
}

View File

@ -1,77 +1,76 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace Bit.Api.Models.Public.Response
namespace Bit.Api.Models.Public.Response;
public class ErrorResponseModel : IResponseModel
{
public class ErrorResponseModel : IResponseModel
public ErrorResponseModel(string message)
{
public ErrorResponseModel(string message)
{
Message = message;
}
public ErrorResponseModel(ModelStateDictionary modelState)
{
Message = "The request's model state is invalid.";
Errors = new Dictionary<string, IEnumerable<string>>();
var keys = modelState.Keys.ToList();
var values = modelState.Values.ToList();
for (var i = 0; i < values.Count; i++)
{
var value = values[i];
if (keys.Count <= i)
{
// Keys not available for some reason.
break;
}
var key = keys[i];
if (value.ValidationState != ModelValidationState.Invalid || value.Errors.Count == 0)
{
continue;
}
var errors = value.Errors.Select(e => e.ErrorMessage);
Errors.Add(key, errors);
}
}
public ErrorResponseModel(Dictionary<string, IEnumerable<string>> errors)
: this("Errors have occurred.", errors)
{ }
public ErrorResponseModel(string errorKey, string errorValue)
: this(errorKey, new string[] { errorValue })
{ }
public ErrorResponseModel(string errorKey, IEnumerable<string> errorValues)
: this(new Dictionary<string, IEnumerable<string>> { { errorKey, errorValues } })
{ }
public ErrorResponseModel(string message, Dictionary<string, IEnumerable<string>> errors)
{
Message = message;
Errors = errors;
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>error</example>
[Required]
public string Object => "error";
/// <summary>
/// A human-readable message providing details about the error.
/// </summary>
/// <example>The request model is invalid.</example>
[Required]
public string Message { get; set; }
/// <summary>
/// If multiple errors occurred, they are listed in dictionary. Errors related to a specific
/// request parameter will include a dictionary key describing that parameter.
/// </summary>
public Dictionary<string, IEnumerable<string>> Errors { get; set; }
Message = message;
}
public ErrorResponseModel(ModelStateDictionary modelState)
{
Message = "The request's model state is invalid.";
Errors = new Dictionary<string, IEnumerable<string>>();
var keys = modelState.Keys.ToList();
var values = modelState.Values.ToList();
for (var i = 0; i < values.Count; i++)
{
var value = values[i];
if (keys.Count <= i)
{
// Keys not available for some reason.
break;
}
var key = keys[i];
if (value.ValidationState != ModelValidationState.Invalid || value.Errors.Count == 0)
{
continue;
}
var errors = value.Errors.Select(e => e.ErrorMessage);
Errors.Add(key, errors);
}
}
public ErrorResponseModel(Dictionary<string, IEnumerable<string>> errors)
: this("Errors have occurred.", errors)
{ }
public ErrorResponseModel(string errorKey, string errorValue)
: this(errorKey, new string[] { errorValue })
{ }
public ErrorResponseModel(string errorKey, IEnumerable<string> errorValues)
: this(new Dictionary<string, IEnumerable<string>> { { errorKey, errorValues } })
{ }
public ErrorResponseModel(string message, Dictionary<string, IEnumerable<string>> errors)
{
Message = message;
Errors = errors;
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>error</example>
[Required]
public string Object => "error";
/// <summary>
/// A human-readable message providing details about the error.
/// </summary>
/// <example>The request model is invalid.</example>
[Required]
public string Message { get; set; }
/// <summary>
/// If multiple errors occurred, they are listed in dictionary. Errors related to a specific
/// request parameter will include a dictionary key describing that parameter.
/// </summary>
public Dictionary<string, IEnumerable<string>> Errors { get; set; }
}

View File

@ -2,92 +2,91 @@
using Bit.Core.Enums;
using Bit.Core.Models.Data;
namespace Bit.Api.Models.Public.Response
{
/// <summary>
/// An event log.
/// </summary>
public class EventResponseModel : IResponseModel
{
public EventResponseModel(IEvent ev)
{
if (ev == null)
{
throw new ArgumentNullException(nameof(ev));
}
namespace Bit.Api.Models.Public.Response;
Type = ev.Type;
ItemId = ev.CipherId;
CollectionId = ev.CollectionId;
GroupId = ev.GroupId;
PolicyId = ev.PolicyId;
MemberId = ev.OrganizationUserId;
ActingUserId = ev.ActingUserId;
Date = ev.Date;
Device = ev.DeviceType;
IpAddress = ev.IpAddress;
InstallationId = ev.InstallationId;
/// <summary>
/// An event log.
/// </summary>
public class EventResponseModel : IResponseModel
{
public EventResponseModel(IEvent ev)
{
if (ev == null)
{
throw new ArgumentNullException(nameof(ev));
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>event</example>
[Required]
public string Object => "event";
/// <summary>
/// The type of event.
/// </summary>
[Required]
public EventType Type { get; set; }
/// <summary>
/// The unique identifier of the related item that the event describes.
/// </summary>
/// <example>3767a302-8208-4dc6-b842-030428a1cfad</example>
public Guid? ItemId { get; set; }
/// <summary>
/// The unique identifier of the related collection that the event describes.
/// </summary>
/// <example>bce212a4-25f3-4888-8a0a-4c5736d851e0</example>
public Guid? CollectionId { get; set; }
/// <summary>
/// The unique identifier of the related group that the event describes.
/// </summary>
/// <example>f29a2515-91d2-4452-b49b-5e8040e6b0f4</example>
public Guid? GroupId { get; set; }
/// <summary>
/// The unique identifier of the related policy that the event describes.
/// </summary>
/// <example>f29a2515-91d2-4452-b49b-5e8040e6b0f4</example>
public Guid? PolicyId { get; set; }
/// <summary>
/// The unique identifier of the related member that the event describes.
/// </summary>
/// <example>e68b8629-85eb-4929-92c0-b84464976ba4</example>
public Guid? MemberId { get; set; }
/// <summary>
/// The unique identifier of the user that performed the event.
/// </summary>
/// <example>a2549f79-a71f-4eb9-9234-eb7247333f94</example>
public Guid? ActingUserId { get; set; }
/// <summary>
/// The Unique identifier of the Installation that performed the event.
/// </summary>
/// <value></value>
public Guid? InstallationId { get; set; }
/// <summary>
/// The date/timestamp when the event occurred.
/// </summary>
[Required]
public DateTime Date { get; set; }
/// <summary>
/// The type of device used by the acting user when the event occurred.
/// </summary>
public DeviceType? Device { get; set; }
/// <summary>
/// The IP address of the acting user.
/// </summary>
/// <example>172.16.254.1</example>
public string IpAddress { get; set; }
Type = ev.Type;
ItemId = ev.CipherId;
CollectionId = ev.CollectionId;
GroupId = ev.GroupId;
PolicyId = ev.PolicyId;
MemberId = ev.OrganizationUserId;
ActingUserId = ev.ActingUserId;
Date = ev.Date;
Device = ev.DeviceType;
IpAddress = ev.IpAddress;
InstallationId = ev.InstallationId;
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>event</example>
[Required]
public string Object => "event";
/// <summary>
/// The type of event.
/// </summary>
[Required]
public EventType Type { get; set; }
/// <summary>
/// The unique identifier of the related item that the event describes.
/// </summary>
/// <example>3767a302-8208-4dc6-b842-030428a1cfad</example>
public Guid? ItemId { get; set; }
/// <summary>
/// The unique identifier of the related collection that the event describes.
/// </summary>
/// <example>bce212a4-25f3-4888-8a0a-4c5736d851e0</example>
public Guid? CollectionId { get; set; }
/// <summary>
/// The unique identifier of the related group that the event describes.
/// </summary>
/// <example>f29a2515-91d2-4452-b49b-5e8040e6b0f4</example>
public Guid? GroupId { get; set; }
/// <summary>
/// The unique identifier of the related policy that the event describes.
/// </summary>
/// <example>f29a2515-91d2-4452-b49b-5e8040e6b0f4</example>
public Guid? PolicyId { get; set; }
/// <summary>
/// The unique identifier of the related member that the event describes.
/// </summary>
/// <example>e68b8629-85eb-4929-92c0-b84464976ba4</example>
public Guid? MemberId { get; set; }
/// <summary>
/// The unique identifier of the user that performed the event.
/// </summary>
/// <example>a2549f79-a71f-4eb9-9234-eb7247333f94</example>
public Guid? ActingUserId { get; set; }
/// <summary>
/// The Unique identifier of the Installation that performed the event.
/// </summary>
/// <value></value>
public Guid? InstallationId { get; set; }
/// <summary>
/// The date/timestamp when the event occurred.
/// </summary>
[Required]
public DateTime Date { get; set; }
/// <summary>
/// The type of device used by the acting user when the event occurred.
/// </summary>
public DeviceType? Device { get; set; }
/// <summary>
/// The IP address of the acting user.
/// </summary>
/// <example>172.16.254.1</example>
public string IpAddress { get; set; }
}

View File

@ -2,42 +2,41 @@
using Bit.Core.Entities;
using Bit.Core.Models.Data;
namespace Bit.Api.Models.Public.Response
{
/// <summary>
/// A user group.
/// </summary>
public class GroupResponseModel : GroupBaseModel, IResponseModel
{
public GroupResponseModel(Group group, IEnumerable<SelectionReadOnly> collections)
{
if (group == null)
{
throw new ArgumentNullException(nameof(group));
}
namespace Bit.Api.Models.Public.Response;
Id = group.Id;
Name = group.Name;
AccessAll = group.AccessAll;
ExternalId = group.ExternalId;
Collections = collections?.Select(c => new AssociationWithPermissionsResponseModel(c));
/// <summary>
/// A user group.
/// </summary>
public class GroupResponseModel : GroupBaseModel, IResponseModel
{
public GroupResponseModel(Group group, IEnumerable<SelectionReadOnly> collections)
{
if (group == null)
{
throw new ArgumentNullException(nameof(group));
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>group</example>
[Required]
public string Object => "group";
/// <summary>
/// The group's unique identifier.
/// </summary>
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
[Required]
public Guid Id { get; set; }
/// <summary>
/// The associated collections that this group can access.
/// </summary>
public IEnumerable<AssociationWithPermissionsResponseModel> Collections { get; set; }
Id = group.Id;
Name = group.Name;
AccessAll = group.AccessAll;
ExternalId = group.ExternalId;
Collections = collections?.Select(c => new AssociationWithPermissionsResponseModel(c));
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>group</example>
[Required]
public string Object => "group";
/// <summary>
/// The group's unique identifier.
/// </summary>
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
[Required]
public Guid Id { get; set; }
/// <summary>
/// The associated collections that this group can access.
/// </summary>
public IEnumerable<AssociationWithPermissionsResponseModel> Collections { get; set; }
}

View File

@ -1,7 +1,6 @@
namespace Bit.Api.Models.Public.Response
namespace Bit.Api.Models.Public.Response;
public interface IResponseModel
{
public interface IResponseModel
{
string Object { get; }
}
string Object { get; }
}

View File

@ -1,29 +1,28 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Public.Response
{
public class ListResponseModel<T> : IResponseModel where T : IResponseModel
{
public ListResponseModel(IEnumerable<T> data, string continuationToken = null)
{
Data = data;
ContinuationToken = continuationToken;
}
namespace Bit.Api.Models.Public.Response;
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>list</example>
[Required]
public string Object => "list";
/// <summary>
/// An array containing the actual response elements, paginated by any request parameters.
/// </summary>
[Required]
public IEnumerable<T> Data { get; set; }
/// <summary>
/// A cursor for use in pagination.
/// </summary>
public string ContinuationToken { get; set; }
public class ListResponseModel<T> : IResponseModel where T : IResponseModel
{
public ListResponseModel(IEnumerable<T> data, string continuationToken = null)
{
Data = data;
ContinuationToken = continuationToken;
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>list</example>
[Required]
public string Object => "list";
/// <summary>
/// An array containing the actual response elements, paginated by any request parameters.
/// </summary>
[Required]
public IEnumerable<T> Data { get; set; }
/// <summary>
/// A cursor for use in pagination.
/// </summary>
public string ContinuationToken { get; set; }
}

View File

@ -4,91 +4,90 @@ using Bit.Core.Enums;
using Bit.Core.Models.Data;
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
namespace Bit.Api.Models.Public.Response
namespace Bit.Api.Models.Public.Response;
/// <summary>
/// An organization member.
/// </summary>
public class MemberResponseModel : MemberBaseModel, IResponseModel
{
/// <summary>
/// An organization member.
/// </summary>
public class MemberResponseModel : MemberBaseModel, IResponseModel
public MemberResponseModel(OrganizationUser user, IEnumerable<SelectionReadOnly> collections)
: base(user)
{
public MemberResponseModel(OrganizationUser user, IEnumerable<SelectionReadOnly> collections)
: base(user)
if (user == null)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
Id = user.Id;
UserId = user.UserId;
Email = user.Email;
Status = user.Status;
Collections = collections?.Select(c => new AssociationWithPermissionsResponseModel(c));
throw new ArgumentNullException(nameof(user));
}
public MemberResponseModel(OrganizationUserUserDetails user, bool twoFactorEnabled,
IEnumerable<SelectionReadOnly> collections)
: base(user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
Id = user.Id;
UserId = user.UserId;
Name = user.Name;
Email = user.Email;
TwoFactorEnabled = twoFactorEnabled;
Status = user.Status;
Collections = collections?.Select(c => new AssociationWithPermissionsResponseModel(c));
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>member</example>
[Required]
public string Object => "member";
/// <summary>
/// The member's unique identifier within the organization.
/// </summary>
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
[Required]
public Guid Id { get; set; }
/// <summary>
/// The member's unique identifier across Bitwarden.
/// </summary>
/// <example>48b47ee1-493e-4c67-aef7-014996c40eca</example>
[Required]
public Guid? UserId { get; set; }
/// <summary>
/// The member's name, set from their user account profile.
/// </summary>
/// <example>John Smith</example>
public string Name { get; set; }
/// <summary>
/// The member's email address.
/// </summary>
/// <example>jsmith@example.com</example>
[Required]
public string Email { get; set; }
/// <summary>
/// Returns <c>true</c> if the member has a two-step login method enabled on their user account.
/// </summary>
[Required]
public bool TwoFactorEnabled { get; set; }
/// <summary>
/// The member's status within the organization. All created members start with a status of "Invited".
/// Once a member accept's their invitation to join the organization, their status changes to "Accepted".
/// Accepted members are then "Confirmed" by an organization administrator. Once a member is "Confirmed",
/// their status can no longer change.
/// </summary>
[Required]
public OrganizationUserStatusType Status { get; set; }
/// <summary>
/// The associated collections that this member can access.
/// </summary>
public IEnumerable<AssociationWithPermissionsResponseModel> Collections { get; set; }
Id = user.Id;
UserId = user.UserId;
Email = user.Email;
Status = user.Status;
Collections = collections?.Select(c => new AssociationWithPermissionsResponseModel(c));
}
public MemberResponseModel(OrganizationUserUserDetails user, bool twoFactorEnabled,
IEnumerable<SelectionReadOnly> collections)
: base(user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
Id = user.Id;
UserId = user.UserId;
Name = user.Name;
Email = user.Email;
TwoFactorEnabled = twoFactorEnabled;
Status = user.Status;
Collections = collections?.Select(c => new AssociationWithPermissionsResponseModel(c));
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>member</example>
[Required]
public string Object => "member";
/// <summary>
/// The member's unique identifier within the organization.
/// </summary>
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
[Required]
public Guid Id { get; set; }
/// <summary>
/// The member's unique identifier across Bitwarden.
/// </summary>
/// <example>48b47ee1-493e-4c67-aef7-014996c40eca</example>
[Required]
public Guid? UserId { get; set; }
/// <summary>
/// The member's name, set from their user account profile.
/// </summary>
/// <example>John Smith</example>
public string Name { get; set; }
/// <summary>
/// The member's email address.
/// </summary>
/// <example>jsmith@example.com</example>
[Required]
public string Email { get; set; }
/// <summary>
/// Returns <c>true</c> if the member has a two-step login method enabled on their user account.
/// </summary>
[Required]
public bool TwoFactorEnabled { get; set; }
/// <summary>
/// The member's status within the organization. All created members start with a status of "Invited".
/// Once a member accept's their invitation to join the organization, their status changes to "Accepted".
/// Accepted members are then "Confirmed" by an organization administrator. Once a member is "Confirmed",
/// their status can no longer change.
/// </summary>
[Required]
public OrganizationUserStatusType Status { get; set; }
/// <summary>
/// The associated collections that this member can access.
/// </summary>
public IEnumerable<AssociationWithPermissionsResponseModel> Collections { get; set; }
}

View File

@ -3,45 +3,44 @@ using System.Text.Json;
using Bit.Core.Entities;
using Bit.Core.Enums;
namespace Bit.Api.Models.Public.Response
{
/// <summary>
/// A policy.
/// </summary>
public class PolicyResponseModel : PolicyBaseModel, IResponseModel
{
public PolicyResponseModel(Policy policy)
{
if (policy == null)
{
throw new ArgumentNullException(nameof(policy));
}
namespace Bit.Api.Models.Public.Response;
Id = policy.Id;
Type = policy.Type;
Enabled = policy.Enabled;
if (!string.IsNullOrWhiteSpace(policy.Data))
{
Data = JsonSerializer.Deserialize<Dictionary<string, object>>(policy.Data);
}
/// <summary>
/// A policy.
/// </summary>
public class PolicyResponseModel : PolicyBaseModel, IResponseModel
{
public PolicyResponseModel(Policy policy)
{
if (policy == null)
{
throw new ArgumentNullException(nameof(policy));
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>policy</example>
[Required]
public string Object => "policy";
/// <summary>
/// The policy's unique identifier.
/// </summary>
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
[Required]
public Guid Id { get; set; }
/// <summary>
/// The type of policy.
/// </summary>
[Required]
public PolicyType? Type { get; set; }
Id = policy.Id;
Type = policy.Type;
Enabled = policy.Enabled;
if (!string.IsNullOrWhiteSpace(policy.Data))
{
Data = JsonSerializer.Deserialize<Dictionary<string, object>>(policy.Data);
}
}
/// <summary>
/// String representing the object's type. Objects of the same type share the same properties.
/// </summary>
/// <example>policy</example>
[Required]
public string Object => "policy";
/// <summary>
/// The policy's unique identifier.
/// </summary>
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
[Required]
public Guid Id { get; set; }
/// <summary>
/// The type of policy.
/// </summary>
[Required]
public PolicyType? Type { get; set; }
}

View File

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

View File

@ -1,20 +1,19 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class EmailRequestModel : SecretVerificationRequestModel
{
public class EmailRequestModel : SecretVerificationRequestModel
{
[Required]
[StrictEmailAddress]
[StringLength(256)]
public string NewEmail { get; set; }
[Required]
[StringLength(300)]
public string NewMasterPasswordHash { get; set; }
[Required]
public string Token { get; set; }
[Required]
public string Key { get; set; }
}
[Required]
[StrictEmailAddress]
[StringLength(256)]
public string NewEmail { get; set; }
[Required]
[StringLength(300)]
public string NewMasterPasswordHash { get; set; }
[Required]
public string Token { get; set; }
[Required]
public string Key { get; set; }
}

View File

@ -1,13 +1,12 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class EmailTokenRequestModel : SecretVerificationRequestModel
{
public class EmailTokenRequestModel : SecretVerificationRequestModel
{
[Required]
[StrictEmailAddress]
[StringLength(256)]
public string NewEmail { get; set; }
}
[Required]
[StrictEmailAddress]
[StringLength(256)]
public string NewEmail { get; set; }
}

View File

@ -1,9 +1,8 @@
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class ImportCiphersRequestModel
{
public class ImportCiphersRequestModel
{
public FolderRequestModel[] Folders { get; set; }
public CipherRequestModel[] Ciphers { get; set; }
public KeyValuePair<int, int>[] FolderRelationships { get; set; }
}
public FolderRequestModel[] Folders { get; set; }
public CipherRequestModel[] Ciphers { get; set; }
public KeyValuePair<int, int>[] FolderRelationships { get; set; }
}

View File

@ -1,30 +1,29 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Enums;
namespace Bit.Api.Models.Request.Accounts
{
public class KdfRequestModel : PasswordRequestModel, IValidatableObject
{
[Required]
public KdfType? Kdf { get; set; }
[Required]
public int? KdfIterations { get; set; }
namespace Bit.Api.Models.Request.Accounts;
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
public class KdfRequestModel : PasswordRequestModel, IValidatableObject
{
[Required]
public KdfType? Kdf { get; set; }
[Required]
public int? KdfIterations { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Kdf.HasValue && KdfIterations.HasValue)
{
if (Kdf.HasValue && KdfIterations.HasValue)
switch (Kdf.Value)
{
switch (Kdf.Value)
{
case KdfType.PBKDF2_SHA256:
if (KdfIterations.Value < 5000 || KdfIterations.Value > 2_000_000)
{
yield return new ValidationResult("KDF iterations must be between 5000 and 2000000.");
}
break;
default:
break;
}
case KdfType.PBKDF2_SHA256:
if (KdfIterations.Value < 5000 || KdfIterations.Value > 2_000_000)
{
yield return new ValidationResult("KDF iterations must be between 5000 and 2000000.");
}
break;
default:
break;
}
}
}

View File

@ -1,9 +1,8 @@
using Bit.Core.Enums;
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class OrganizationApiKeyRequestModel : SecretVerificationRequestModel
{
public class OrganizationApiKeyRequestModel : SecretVerificationRequestModel
{
public OrganizationApiKeyType Type { get; set; }
}
public OrganizationApiKeyType Type { get; set; }
}

View File

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

View File

@ -1,15 +1,14 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class PasswordRequestModel : SecretVerificationRequestModel
{
public class PasswordRequestModel : SecretVerificationRequestModel
{
[Required]
[StringLength(300)]
public string NewMasterPasswordHash { get; set; }
[StringLength(50)]
public string MasterPasswordHint { get; set; }
[Required]
public string Key { get; set; }
}
[Required]
[StringLength(300)]
public string NewMasterPasswordHash { get; set; }
[StringLength(50)]
public string MasterPasswordHint { get; set; }
[Required]
public string Key { get; set; }
}

View File

@ -2,41 +2,40 @@
using Bit.Core.Settings;
using Enums = Bit.Core.Enums;
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class PremiumRequestModel : IValidatableObject
{
public class PremiumRequestModel : IValidatableObject
[Required]
public Enums.PaymentMethodType? PaymentMethodType { get; set; }
public string PaymentToken { get; set; }
[Range(0, 99)]
public short? AdditionalStorageGb { get; set; }
public IFormFile License { get; set; }
public string Country { get; set; }
public string PostalCode { get; set; }
public bool Validate(GlobalSettings globalSettings)
{
[Required]
public Enums.PaymentMethodType? PaymentMethodType { get; set; }
public string PaymentToken { get; set; }
[Range(0, 99)]
public short? AdditionalStorageGb { get; set; }
public IFormFile License { get; set; }
public string Country { get; set; }
public string PostalCode { get; set; }
public bool Validate(GlobalSettings globalSettings)
if (!(License == null && !globalSettings.SelfHosted) ||
(License != null && globalSettings.SelfHosted))
{
if (!(License == null && !globalSettings.SelfHosted) ||
(License != null && globalSettings.SelfHosted))
{
return false;
}
return globalSettings.SelfHosted || !string.IsNullOrWhiteSpace(Country);
return false;
}
return globalSettings.SelfHosted || !string.IsNullOrWhiteSpace(Country);
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var creditType = PaymentMethodType.HasValue && PaymentMethodType.Value == Enums.PaymentMethodType.Credit;
if (string.IsNullOrWhiteSpace(PaymentToken) && !creditType && License == null)
{
var creditType = PaymentMethodType.HasValue && PaymentMethodType.Value == Enums.PaymentMethodType.Credit;
if (string.IsNullOrWhiteSpace(PaymentToken) && !creditType && License == null)
{
yield return new ValidationResult("Payment token or license is required.");
}
if (Country == "US" && string.IsNullOrWhiteSpace(PostalCode))
{
yield return new ValidationResult("Zip / postal code is required.",
new string[] { nameof(PostalCode) });
}
yield return new ValidationResult("Payment token or license is required.");
}
if (Country == "US" && string.IsNullOrWhiteSpace(PostalCode))
{
yield return new ValidationResult("Zip / postal code is required.",
new string[] { nameof(PostalCode) });
}
}
}

View File

@ -1,13 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class RegenerateTwoFactorRequestModel
{
public class RegenerateTwoFactorRequestModel
{
[Required]
public string MasterPasswordHash { get; set; }
[Required]
[StringLength(50)]
public string Token { get; set; }
}
[Required]
public string MasterPasswordHash { get; set; }
[Required]
[StringLength(50)]
public string Token { get; set; }
}

View File

@ -1,20 +1,19 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Accounts
{
public class SecretVerificationRequestModel : IValidatableObject
{
[StringLength(300)]
public string MasterPasswordHash { get; set; }
public string OTP { get; set; }
public string Secret => !string.IsNullOrEmpty(MasterPasswordHash) ? MasterPasswordHash : OTP;
namespace Bit.Api.Models.Request.Accounts;
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
public class SecretVerificationRequestModel : IValidatableObject
{
[StringLength(300)]
public string MasterPasswordHash { get; set; }
public string OTP { get; set; }
public string Secret => !string.IsNullOrEmpty(MasterPasswordHash) ? MasterPasswordHash : OTP;
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrEmpty(Secret))
{
if (string.IsNullOrEmpty(Secret))
{
yield return new ValidationResult("MasterPasswordHash or OTP must be supplied.");
}
yield return new ValidationResult("MasterPasswordHash or OTP must be supplied.");
}
}
}

View File

@ -3,28 +3,27 @@ using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Api.Request.Accounts;
namespace Bit.Api.Models.Request.Accounts
{
public class SetKeyConnectorKeyRequestModel
{
[Required]
public string Key { get; set; }
[Required]
public KeysRequestModel Keys { get; set; }
[Required]
public KdfType Kdf { get; set; }
[Required]
public int KdfIterations { get; set; }
[Required]
public string OrgIdentifier { get; set; }
namespace Bit.Api.Models.Request.Accounts;
public User ToUser(User existingUser)
{
existingUser.Kdf = Kdf;
existingUser.KdfIterations = KdfIterations;
existingUser.Key = Key;
Keys.ToUser(existingUser);
return existingUser;
}
public class SetKeyConnectorKeyRequestModel
{
[Required]
public string Key { get; set; }
[Required]
public KeysRequestModel Keys { get; set; }
[Required]
public KdfType Kdf { get; set; }
[Required]
public int KdfIterations { get; set; }
[Required]
public string OrgIdentifier { get; set; }
public User ToUser(User existingUser)
{
existingUser.Kdf = Kdf;
existingUser.KdfIterations = KdfIterations;
existingUser.Key = Key;
Keys.ToUser(existingUser);
return existingUser;
}
}

View File

@ -3,33 +3,32 @@ using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Api.Request.Accounts;
namespace Bit.Api.Models.Request.Accounts
{
public class SetPasswordRequestModel
{
[Required]
[StringLength(300)]
public string MasterPasswordHash { get; set; }
[Required]
public string Key { get; set; }
[StringLength(50)]
public string MasterPasswordHint { get; set; }
[Required]
public KeysRequestModel Keys { get; set; }
[Required]
public KdfType Kdf { get; set; }
[Required]
public int KdfIterations { get; set; }
public string OrgIdentifier { get; set; }
namespace Bit.Api.Models.Request.Accounts;
public User ToUser(User existingUser)
{
existingUser.MasterPasswordHint = MasterPasswordHint;
existingUser.Kdf = Kdf;
existingUser.KdfIterations = KdfIterations;
existingUser.Key = Key;
Keys.ToUser(existingUser);
return existingUser;
}
public class SetPasswordRequestModel
{
[Required]
[StringLength(300)]
public string MasterPasswordHash { get; set; }
[Required]
public string Key { get; set; }
[StringLength(50)]
public string MasterPasswordHint { get; set; }
[Required]
public KeysRequestModel Keys { get; set; }
[Required]
public KdfType Kdf { get; set; }
[Required]
public int KdfIterations { get; set; }
public string OrgIdentifier { get; set; }
public User ToUser(User existingUser)
{
existingUser.MasterPasswordHint = MasterPasswordHint;
existingUser.Kdf = Kdf;
existingUser.KdfIterations = KdfIterations;
existingUser.Key = Key;
Keys.ToUser(existingUser);
return existingUser;
}
}

View File

@ -1,19 +1,18 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Accounts
{
public class StorageRequestModel : IValidatableObject
{
[Required]
public short? StorageGbAdjustment { get; set; }
namespace Bit.Api.Models.Request.Accounts;
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
public class StorageRequestModel : IValidatableObject
{
[Required]
public short? StorageGbAdjustment { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (StorageGbAdjustment == 0)
{
if (StorageGbAdjustment == 0)
{
yield return new ValidationResult("Storage adjustment cannot be 0.",
new string[] { nameof(StorageGbAdjustment) });
}
yield return new ValidationResult("Storage adjustment cannot be 0.",
new string[] { nameof(StorageGbAdjustment) });
}
}
}

View File

@ -1,20 +1,19 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Accounts
{
public class TaxInfoUpdateRequestModel : IValidatableObject
{
[Required]
public string Country { get; set; }
public string PostalCode { get; set; }
namespace Bit.Api.Models.Request.Accounts;
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
public class TaxInfoUpdateRequestModel : IValidatableObject
{
[Required]
public string Country { get; set; }
public string PostalCode { get; set; }
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Country == "US" && string.IsNullOrWhiteSpace(PostalCode))
{
if (Country == "US" && string.IsNullOrWhiteSpace(PostalCode))
{
yield return new ValidationResult("Zip / postal code is required.",
new string[] { nameof(PostalCode) });
}
yield return new ValidationResult("Zip / postal code is required.",
new string[] { nameof(PostalCode) });
}
}
}

View File

@ -1,20 +1,19 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class UpdateKeyRequestModel
{
public class UpdateKeyRequestModel
{
[Required]
[StringLength(300)]
public string MasterPasswordHash { get; set; }
[Required]
public IEnumerable<CipherWithIdRequestModel> Ciphers { get; set; }
[Required]
public IEnumerable<FolderWithIdRequestModel> Folders { get; set; }
public IEnumerable<SendWithIdRequestModel> Sends { get; set; }
[Required]
public string PrivateKey { get; set; }
[Required]
public string Key { get; set; }
}
[Required]
[StringLength(300)]
public string MasterPasswordHash { get; set; }
[Required]
public IEnumerable<CipherWithIdRequestModel> Ciphers { get; set; }
[Required]
public IEnumerable<FolderWithIdRequestModel> Folders { get; set; }
public IEnumerable<SendWithIdRequestModel> Sends { get; set; }
[Required]
public string PrivateKey { get; set; }
[Required]
public string Key { get; set; }
}

View File

@ -1,21 +1,20 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Entities;
namespace Bit.Api.Models.Request.Accounts
{
public class UpdateProfileRequestModel
{
[StringLength(50)]
public string Name { get; set; }
[StringLength(50)]
[Obsolete("Changes will be made via the 'password' endpoint going forward.")]
public string MasterPasswordHint { get; set; }
namespace Bit.Api.Models.Request.Accounts;
public User ToUser(User existingUser)
{
existingUser.Name = Name;
existingUser.MasterPasswordHint = string.IsNullOrWhiteSpace(MasterPasswordHint) ? null : MasterPasswordHint;
return existingUser;
}
public class UpdateProfileRequestModel
{
[StringLength(50)]
public string Name { get; set; }
[StringLength(50)]
[Obsolete("Changes will be made via the 'password' endpoint going forward.")]
public string MasterPasswordHint { get; set; }
public User ToUser(User existingUser)
{
existingUser.Name = Name;
existingUser.MasterPasswordHint = string.IsNullOrWhiteSpace(MasterPasswordHint) ? null : MasterPasswordHint;
return existingUser;
}
}

View File

@ -1,11 +1,10 @@
using System.ComponentModel.DataAnnotations;
using Bit.Api.Models.Request.Organizations;
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class UpdateTempPasswordRequestModel : OrganizationUserResetPasswordRequestModel
{
public class UpdateTempPasswordRequestModel : OrganizationUserResetPasswordRequestModel
{
[StringLength(50)]
public string MasterPasswordHint { get; set; }
}
[StringLength(50)]
public string MasterPasswordHint { get; set; }
}

View File

@ -1,12 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class VerifyDeleteRecoverRequestModel
{
public class VerifyDeleteRecoverRequestModel
{
[Required]
public string UserId { get; set; }
[Required]
public string Token { get; set; }
}
[Required]
public string UserId { get; set; }
[Required]
public string Token { get; set; }
}

View File

@ -1,12 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class VerifyEmailRequestModel
{
public class VerifyEmailRequestModel
{
[Required]
public string UserId { get; set; }
[Required]
public string Token { get; set; }
}
[Required]
public string UserId { get; set; }
[Required]
public string Token { get; set; }
}

View File

@ -1,10 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Accounts
namespace Bit.Api.Models.Request.Accounts;
public class VerifyOTPRequestModel
{
public class VerifyOTPRequestModel
{
[Required]
public string OTP { get; set; }
}
[Required]
public string OTP { get; set; }
}

View File

@ -1,10 +1,9 @@
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class AttachmentRequestModel
{
public class AttachmentRequestModel
{
public string Key { get; set; }
public string FileName { get; set; }
public long FileSize { get; set; }
public bool AdminRequest { get; set; } = false;
}
public string Key { get; set; }
public string FileName { get; set; }
public long FileSize { get; set; }
public bool AdminRequest { get; set; } = false;
}

View File

@ -1,66 +1,65 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Settings;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class BitPayInvoiceRequestModel : IValidatableObject
{
public class BitPayInvoiceRequestModel : IValidatableObject
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public bool Credit { get; set; }
[Required]
public decimal? Amount { get; set; }
public string ReturnUrl { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public BitPayLight.Models.Invoice.Invoice ToBitpayInvoice(GlobalSettings globalSettings)
{
public Guid? UserId { get; set; }
public Guid? OrganizationId { get; set; }
public bool Credit { get; set; }
[Required]
public decimal? Amount { get; set; }
public string ReturnUrl { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public BitPayLight.Models.Invoice.Invoice ToBitpayInvoice(GlobalSettings globalSettings)
var inv = new BitPayLight.Models.Invoice.Invoice
{
var inv = new BitPayLight.Models.Invoice.Invoice
Price = Convert.ToDouble(Amount.Value),
Currency = "USD",
RedirectUrl = ReturnUrl,
Buyer = new BitPayLight.Models.Invoice.Buyer
{
Price = Convert.ToDouble(Amount.Value),
Currency = "USD",
RedirectUrl = ReturnUrl,
Buyer = new BitPayLight.Models.Invoice.Buyer
{
Email = Email,
Name = Name
},
NotificationUrl = globalSettings.BitPay.NotificationUrl,
FullNotifications = true,
ExtendedNotifications = true
};
Email = Email,
Name = Name
},
NotificationUrl = globalSettings.BitPay.NotificationUrl,
FullNotifications = true,
ExtendedNotifications = true
};
var posData = string.Empty;
if (UserId.HasValue)
{
posData = "userId:" + UserId.Value;
}
else if (OrganizationId.HasValue)
{
posData = "organizationId:" + OrganizationId.Value;
}
if (Credit)
{
posData += ",accountCredit:1";
inv.ItemDesc = "Bitwarden Account Credit";
}
else
{
inv.ItemDesc = "Bitwarden";
}
inv.PosData = posData;
return inv;
var posData = string.Empty;
if (UserId.HasValue)
{
posData = "userId:" + UserId.Value;
}
else if (OrganizationId.HasValue)
{
posData = "organizationId:" + OrganizationId.Value;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
if (Credit)
{
if (!UserId.HasValue && !OrganizationId.HasValue)
{
yield return new ValidationResult("User or Ooganization is required.");
}
posData += ",accountCredit:1";
inv.ItemDesc = "Bitwarden Account Credit";
}
else
{
inv.ItemDesc = "Bitwarden";
}
inv.PosData = posData;
return inv;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!UserId.HasValue && !OrganizationId.HasValue)
{
yield return new ValidationResult("User or Ooganization is required.");
}
}
}

View File

@ -1,11 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class CipherPartialRequestModel
{
public class CipherPartialRequestModel
{
[StringLength(36)]
public string FolderId { get; set; }
public bool Favorite { get; set; }
}
[StringLength(36)]
public string FolderId { get; set; }
public bool Favorite { get; set; }
}

View File

@ -8,342 +8,341 @@ using Core.Models.Data;
using NS = Newtonsoft.Json;
using NSL = Newtonsoft.Json.Linq;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class CipherRequestModel
{
public class CipherRequestModel
public CipherType Type { get; set; }
[StringLength(36)]
public string OrganizationId { get; set; }
public string FolderId { get; set; }
public bool Favorite { get; set; }
public CipherRepromptType Reprompt { get; set; }
[Required]
[EncryptedString]
[EncryptedStringLength(1000)]
public string Name { get; set; }
[EncryptedString]
[EncryptedStringLength(10000)]
public string Notes { get; set; }
public IEnumerable<CipherFieldModel> Fields { get; set; }
public IEnumerable<CipherPasswordHistoryModel> PasswordHistory { get; set; }
[Obsolete]
public Dictionary<string, string> Attachments { get; set; }
// TODO: Rename to Attachments whenever the above is finally removed.
public Dictionary<string, CipherAttachmentModel> Attachments2 { get; set; }
public CipherLoginModel Login { get; set; }
public CipherCardModel Card { get; set; }
public CipherIdentityModel Identity { get; set; }
public CipherSecureNoteModel SecureNote { get; set; }
public DateTime? LastKnownRevisionDate { get; set; } = null;
public CipherDetails ToCipherDetails(Guid userId, bool allowOrgIdSet = true)
{
public CipherType Type { get; set; }
[StringLength(36)]
public string OrganizationId { get; set; }
public string FolderId { get; set; }
public bool Favorite { get; set; }
public CipherRepromptType Reprompt { get; set; }
[Required]
[EncryptedString]
[EncryptedStringLength(1000)]
public string Name { get; set; }
[EncryptedString]
[EncryptedStringLength(10000)]
public string Notes { get; set; }
public IEnumerable<CipherFieldModel> Fields { get; set; }
public IEnumerable<CipherPasswordHistoryModel> PasswordHistory { get; set; }
[Obsolete]
public Dictionary<string, string> Attachments { get; set; }
// TODO: Rename to Attachments whenever the above is finally removed.
public Dictionary<string, CipherAttachmentModel> Attachments2 { get; set; }
public CipherLoginModel Login { get; set; }
public CipherCardModel Card { get; set; }
public CipherIdentityModel Identity { get; set; }
public CipherSecureNoteModel SecureNote { get; set; }
public DateTime? LastKnownRevisionDate { get; set; } = null;
public CipherDetails ToCipherDetails(Guid userId, bool allowOrgIdSet = true)
var hasOrgId = !string.IsNullOrWhiteSpace(OrganizationId);
var cipher = new CipherDetails
{
var hasOrgId = !string.IsNullOrWhiteSpace(OrganizationId);
var cipher = new CipherDetails
{
Type = Type,
UserId = !hasOrgId ? (Guid?)userId : null,
OrganizationId = allowOrgIdSet && hasOrgId ? new Guid(OrganizationId) : (Guid?)null,
Edit = true,
ViewPassword = true,
};
ToCipherDetails(cipher);
return cipher;
Type = Type,
UserId = !hasOrgId ? (Guid?)userId : null,
OrganizationId = allowOrgIdSet && hasOrgId ? new Guid(OrganizationId) : (Guid?)null,
Edit = true,
ViewPassword = true,
};
ToCipherDetails(cipher);
return cipher;
}
public CipherDetails ToCipherDetails(CipherDetails existingCipher)
{
existingCipher.FolderId = string.IsNullOrWhiteSpace(FolderId) ? null : (Guid?)new Guid(FolderId);
existingCipher.Favorite = Favorite;
ToCipher(existingCipher);
return existingCipher;
}
public Cipher ToCipher(Cipher existingCipher)
{
switch (existingCipher.Type)
{
case CipherType.Login:
var loginObj = NSL.JObject.FromObject(ToCipherLoginData(),
new NS.JsonSerializer { NullValueHandling = NS.NullValueHandling.Ignore });
// TODO: Switch to JsonNode in .NET 6 https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-use-dom-utf8jsonreader-utf8jsonwriter?pivots=dotnet-6-0
loginObj[nameof(CipherLoginData.Uri)]?.Parent?.Remove();
existingCipher.Data = loginObj.ToString(NS.Formatting.None);
break;
case CipherType.Card:
existingCipher.Data = JsonSerializer.Serialize(ToCipherCardData(), JsonHelpers.IgnoreWritingNull);
break;
case CipherType.Identity:
existingCipher.Data = JsonSerializer.Serialize(ToCipherIdentityData(), JsonHelpers.IgnoreWritingNull);
break;
case CipherType.SecureNote:
existingCipher.Data = JsonSerializer.Serialize(ToCipherSecureNoteData(), JsonHelpers.IgnoreWritingNull);
break;
default:
throw new ArgumentException("Unsupported type: " + nameof(Type) + ".");
}
public CipherDetails ToCipherDetails(CipherDetails existingCipher)
existingCipher.Reprompt = Reprompt;
var hasAttachments2 = (Attachments2?.Count ?? 0) > 0;
var hasAttachments = (Attachments?.Count ?? 0) > 0;
if (!hasAttachments2 && !hasAttachments)
{
existingCipher.FolderId = string.IsNullOrWhiteSpace(FolderId) ? null : (Guid?)new Guid(FolderId);
existingCipher.Favorite = Favorite;
ToCipher(existingCipher);
return existingCipher;
}
public Cipher ToCipher(Cipher existingCipher)
var attachments = existingCipher.GetAttachments();
if ((attachments?.Count ?? 0) == 0)
{
switch (existingCipher.Type)
{
case CipherType.Login:
var loginObj = NSL.JObject.FromObject(ToCipherLoginData(),
new NS.JsonSerializer { NullValueHandling = NS.NullValueHandling.Ignore });
// TODO: Switch to JsonNode in .NET 6 https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-use-dom-utf8jsonreader-utf8jsonwriter?pivots=dotnet-6-0
loginObj[nameof(CipherLoginData.Uri)]?.Parent?.Remove();
existingCipher.Data = loginObj.ToString(NS.Formatting.None);
break;
case CipherType.Card:
existingCipher.Data = JsonSerializer.Serialize(ToCipherCardData(), JsonHelpers.IgnoreWritingNull);
break;
case CipherType.Identity:
existingCipher.Data = JsonSerializer.Serialize(ToCipherIdentityData(), JsonHelpers.IgnoreWritingNull);
break;
case CipherType.SecureNote:
existingCipher.Data = JsonSerializer.Serialize(ToCipherSecureNoteData(), JsonHelpers.IgnoreWritingNull);
break;
default:
throw new ArgumentException("Unsupported type: " + nameof(Type) + ".");
}
existingCipher.Reprompt = Reprompt;
var hasAttachments2 = (Attachments2?.Count ?? 0) > 0;
var hasAttachments = (Attachments?.Count ?? 0) > 0;
if (!hasAttachments2 && !hasAttachments)
{
return existingCipher;
}
var attachments = existingCipher.GetAttachments();
if ((attachments?.Count ?? 0) == 0)
{
return existingCipher;
}
if (hasAttachments2)
{
foreach (var attachment in attachments.Where(a => Attachments2.ContainsKey(a.Key)))
{
var attachment2 = Attachments2[attachment.Key];
attachment.Value.FileName = attachment2.FileName;
attachment.Value.Key = attachment2.Key;
}
}
else if (hasAttachments)
{
foreach (var attachment in attachments.Where(a => Attachments.ContainsKey(a.Key)))
{
attachment.Value.FileName = Attachments[attachment.Key];
attachment.Value.Key = null;
}
}
existingCipher.SetAttachments(attachments);
return existingCipher;
}
public Cipher ToOrganizationCipher()
if (hasAttachments2)
{
if (string.IsNullOrWhiteSpace(OrganizationId))
foreach (var attachment in attachments.Where(a => Attachments2.ContainsKey(a.Key)))
{
throw new ArgumentNullException(nameof(OrganizationId));
}
return ToCipher(new Cipher
{
Type = Type,
OrganizationId = new Guid(OrganizationId)
});
}
public CipherDetails ToOrganizationCipherDetails(Guid orgId)
{
return ToCipherDetails(new CipherDetails
{
Type = Type,
OrganizationId = orgId,
Edit = true
});
}
private CipherLoginData ToCipherLoginData()
{
return new CipherLoginData
{
Name = Name,
Notes = Notes,
Fields = Fields?.Select(f => f.ToCipherFieldData()),
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
Uris =
Login.Uris?.Where(u => u != null)
.Select(u => u.ToCipherLoginUriData()),
Username = Login.Username,
Password = Login.Password,
PasswordRevisionDate = Login.PasswordRevisionDate,
Totp = Login.Totp,
AutofillOnPageLoad = Login.AutofillOnPageLoad,
};
}
private CipherIdentityData ToCipherIdentityData()
{
return new CipherIdentityData
{
Name = Name,
Notes = Notes,
Fields = Fields?.Select(f => f.ToCipherFieldData()),
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
Title = Identity.Title,
FirstName = Identity.FirstName,
MiddleName = Identity.MiddleName,
LastName = Identity.LastName,
Address1 = Identity.Address1,
Address2 = Identity.Address2,
Address3 = Identity.Address3,
City = Identity.City,
State = Identity.State,
PostalCode = Identity.PostalCode,
Country = Identity.Country,
Company = Identity.Company,
Email = Identity.Email,
Phone = Identity.Phone,
SSN = Identity.SSN,
Username = Identity.Username,
PassportNumber = Identity.PassportNumber,
LicenseNumber = Identity.LicenseNumber,
};
}
private CipherCardData ToCipherCardData()
{
return new CipherCardData
{
Name = Name,
Notes = Notes,
Fields = Fields?.Select(f => f.ToCipherFieldData()),
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
CardholderName = Card.CardholderName,
Brand = Card.Brand,
Number = Card.Number,
ExpMonth = Card.ExpMonth,
ExpYear = Card.ExpYear,
Code = Card.Code,
};
}
private CipherSecureNoteData ToCipherSecureNoteData()
{
return new CipherSecureNoteData
{
Name = Name,
Notes = Notes,
Fields = Fields?.Select(f => f.ToCipherFieldData()),
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
Type = SecureNote.Type,
};
}
}
public class CipherWithIdRequestModel : CipherRequestModel
{
[Required]
public Guid? Id { get; set; }
}
public class CipherCreateRequestModel : IValidatableObject
{
public IEnumerable<Guid> CollectionIds { get; set; }
[Required]
public CipherRequestModel Cipher { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!string.IsNullOrWhiteSpace(Cipher.OrganizationId) && (!CollectionIds?.Any() ?? true))
{
yield return new ValidationResult("You must select at least one collection.",
new string[] { nameof(CollectionIds) });
var attachment2 = Attachments2[attachment.Key];
attachment.Value.FileName = attachment2.FileName;
attachment.Value.Key = attachment2.Key;
}
}
}
public class CipherShareRequestModel : IValidatableObject
{
[Required]
public IEnumerable<string> CollectionIds { get; set; }
[Required]
public CipherRequestModel Cipher { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
else if (hasAttachments)
{
if (string.IsNullOrWhiteSpace(Cipher.OrganizationId))
foreach (var attachment in attachments.Where(a => Attachments.ContainsKey(a.Key)))
{
yield return new ValidationResult("Cipher OrganizationId is required.",
new string[] { nameof(Cipher.OrganizationId) });
}
if (!CollectionIds?.Any() ?? true)
{
yield return new ValidationResult("You must select at least one collection.",
new string[] { nameof(CollectionIds) });
attachment.Value.FileName = Attachments[attachment.Key];
attachment.Value.Key = null;
}
}
existingCipher.SetAttachments(attachments);
return existingCipher;
}
public class CipherCollectionsRequestModel
public Cipher ToOrganizationCipher()
{
[Required]
public IEnumerable<string> CollectionIds { get; set; }
}
public class CipherBulkDeleteRequestModel
{
[Required]
public IEnumerable<string> Ids { get; set; }
public string OrganizationId { get; set; }
}
public class CipherBulkRestoreRequestModel
{
[Required]
public IEnumerable<string> Ids { get; set; }
}
public class CipherBulkMoveRequestModel
{
[Required]
public IEnumerable<string> Ids { get; set; }
public string FolderId { get; set; }
}
public class CipherBulkShareRequestModel : IValidatableObject
{
[Required]
public IEnumerable<string> CollectionIds { get; set; }
[Required]
public IEnumerable<CipherWithIdRequestModel> Ciphers { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
if (string.IsNullOrWhiteSpace(OrganizationId))
{
if (!Ciphers?.Any() ?? true)
{
yield return new ValidationResult("You must select at least one cipher.",
new string[] { nameof(Ciphers) });
}
else
{
var allHaveIds = true;
var organizationIds = new HashSet<string>();
foreach (var c in Ciphers)
{
organizationIds.Add(c.OrganizationId);
if (allHaveIds)
{
allHaveIds = !(!c.Id.HasValue || string.IsNullOrWhiteSpace(c.OrganizationId));
}
}
throw new ArgumentNullException(nameof(OrganizationId));
}
if (!allHaveIds)
{
yield return new ValidationResult("All Ciphers must have an Id and OrganizationId.",
new string[] { nameof(Ciphers) });
}
else if (organizationIds.Count != 1)
{
yield return new ValidationResult("All ciphers must be for the same organization.");
}
}
return ToCipher(new Cipher
{
Type = Type,
OrganizationId = new Guid(OrganizationId)
});
}
if (!CollectionIds?.Any() ?? true)
{
yield return new ValidationResult("You must select at least one collection.",
new string[] { nameof(CollectionIds) });
}
public CipherDetails ToOrganizationCipherDetails(Guid orgId)
{
return ToCipherDetails(new CipherDetails
{
Type = Type,
OrganizationId = orgId,
Edit = true
});
}
private CipherLoginData ToCipherLoginData()
{
return new CipherLoginData
{
Name = Name,
Notes = Notes,
Fields = Fields?.Select(f => f.ToCipherFieldData()),
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
Uris =
Login.Uris?.Where(u => u != null)
.Select(u => u.ToCipherLoginUriData()),
Username = Login.Username,
Password = Login.Password,
PasswordRevisionDate = Login.PasswordRevisionDate,
Totp = Login.Totp,
AutofillOnPageLoad = Login.AutofillOnPageLoad,
};
}
private CipherIdentityData ToCipherIdentityData()
{
return new CipherIdentityData
{
Name = Name,
Notes = Notes,
Fields = Fields?.Select(f => f.ToCipherFieldData()),
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
Title = Identity.Title,
FirstName = Identity.FirstName,
MiddleName = Identity.MiddleName,
LastName = Identity.LastName,
Address1 = Identity.Address1,
Address2 = Identity.Address2,
Address3 = Identity.Address3,
City = Identity.City,
State = Identity.State,
PostalCode = Identity.PostalCode,
Country = Identity.Country,
Company = Identity.Company,
Email = Identity.Email,
Phone = Identity.Phone,
SSN = Identity.SSN,
Username = Identity.Username,
PassportNumber = Identity.PassportNumber,
LicenseNumber = Identity.LicenseNumber,
};
}
private CipherCardData ToCipherCardData()
{
return new CipherCardData
{
Name = Name,
Notes = Notes,
Fields = Fields?.Select(f => f.ToCipherFieldData()),
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
CardholderName = Card.CardholderName,
Brand = Card.Brand,
Number = Card.Number,
ExpMonth = Card.ExpMonth,
ExpYear = Card.ExpYear,
Code = Card.Code,
};
}
private CipherSecureNoteData ToCipherSecureNoteData()
{
return new CipherSecureNoteData
{
Name = Name,
Notes = Notes,
Fields = Fields?.Select(f => f.ToCipherFieldData()),
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
Type = SecureNote.Type,
};
}
}
public class CipherWithIdRequestModel : CipherRequestModel
{
[Required]
public Guid? Id { get; set; }
}
public class CipherCreateRequestModel : IValidatableObject
{
public IEnumerable<Guid> CollectionIds { get; set; }
[Required]
public CipherRequestModel Cipher { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!string.IsNullOrWhiteSpace(Cipher.OrganizationId) && (!CollectionIds?.Any() ?? true))
{
yield return new ValidationResult("You must select at least one collection.",
new string[] { nameof(CollectionIds) });
}
}
}
public class CipherShareRequestModel : IValidatableObject
{
[Required]
public IEnumerable<string> CollectionIds { get; set; }
[Required]
public CipherRequestModel Cipher { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrWhiteSpace(Cipher.OrganizationId))
{
yield return new ValidationResult("Cipher OrganizationId is required.",
new string[] { nameof(Cipher.OrganizationId) });
}
if (!CollectionIds?.Any() ?? true)
{
yield return new ValidationResult("You must select at least one collection.",
new string[] { nameof(CollectionIds) });
}
}
}
public class CipherCollectionsRequestModel
{
[Required]
public IEnumerable<string> CollectionIds { get; set; }
}
public class CipherBulkDeleteRequestModel
{
[Required]
public IEnumerable<string> Ids { get; set; }
public string OrganizationId { get; set; }
}
public class CipherBulkRestoreRequestModel
{
[Required]
public IEnumerable<string> Ids { get; set; }
}
public class CipherBulkMoveRequestModel
{
[Required]
public IEnumerable<string> Ids { get; set; }
public string FolderId { get; set; }
}
public class CipherBulkShareRequestModel : IValidatableObject
{
[Required]
public IEnumerable<string> CollectionIds { get; set; }
[Required]
public IEnumerable<CipherWithIdRequestModel> Ciphers { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!Ciphers?.Any() ?? true)
{
yield return new ValidationResult("You must select at least one cipher.",
new string[] { nameof(Ciphers) });
}
else
{
var allHaveIds = true;
var organizationIds = new HashSet<string>();
foreach (var c in Ciphers)
{
organizationIds.Add(c.OrganizationId);
if (allHaveIds)
{
allHaveIds = !(!c.Id.HasValue || string.IsNullOrWhiteSpace(c.OrganizationId));
}
}
if (!allHaveIds)
{
yield return new ValidationResult("All Ciphers must have an Id and OrganizationId.",
new string[] { nameof(Ciphers) });
}
else if (organizationIds.Count != 1)
{
yield return new ValidationResult("All ciphers must be for the same organization.");
}
}
if (!CollectionIds?.Any() ?? true)
{
yield return new ValidationResult("You must select at least one collection.",
new string[] { nameof(CollectionIds) });
}
}
}

View File

@ -2,31 +2,30 @@
using Bit.Core.Entities;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class CollectionRequestModel
{
public class CollectionRequestModel
[Required]
[EncryptedString]
[EncryptedStringLength(1000)]
public string Name { get; set; }
[StringLength(300)]
public string ExternalId { get; set; }
public IEnumerable<SelectionReadOnlyRequestModel> Groups { get; set; }
public Collection ToCollection(Guid orgId)
{
[Required]
[EncryptedString]
[EncryptedStringLength(1000)]
public string Name { get; set; }
[StringLength(300)]
public string ExternalId { get; set; }
public IEnumerable<SelectionReadOnlyRequestModel> Groups { get; set; }
public Collection ToCollection(Guid orgId)
return ToCollection(new Collection
{
return ToCollection(new Collection
{
OrganizationId = orgId
});
}
OrganizationId = orgId
});
}
public Collection ToCollection(Collection existingCollection)
{
existingCollection.Name = Name;
existingCollection.ExternalId = ExternalId;
return existingCollection;
}
public Collection ToCollection(Collection existingCollection)
{
existingCollection.Name = Name;
existingCollection.ExternalId = ExternalId;
return existingCollection;
}
}

View File

@ -2,49 +2,48 @@
using Bit.Core.Entities;
using Bit.Core.Enums;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class DeviceRequestModel
{
public class DeviceRequestModel
[Required]
public DeviceType? Type { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[StringLength(50)]
public string Identifier { get; set; }
[StringLength(255)]
public string PushToken { get; set; }
public Device ToDevice(Guid? userId = null)
{
[Required]
public DeviceType? Type { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[StringLength(50)]
public string Identifier { get; set; }
[StringLength(255)]
public string PushToken { get; set; }
public Device ToDevice(Guid? userId = null)
return ToDevice(new Device
{
return ToDevice(new Device
{
UserId = userId == null ? default(Guid) : userId.Value
});
}
public Device ToDevice(Device existingDevice)
{
existingDevice.Name = Name;
existingDevice.Identifier = Identifier;
existingDevice.PushToken = PushToken;
existingDevice.Type = Type.Value;
return existingDevice;
}
UserId = userId == null ? default(Guid) : userId.Value
});
}
public class DeviceTokenRequestModel
public Device ToDevice(Device existingDevice)
{
[StringLength(255)]
public string PushToken { get; set; }
existingDevice.Name = Name;
existingDevice.Identifier = Identifier;
existingDevice.PushToken = PushToken;
existingDevice.Type = Type.Value;
public Device ToDevice(Device existingDevice)
{
existingDevice.PushToken = PushToken;
return existingDevice;
}
return existingDevice;
}
}
public class DeviceTokenRequestModel
{
[StringLength(255)]
public string PushToken { get; set; }
public Device ToDevice(Device existingDevice)
{
existingDevice.PushToken = PushToken;
return existingDevice;
}
}

View File

@ -1,17 +1,16 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Entities;
namespace Bit.Api.Models.Request
{
public class DeviceVerificationRequestModel
{
[Required]
public bool UnknownDeviceVerificationEnabled { get; set; }
namespace Bit.Api.Models.Request;
public User ToUser(User user)
{
user.UnknownDeviceVerificationEnabled = UnknownDeviceVerificationEnabled;
return user;
}
public class DeviceVerificationRequestModel
{
[Required]
public bool UnknownDeviceVerificationEnabled { get; set; }
public User ToUser(User user)
{
user.UnknownDeviceVerificationEnabled = UnknownDeviceVerificationEnabled;
return user;
}
}

View File

@ -3,47 +3,46 @@ using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class EmergencyAccessInviteRequestModel
{
public class EmergencyAccessInviteRequestModel
{
[Required]
[StrictEmailAddress]
[StringLength(256)]
public string Email { get; set; }
[Required]
public EmergencyAccessType? Type { get; set; }
[Required]
public int WaitTimeDays { get; set; }
}
[Required]
[StrictEmailAddress]
[StringLength(256)]
public string Email { get; set; }
[Required]
public EmergencyAccessType? Type { get; set; }
[Required]
public int WaitTimeDays { get; set; }
}
public class EmergencyAccessUpdateRequestModel
{
[Required]
public EmergencyAccessType Type { get; set; }
[Required]
public int WaitTimeDays { get; set; }
public string KeyEncrypted { get; set; }
public class EmergencyAccessUpdateRequestModel
{
[Required]
public EmergencyAccessType Type { get; set; }
[Required]
public int WaitTimeDays { get; set; }
public string KeyEncrypted { get; set; }
public EmergencyAccess ToEmergencyAccess(EmergencyAccess existingEmergencyAccess)
public EmergencyAccess ToEmergencyAccess(EmergencyAccess existingEmergencyAccess)
{
// Ensure we only set keys for a confirmed emergency access.
if (!string.IsNullOrWhiteSpace(existingEmergencyAccess.KeyEncrypted) && !string.IsNullOrWhiteSpace(KeyEncrypted))
{
// Ensure we only set keys for a confirmed emergency access.
if (!string.IsNullOrWhiteSpace(existingEmergencyAccess.KeyEncrypted) && !string.IsNullOrWhiteSpace(KeyEncrypted))
{
existingEmergencyAccess.KeyEncrypted = KeyEncrypted;
}
existingEmergencyAccess.Type = Type;
existingEmergencyAccess.WaitTimeDays = WaitTimeDays;
return existingEmergencyAccess;
existingEmergencyAccess.KeyEncrypted = KeyEncrypted;
}
}
public class EmergencyAccessPasswordRequestModel
{
[Required]
[StringLength(300)]
public string NewMasterPasswordHash { get; set; }
[Required]
public string Key { get; set; }
existingEmergencyAccess.Type = Type;
existingEmergencyAccess.WaitTimeDays = WaitTimeDays;
return existingEmergencyAccess;
}
}
public class EmergencyAccessPasswordRequestModel
{
[Required]
[StringLength(300)]
public string NewMasterPasswordHash { get; set; }
[Required]
public string Key { get; set; }
}

View File

@ -2,32 +2,31 @@
using Bit.Core.Entities;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class FolderRequestModel
{
public class FolderRequestModel
[Required]
[EncryptedString]
[EncryptedStringLength(1000)]
public string Name { get; set; }
public Folder ToFolder(Guid userId)
{
[Required]
[EncryptedString]
[EncryptedStringLength(1000)]
public string Name { get; set; }
public Folder ToFolder(Guid userId)
return ToFolder(new Folder
{
return ToFolder(new Folder
{
UserId = userId
});
}
public Folder ToFolder(Folder existingFolder)
{
existingFolder.Name = Name;
return existingFolder;
}
UserId = userId
});
}
public class FolderWithIdRequestModel : FolderRequestModel
public Folder ToFolder(Folder existingFolder)
{
public Guid Id { get; set; }
existingFolder.Name = Name;
return existingFolder;
}
}
public class FolderWithIdRequestModel : FolderRequestModel
{
public Guid Id { get; set; }
}

View File

@ -1,33 +1,32 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Entities;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class GroupRequestModel
{
public class GroupRequestModel
[Required]
[StringLength(100)]
public string Name { get; set; }
[Required]
public bool? AccessAll { get; set; }
[StringLength(300)]
public string ExternalId { get; set; }
public IEnumerable<SelectionReadOnlyRequestModel> Collections { get; set; }
public Group ToGroup(Guid orgId)
{
[Required]
[StringLength(100)]
public string Name { get; set; }
[Required]
public bool? AccessAll { get; set; }
[StringLength(300)]
public string ExternalId { get; set; }
public IEnumerable<SelectionReadOnlyRequestModel> Collections { get; set; }
public Group ToGroup(Guid orgId)
return ToGroup(new Group
{
return ToGroup(new Group
{
OrganizationId = orgId
});
}
OrganizationId = orgId
});
}
public Group ToGroup(Group existingGroup)
{
existingGroup.Name = Name;
existingGroup.AccessAll = AccessAll.Value;
existingGroup.ExternalId = ExternalId;
return existingGroup;
}
public Group ToGroup(Group existingGroup)
{
existingGroup.Name = Name;
existingGroup.AccessAll = AccessAll.Value;
existingGroup.ExternalId = ExternalId;
return existingGroup;
}
}

View File

@ -1,20 +1,19 @@
using System.ComponentModel.DataAnnotations;
using Enums = Bit.Core.Enums;
namespace Bit.Api.Models.Request
{
public class IapCheckRequestModel : IValidatableObject
{
[Required]
public Enums.PaymentMethodType? PaymentMethodType { get; set; }
namespace Bit.Api.Models.Request;
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
public class IapCheckRequestModel : IValidatableObject
{
[Required]
public Enums.PaymentMethodType? PaymentMethodType { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (PaymentMethodType != Enums.PaymentMethodType.AppleInApp)
{
if (PaymentMethodType != Enums.PaymentMethodType.AppleInApp)
{
yield return new ValidationResult("Not a supported in-app purchase payment method.",
new string[] { nameof(PaymentMethodType) });
}
yield return new ValidationResult("Not a supported in-app purchase payment method.",
new string[] { nameof(PaymentMethodType) });
}
}
}

View File

@ -2,23 +2,22 @@
using Bit.Core.Entities;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request
{
public class InstallationRequestModel
{
[Required]
[EmailAddress]
[StringLength(256)]
public string Email { get; set; }
namespace Bit.Api.Models.Request;
public Installation ToInstallation()
public class InstallationRequestModel
{
[Required]
[EmailAddress]
[StringLength(256)]
public string Email { get; set; }
public Installation ToInstallation()
{
return new Installation
{
return new Installation
{
Key = CoreHelpers.SecureRandomString(20),
Email = Email,
Enabled = true
};
}
Key = CoreHelpers.SecureRandomString(20),
Email = Email,
Enabled = true
};
}
}

View File

@ -1,10 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class LicenseRequestModel
{
public class LicenseRequestModel
{
[Required]
public IFormFile License { get; set; }
}
[Required]
public IFormFile License { get; set; }
}

View File

@ -1,9 +1,8 @@
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class ImportOrganizationCiphersRequestModel
{
public class ImportOrganizationCiphersRequestModel
{
public CollectionRequestModel[] Collections { get; set; }
public CipherRequestModel[] Ciphers { get; set; }
public KeyValuePair<int, int>[] CollectionRelationships { get; set; }
}
public CollectionRequestModel[] Collections { get; set; }
public CipherRequestModel[] Ciphers { get; set; }
public KeyValuePair<int, int>[] CollectionRelationships { get; set; }
}

View File

@ -1,69 +1,68 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Models.Business;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class ImportOrganizationUsersRequestModel
{
public class ImportOrganizationUsersRequestModel
public Group[] Groups { get; set; }
public User[] Users { get; set; }
public bool OverwriteExisting { get; set; }
public bool LargeImport { get; set; }
public class Group
{
public Group[] Groups { get; set; }
public User[] Users { get; set; }
public bool OverwriteExisting { get; set; }
public bool LargeImport { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
[Required]
[StringLength(300)]
public string ExternalId { get; set; }
public IEnumerable<string> Users { get; set; }
public class Group
public ImportedGroup ToImportedGroup(Guid organizationId)
{
[Required]
[StringLength(100)]
public string Name { get; set; }
[Required]
[StringLength(300)]
public string ExternalId { get; set; }
public IEnumerable<string> Users { get; set; }
public ImportedGroup ToImportedGroup(Guid organizationId)
var importedGroup = new ImportedGroup
{
var importedGroup = new ImportedGroup
Group = new Core.Entities.Group
{
Group = new Core.Entities.Group
{
OrganizationId = organizationId,
Name = Name,
ExternalId = ExternalId
},
ExternalUserIds = new HashSet<string>(Users)
};
OrganizationId = organizationId,
Name = Name,
ExternalId = ExternalId
},
ExternalUserIds = new HashSet<string>(Users)
};
return importedGroup;
}
return importedGroup;
}
}
public class User : IValidatableObject
{
[EmailAddress]
[StringLength(256)]
public string Email { get; set; }
public bool Deleted { get; set; }
[Required]
[StringLength(300)]
public string ExternalId { get; set; }
public ImportedOrganizationUser ToImportedOrganizationUser()
{
var importedUser = new ImportedOrganizationUser
{
Email = Email.ToLowerInvariant(),
ExternalId = ExternalId
};
return importedUser;
}
public class User : IValidatableObject
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
[EmailAddress]
[StringLength(256)]
public string Email { get; set; }
public bool Deleted { get; set; }
[Required]
[StringLength(300)]
public string ExternalId { get; set; }
public ImportedOrganizationUser ToImportedOrganizationUser()
if (string.IsNullOrWhiteSpace(Email) && !Deleted)
{
var importedUser = new ImportedOrganizationUser
{
Email = Email.ToLowerInvariant(),
ExternalId = ExternalId
};
return importedUser;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrWhiteSpace(Email) && !Deleted)
{
yield return new ValidationResult("Email is required for enabled users.", new string[] { nameof(Email) });
}
yield return new ValidationResult("Email is required for enabled users.", new string[] { nameof(Email) });
}
}
}

View File

@ -4,48 +4,47 @@ using Bit.Core.Exceptions;
using Bit.Core.Models.Data.Organizations.OrganizationConnections;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationConnectionRequestModel
{
public class OrganizationConnectionRequestModel
{
public OrganizationConnectionType Type { get; set; }
public Guid OrganizationId { get; set; }
public bool Enabled { get; set; }
public JsonDocument Config { get; set; }
public OrganizationConnectionType Type { get; set; }
public Guid OrganizationId { get; set; }
public bool Enabled { get; set; }
public JsonDocument Config { get; set; }
public OrganizationConnectionRequestModel() { }
}
public class OrganizationConnectionRequestModel<T> : OrganizationConnectionRequestModel where T : new()
{
public T ParsedConfig { get; private set; }
public OrganizationConnectionRequestModel(OrganizationConnectionRequestModel model)
{
Type = model.Type;
OrganizationId = model.OrganizationId;
Enabled = model.Enabled;
Config = model.Config;
try
{
ParsedConfig = model.Config.ToObject<T>(JsonHelpers.IgnoreCase);
}
catch (JsonException)
{
throw new BadRequestException("Organization Connection configuration malformed");
}
}
public OrganizationConnectionData<T> ToData(Guid? id = null) =>
new()
{
Id = id,
Type = Type,
OrganizationId = OrganizationId,
Enabled = Enabled,
Config = ParsedConfig,
};
}
public OrganizationConnectionRequestModel() { }
}
public class OrganizationConnectionRequestModel<T> : OrganizationConnectionRequestModel where T : new()
{
public T ParsedConfig { get; private set; }
public OrganizationConnectionRequestModel(OrganizationConnectionRequestModel model)
{
Type = model.Type;
OrganizationId = model.OrganizationId;
Enabled = model.Enabled;
Config = model.Config;
try
{
ParsedConfig = model.Config.ToObject<T>(JsonHelpers.IgnoreCase);
}
catch (JsonException)
{
throw new BadRequestException("Organization Connection configuration malformed");
}
}
public OrganizationConnectionData<T> ToData(Guid? id = null) =>
new()
{
Id = id,
Type = Type,
OrganizationId = OrganizationId,
Enabled = Enabled,
Config = ParsedConfig,
};
}

View File

@ -1,15 +1,14 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationCreateLicenseRequestModel : LicenseRequestModel
{
public class OrganizationCreateLicenseRequestModel : LicenseRequestModel
{
[Required]
public string Key { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string CollectionName { get; set; }
public OrganizationKeysRequestModel Keys { get; set; }
}
[Required]
public string Key { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string CollectionName { get; set; }
public OrganizationKeysRequestModel Keys { get; set; }
}

View File

@ -4,99 +4,98 @@ using Bit.Core.Enums;
using Bit.Core.Models.Business;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationCreateRequestModel : IValidatableObject
{
public class OrganizationCreateRequestModel : IValidatableObject
[Required]
[StringLength(50)]
public string Name { get; set; }
[StringLength(50)]
public string BusinessName { get; set; }
[Required]
[StringLength(256)]
[EmailAddress]
public string BillingEmail { get; set; }
public PlanType PlanType { get; set; }
[Required]
public string Key { get; set; }
public OrganizationKeysRequestModel Keys { get; set; }
public PaymentMethodType? PaymentMethodType { get; set; }
public string PaymentToken { get; set; }
[Range(0, int.MaxValue)]
public int AdditionalSeats { get; set; }
[Range(0, 99)]
public short? AdditionalStorageGb { get; set; }
public bool PremiumAccessAddon { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string CollectionName { get; set; }
public string TaxIdNumber { get; set; }
public string BillingAddressLine1 { get; set; }
public string BillingAddressLine2 { get; set; }
public string BillingAddressCity { get; set; }
public string BillingAddressState { get; set; }
public string BillingAddressPostalCode { get; set; }
[StringLength(2)]
public string BillingAddressCountry { get; set; }
public int? MaxAutoscaleSeats { get; set; }
public virtual OrganizationSignup ToOrganizationSignup(User user)
{
[Required]
[StringLength(50)]
public string Name { get; set; }
[StringLength(50)]
public string BusinessName { get; set; }
[Required]
[StringLength(256)]
[EmailAddress]
public string BillingEmail { get; set; }
public PlanType PlanType { get; set; }
[Required]
public string Key { get; set; }
public OrganizationKeysRequestModel Keys { get; set; }
public PaymentMethodType? PaymentMethodType { get; set; }
public string PaymentToken { get; set; }
[Range(0, int.MaxValue)]
public int AdditionalSeats { get; set; }
[Range(0, 99)]
public short? AdditionalStorageGb { get; set; }
public bool PremiumAccessAddon { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string CollectionName { get; set; }
public string TaxIdNumber { get; set; }
public string BillingAddressLine1 { get; set; }
public string BillingAddressLine2 { get; set; }
public string BillingAddressCity { get; set; }
public string BillingAddressState { get; set; }
public string BillingAddressPostalCode { get; set; }
[StringLength(2)]
public string BillingAddressCountry { get; set; }
public int? MaxAutoscaleSeats { get; set; }
public virtual OrganizationSignup ToOrganizationSignup(User user)
var orgSignup = new OrganizationSignup
{
var orgSignup = new OrganizationSignup
Owner = user,
OwnerKey = Key,
Name = Name,
Plan = PlanType,
PaymentMethodType = PaymentMethodType,
PaymentToken = PaymentToken,
AdditionalSeats = AdditionalSeats,
MaxAutoscaleSeats = MaxAutoscaleSeats,
AdditionalStorageGb = AdditionalStorageGb.GetValueOrDefault(0),
PremiumAccessAddon = PremiumAccessAddon,
BillingEmail = BillingEmail,
BusinessName = BusinessName,
CollectionName = CollectionName,
TaxInfo = new TaxInfo
{
Owner = user,
OwnerKey = Key,
Name = Name,
Plan = PlanType,
PaymentMethodType = PaymentMethodType,
PaymentToken = PaymentToken,
AdditionalSeats = AdditionalSeats,
MaxAutoscaleSeats = MaxAutoscaleSeats,
AdditionalStorageGb = AdditionalStorageGb.GetValueOrDefault(0),
PremiumAccessAddon = PremiumAccessAddon,
BillingEmail = BillingEmail,
BusinessName = BusinessName,
CollectionName = CollectionName,
TaxInfo = new TaxInfo
{
TaxIdNumber = TaxIdNumber,
BillingAddressLine1 = BillingAddressLine1,
BillingAddressLine2 = BillingAddressLine2,
BillingAddressCity = BillingAddressCity,
BillingAddressState = BillingAddressState,
BillingAddressPostalCode = BillingAddressPostalCode,
BillingAddressCountry = BillingAddressCountry,
},
};
TaxIdNumber = TaxIdNumber,
BillingAddressLine1 = BillingAddressLine1,
BillingAddressLine2 = BillingAddressLine2,
BillingAddressCity = BillingAddressCity,
BillingAddressState = BillingAddressState,
BillingAddressPostalCode = BillingAddressPostalCode,
BillingAddressCountry = BillingAddressCountry,
},
};
Keys?.ToOrganizationSignup(orgSignup);
Keys?.ToOrganizationSignup(orgSignup);
return orgSignup;
return orgSignup;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (PlanType != PlanType.Free && string.IsNullOrWhiteSpace(PaymentToken))
{
yield return new ValidationResult("Payment required.", new string[] { nameof(PaymentToken) });
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
if (PlanType != PlanType.Free && !PaymentMethodType.HasValue)
{
if (PlanType != PlanType.Free && string.IsNullOrWhiteSpace(PaymentToken))
{
yield return new ValidationResult("Payment required.", new string[] { nameof(PaymentToken) });
}
if (PlanType != PlanType.Free && !PaymentMethodType.HasValue)
{
yield return new ValidationResult("Payment method type required.",
new string[] { nameof(PaymentMethodType) });
}
if (PlanType != PlanType.Free && string.IsNullOrWhiteSpace(BillingAddressCountry))
{
yield return new ValidationResult("Country required.",
new string[] { nameof(BillingAddressCountry) });
}
if (PlanType != PlanType.Free && BillingAddressCountry == "US" &&
string.IsNullOrWhiteSpace(BillingAddressPostalCode))
{
yield return new ValidationResult("Zip / postal code is required.",
new string[] { nameof(BillingAddressPostalCode) });
}
yield return new ValidationResult("Payment method type required.",
new string[] { nameof(PaymentMethodType) });
}
if (PlanType != PlanType.Free && string.IsNullOrWhiteSpace(BillingAddressCountry))
{
yield return new ValidationResult("Country required.",
new string[] { nameof(BillingAddressCountry) });
}
if (PlanType != PlanType.Free && BillingAddressCountry == "US" &&
string.IsNullOrWhiteSpace(BillingAddressPostalCode))
{
yield return new ValidationResult("Zip / postal code is required.",
new string[] { nameof(BillingAddressPostalCode) });
}
}
}

View File

@ -2,58 +2,57 @@
using Bit.Core.Entities;
using Bit.Core.Models.Business;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationKeysRequestModel
{
public class OrganizationKeysRequestModel
[Required]
public string PublicKey { get; set; }
[Required]
public string EncryptedPrivateKey { get; set; }
public OrganizationSignup ToOrganizationSignup(OrganizationSignup existingSignup)
{
[Required]
public string PublicKey { get; set; }
[Required]
public string EncryptedPrivateKey { get; set; }
public OrganizationSignup ToOrganizationSignup(OrganizationSignup existingSignup)
if (string.IsNullOrWhiteSpace(existingSignup.PublicKey))
{
if (string.IsNullOrWhiteSpace(existingSignup.PublicKey))
{
existingSignup.PublicKey = PublicKey;
}
if (string.IsNullOrWhiteSpace(existingSignup.PrivateKey))
{
existingSignup.PrivateKey = EncryptedPrivateKey;
}
return existingSignup;
existingSignup.PublicKey = PublicKey;
}
public OrganizationUpgrade ToOrganizationUpgrade(OrganizationUpgrade existingUpgrade)
if (string.IsNullOrWhiteSpace(existingSignup.PrivateKey))
{
if (string.IsNullOrWhiteSpace(existingUpgrade.PublicKey))
{
existingUpgrade.PublicKey = PublicKey;
}
if (string.IsNullOrWhiteSpace(existingUpgrade.PrivateKey))
{
existingUpgrade.PrivateKey = EncryptedPrivateKey;
}
return existingUpgrade;
existingSignup.PrivateKey = EncryptedPrivateKey;
}
public Organization ToOrganization(Organization existingOrg)
return existingSignup;
}
public OrganizationUpgrade ToOrganizationUpgrade(OrganizationUpgrade existingUpgrade)
{
if (string.IsNullOrWhiteSpace(existingUpgrade.PublicKey))
{
if (string.IsNullOrWhiteSpace(existingOrg.PublicKey))
{
existingOrg.PublicKey = PublicKey;
}
if (string.IsNullOrWhiteSpace(existingOrg.PrivateKey))
{
existingOrg.PrivateKey = EncryptedPrivateKey;
}
return existingOrg;
existingUpgrade.PublicKey = PublicKey;
}
if (string.IsNullOrWhiteSpace(existingUpgrade.PrivateKey))
{
existingUpgrade.PrivateKey = EncryptedPrivateKey;
}
return existingUpgrade;
}
public Organization ToOrganization(Organization existingOrg)
{
if (string.IsNullOrWhiteSpace(existingOrg.PublicKey))
{
existingOrg.PublicKey = PublicKey;
}
if (string.IsNullOrWhiteSpace(existingOrg.PrivateKey))
{
existingOrg.PrivateKey = EncryptedPrivateKey;
}
return existingOrg;
}
}

View File

@ -1,18 +1,17 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Organizations
{
public class OrganizationSeatRequestModel : IValidatableObject
{
[Required]
public int? SeatAdjustment { get; set; }
namespace Bit.Api.Models.Request.Organizations;
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
public class OrganizationSeatRequestModel : IValidatableObject
{
[Required]
public int? SeatAdjustment { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (SeatAdjustment == 0)
{
if (SeatAdjustment == 0)
{
yield return new ValidationResult("Seat adjustment cannot be 0.", new string[] { nameof(SeatAdjustment) });
}
yield return new ValidationResult("Seat adjustment cannot be 0.", new string[] { nameof(SeatAdjustment) });
}
}
}

View File

@ -2,19 +2,18 @@
using Bit.Core.Enums;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationSponsorshipCreateRequestModel
{
public class OrganizationSponsorshipCreateRequestModel
{
[Required]
public PlanSponsorshipType PlanSponsorshipType { get; set; }
[Required]
public PlanSponsorshipType PlanSponsorshipType { get; set; }
[Required]
[StringLength(256)]
[StrictEmailAddress]
public string SponsoredEmail { get; set; }
[Required]
[StringLength(256)]
[StrictEmailAddress]
public string SponsoredEmail { get; set; }
[StringLength(256)]
public string FriendlyName { get; set; }
}
[StringLength(256)]
public string FriendlyName { get; set; }
}

View File

@ -1,13 +1,12 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Enums;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationSponsorshipRedeemRequestModel
{
public class OrganizationSponsorshipRedeemRequestModel
{
[Required]
public PlanSponsorshipType PlanSponsorshipType { get; set; }
[Required]
public Guid SponsoredOrganizationId { get; set; }
}
[Required]
public PlanSponsorshipType PlanSponsorshipType { get; set; }
[Required]
public Guid SponsoredOrganizationId { get; set; }
}

View File

@ -10,216 +10,215 @@ using Bit.Core.Sso;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationSsoRequestModel
{
public class OrganizationSsoRequestModel
[Required]
public bool Enabled { get; set; }
[Required]
public SsoConfigurationDataRequest Data { get; set; }
public SsoConfig ToSsoConfig(Guid organizationId)
{
[Required]
public bool Enabled { get; set; }
[Required]
public SsoConfigurationDataRequest Data { get; set; }
public SsoConfig ToSsoConfig(Guid organizationId)
{
return ToSsoConfig(new SsoConfig { OrganizationId = organizationId });
}
public SsoConfig ToSsoConfig(SsoConfig existingConfig)
{
existingConfig.Enabled = Enabled;
var configurationData = Data.ToConfigurationData();
existingConfig.SetData(configurationData);
return existingConfig;
}
return ToSsoConfig(new SsoConfig { OrganizationId = organizationId });
}
public class SsoConfigurationDataRequest : IValidatableObject
public SsoConfig ToSsoConfig(SsoConfig existingConfig)
{
public SsoConfigurationDataRequest() { }
[Required]
public SsoType ConfigType { get; set; }
public bool KeyConnectorEnabled { get; set; }
public string KeyConnectorUrl { get; set; }
// OIDC
public string Authority { get; set; }
public string ClientId { get; set; }
public string ClientSecret { get; set; }
public string MetadataAddress { get; set; }
public OpenIdConnectRedirectBehavior RedirectBehavior { get; set; }
public bool? GetClaimsFromUserInfoEndpoint { get; set; }
public string AdditionalScopes { get; set; }
public string AdditionalUserIdClaimTypes { get; set; }
public string AdditionalEmailClaimTypes { get; set; }
public string AdditionalNameClaimTypes { get; set; }
public string AcrValues { get; set; }
public string ExpectedReturnAcrValue { get; set; }
// SAML2 SP
public Saml2NameIdFormat SpNameIdFormat { get; set; }
public string SpOutboundSigningAlgorithm { get; set; }
public Saml2SigningBehavior SpSigningBehavior { get; set; }
public bool? SpWantAssertionsSigned { get; set; }
public bool? SpValidateCertificates { get; set; }
public string SpMinIncomingSigningAlgorithm { get; set; }
// SAML2 IDP
public string IdpEntityId { get; set; }
public Saml2BindingType IdpBindingType { get; set; }
public string IdpSingleSignOnServiceUrl { get; set; }
public string IdpSingleLogoutServiceUrl { get; set; }
public string IdpArtifactResolutionServiceUrl { get => null; set { /*IGNORE*/ } }
public string IdpX509PublicCert { get; set; }
public string IdpOutboundSigningAlgorithm { get; set; }
public bool? IdpAllowUnsolicitedAuthnResponse { get; set; }
public bool? IdpDisableOutboundLogoutRequests { get; set; }
public bool? IdpWantAuthnRequestsSigned { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext context)
{
var i18nService = context.GetService(typeof(II18nService)) as I18nService;
if (ConfigType == SsoType.OpenIdConnect)
{
if (string.IsNullOrWhiteSpace(Authority))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("AuthorityValidationError"),
new[] { nameof(Authority) });
}
if (string.IsNullOrWhiteSpace(ClientId))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("ClientIdValidationError"),
new[] { nameof(ClientId) });
}
if (string.IsNullOrWhiteSpace(ClientSecret))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("ClientSecretValidationError"),
new[] { nameof(ClientSecret) });
}
}
else if (ConfigType == SsoType.Saml2)
{
if (string.IsNullOrWhiteSpace(IdpEntityId))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpEntityIdValidationError"),
new[] { nameof(IdpEntityId) });
}
if (!Uri.IsWellFormedUriString(IdpEntityId, UriKind.Absolute) && string.IsNullOrWhiteSpace(IdpSingleSignOnServiceUrl))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleSignOnServiceUrlValidationError"),
new[] { nameof(IdpSingleSignOnServiceUrl) });
}
if (InvalidServiceUrl(IdpSingleSignOnServiceUrl))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleSignOnServiceUrlInvalid"),
new[] { nameof(IdpSingleSignOnServiceUrl) });
}
if (InvalidServiceUrl(IdpSingleLogoutServiceUrl))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleLogoutServiceUrlInvalid"),
new[] { nameof(IdpSingleLogoutServiceUrl) });
}
if (!string.IsNullOrWhiteSpace(IdpX509PublicCert))
{
// Validate the certificate is in a valid format
ValidationResult failedResult = null;
try
{
var certData = CoreHelpers.Base64UrlDecode(StripPemCertificateElements(IdpX509PublicCert));
new X509Certificate2(certData);
}
catch (FormatException)
{
failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertInvalidFormatValidationError"),
new[] { nameof(IdpX509PublicCert) });
}
catch (CryptographicException cryptoEx)
{
failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertCryptographicExceptionValidationError", cryptoEx.Message),
new[] { nameof(IdpX509PublicCert) });
}
catch (Exception ex)
{
failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertValidationError", ex.Message),
new[] { nameof(IdpX509PublicCert) });
}
if (failedResult != null)
{
yield return failedResult;
}
}
}
}
public SsoConfigurationData ToConfigurationData()
{
return new SsoConfigurationData
{
ConfigType = ConfigType,
KeyConnectorEnabled = KeyConnectorEnabled,
KeyConnectorUrl = KeyConnectorUrl,
Authority = Authority,
ClientId = ClientId,
ClientSecret = ClientSecret,
MetadataAddress = MetadataAddress,
GetClaimsFromUserInfoEndpoint = GetClaimsFromUserInfoEndpoint.GetValueOrDefault(),
RedirectBehavior = RedirectBehavior,
IdpEntityId = IdpEntityId,
IdpBindingType = IdpBindingType,
IdpSingleSignOnServiceUrl = IdpSingleSignOnServiceUrl,
IdpSingleLogoutServiceUrl = IdpSingleLogoutServiceUrl,
IdpArtifactResolutionServiceUrl = null,
IdpX509PublicCert = StripPemCertificateElements(IdpX509PublicCert),
IdpOutboundSigningAlgorithm = IdpOutboundSigningAlgorithm,
IdpAllowUnsolicitedAuthnResponse = IdpAllowUnsolicitedAuthnResponse.GetValueOrDefault(),
IdpDisableOutboundLogoutRequests = IdpDisableOutboundLogoutRequests.GetValueOrDefault(),
IdpWantAuthnRequestsSigned = IdpWantAuthnRequestsSigned.GetValueOrDefault(),
SpNameIdFormat = SpNameIdFormat,
SpOutboundSigningAlgorithm = SpOutboundSigningAlgorithm ?? SamlSigningAlgorithms.Sha256,
SpSigningBehavior = SpSigningBehavior,
SpWantAssertionsSigned = SpWantAssertionsSigned.GetValueOrDefault(),
SpValidateCertificates = SpValidateCertificates.GetValueOrDefault(),
SpMinIncomingSigningAlgorithm = SpMinIncomingSigningAlgorithm,
AdditionalScopes = AdditionalScopes,
AdditionalUserIdClaimTypes = AdditionalUserIdClaimTypes,
AdditionalEmailClaimTypes = AdditionalEmailClaimTypes,
AdditionalNameClaimTypes = AdditionalNameClaimTypes,
AcrValues = AcrValues,
ExpectedReturnAcrValue = ExpectedReturnAcrValue,
};
}
private string StripPemCertificateElements(string certificateText)
{
if (string.IsNullOrWhiteSpace(certificateText))
{
return null;
}
return Regex.Replace(certificateText,
@"(((BEGIN|END) CERTIFICATE)|([\-\n\r\t\s\f]))",
string.Empty,
RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
}
private bool InvalidServiceUrl(string url)
{
if (string.IsNullOrWhiteSpace(url))
{
return false;
}
if (!url.StartsWith("http://") && !url.StartsWith("https://"))
{
return true;
}
return Regex.IsMatch(url, "[<>\"]");
}
existingConfig.Enabled = Enabled;
var configurationData = Data.ToConfigurationData();
existingConfig.SetData(configurationData);
return existingConfig;
}
}
public class SsoConfigurationDataRequest : IValidatableObject
{
public SsoConfigurationDataRequest() { }
[Required]
public SsoType ConfigType { get; set; }
public bool KeyConnectorEnabled { get; set; }
public string KeyConnectorUrl { get; set; }
// OIDC
public string Authority { get; set; }
public string ClientId { get; set; }
public string ClientSecret { get; set; }
public string MetadataAddress { get; set; }
public OpenIdConnectRedirectBehavior RedirectBehavior { get; set; }
public bool? GetClaimsFromUserInfoEndpoint { get; set; }
public string AdditionalScopes { get; set; }
public string AdditionalUserIdClaimTypes { get; set; }
public string AdditionalEmailClaimTypes { get; set; }
public string AdditionalNameClaimTypes { get; set; }
public string AcrValues { get; set; }
public string ExpectedReturnAcrValue { get; set; }
// SAML2 SP
public Saml2NameIdFormat SpNameIdFormat { get; set; }
public string SpOutboundSigningAlgorithm { get; set; }
public Saml2SigningBehavior SpSigningBehavior { get; set; }
public bool? SpWantAssertionsSigned { get; set; }
public bool? SpValidateCertificates { get; set; }
public string SpMinIncomingSigningAlgorithm { get; set; }
// SAML2 IDP
public string IdpEntityId { get; set; }
public Saml2BindingType IdpBindingType { get; set; }
public string IdpSingleSignOnServiceUrl { get; set; }
public string IdpSingleLogoutServiceUrl { get; set; }
public string IdpArtifactResolutionServiceUrl { get => null; set { /*IGNORE*/ } }
public string IdpX509PublicCert { get; set; }
public string IdpOutboundSigningAlgorithm { get; set; }
public bool? IdpAllowUnsolicitedAuthnResponse { get; set; }
public bool? IdpDisableOutboundLogoutRequests { get; set; }
public bool? IdpWantAuthnRequestsSigned { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext context)
{
var i18nService = context.GetService(typeof(II18nService)) as I18nService;
if (ConfigType == SsoType.OpenIdConnect)
{
if (string.IsNullOrWhiteSpace(Authority))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("AuthorityValidationError"),
new[] { nameof(Authority) });
}
if (string.IsNullOrWhiteSpace(ClientId))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("ClientIdValidationError"),
new[] { nameof(ClientId) });
}
if (string.IsNullOrWhiteSpace(ClientSecret))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("ClientSecretValidationError"),
new[] { nameof(ClientSecret) });
}
}
else if (ConfigType == SsoType.Saml2)
{
if (string.IsNullOrWhiteSpace(IdpEntityId))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpEntityIdValidationError"),
new[] { nameof(IdpEntityId) });
}
if (!Uri.IsWellFormedUriString(IdpEntityId, UriKind.Absolute) && string.IsNullOrWhiteSpace(IdpSingleSignOnServiceUrl))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleSignOnServiceUrlValidationError"),
new[] { nameof(IdpSingleSignOnServiceUrl) });
}
if (InvalidServiceUrl(IdpSingleSignOnServiceUrl))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleSignOnServiceUrlInvalid"),
new[] { nameof(IdpSingleSignOnServiceUrl) });
}
if (InvalidServiceUrl(IdpSingleLogoutServiceUrl))
{
yield return new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleLogoutServiceUrlInvalid"),
new[] { nameof(IdpSingleLogoutServiceUrl) });
}
if (!string.IsNullOrWhiteSpace(IdpX509PublicCert))
{
// Validate the certificate is in a valid format
ValidationResult failedResult = null;
try
{
var certData = CoreHelpers.Base64UrlDecode(StripPemCertificateElements(IdpX509PublicCert));
new X509Certificate2(certData);
}
catch (FormatException)
{
failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertInvalidFormatValidationError"),
new[] { nameof(IdpX509PublicCert) });
}
catch (CryptographicException cryptoEx)
{
failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertCryptographicExceptionValidationError", cryptoEx.Message),
new[] { nameof(IdpX509PublicCert) });
}
catch (Exception ex)
{
failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertValidationError", ex.Message),
new[] { nameof(IdpX509PublicCert) });
}
if (failedResult != null)
{
yield return failedResult;
}
}
}
}
public SsoConfigurationData ToConfigurationData()
{
return new SsoConfigurationData
{
ConfigType = ConfigType,
KeyConnectorEnabled = KeyConnectorEnabled,
KeyConnectorUrl = KeyConnectorUrl,
Authority = Authority,
ClientId = ClientId,
ClientSecret = ClientSecret,
MetadataAddress = MetadataAddress,
GetClaimsFromUserInfoEndpoint = GetClaimsFromUserInfoEndpoint.GetValueOrDefault(),
RedirectBehavior = RedirectBehavior,
IdpEntityId = IdpEntityId,
IdpBindingType = IdpBindingType,
IdpSingleSignOnServiceUrl = IdpSingleSignOnServiceUrl,
IdpSingleLogoutServiceUrl = IdpSingleLogoutServiceUrl,
IdpArtifactResolutionServiceUrl = null,
IdpX509PublicCert = StripPemCertificateElements(IdpX509PublicCert),
IdpOutboundSigningAlgorithm = IdpOutboundSigningAlgorithm,
IdpAllowUnsolicitedAuthnResponse = IdpAllowUnsolicitedAuthnResponse.GetValueOrDefault(),
IdpDisableOutboundLogoutRequests = IdpDisableOutboundLogoutRequests.GetValueOrDefault(),
IdpWantAuthnRequestsSigned = IdpWantAuthnRequestsSigned.GetValueOrDefault(),
SpNameIdFormat = SpNameIdFormat,
SpOutboundSigningAlgorithm = SpOutboundSigningAlgorithm ?? SamlSigningAlgorithms.Sha256,
SpSigningBehavior = SpSigningBehavior,
SpWantAssertionsSigned = SpWantAssertionsSigned.GetValueOrDefault(),
SpValidateCertificates = SpValidateCertificates.GetValueOrDefault(),
SpMinIncomingSigningAlgorithm = SpMinIncomingSigningAlgorithm,
AdditionalScopes = AdditionalScopes,
AdditionalUserIdClaimTypes = AdditionalUserIdClaimTypes,
AdditionalEmailClaimTypes = AdditionalEmailClaimTypes,
AdditionalNameClaimTypes = AdditionalNameClaimTypes,
AcrValues = AcrValues,
ExpectedReturnAcrValue = ExpectedReturnAcrValue,
};
}
private string StripPemCertificateElements(string certificateText)
{
if (string.IsNullOrWhiteSpace(certificateText))
{
return null;
}
return Regex.Replace(certificateText,
@"(((BEGIN|END) CERTIFICATE)|([\-\n\r\t\s\f]))",
string.Empty,
RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
}
private bool InvalidServiceUrl(string url)
{
if (string.IsNullOrWhiteSpace(url))
{
return false;
}
if (!url.StartsWith("http://") && !url.StartsWith("https://"))
{
return true;
}
return Regex.IsMatch(url, "[<>\"]");
}
}

View File

@ -1,11 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationSubscriptionUpdateRequestModel
{
public class OrganizationSubscriptionUpdateRequestModel
{
[Required]
public int SeatAdjustment { get; set; }
public int? MaxAutoscaleSeats { get; set; }
}
[Required]
public int SeatAdjustment { get; set; }
public int? MaxAutoscaleSeats { get; set; }
}

View File

@ -1,13 +1,12 @@
using Bit.Api.Models.Request.Accounts;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationTaxInfoUpdateRequestModel : TaxInfoUpdateRequestModel
{
public class OrganizationTaxInfoUpdateRequestModel : TaxInfoUpdateRequestModel
{
public string TaxId { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string City { get; set; }
public string State { get; set; }
}
public string TaxId { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string City { get; set; }
public string State { get; set; }
}

View File

@ -3,36 +3,35 @@ using Bit.Core.Entities;
using Bit.Core.Models.Data;
using Bit.Core.Settings;
namespace Bit.Api.Models.Request.Organizations
{
public class OrganizationUpdateRequestModel
{
[Required]
[StringLength(50)]
public string Name { get; set; }
[StringLength(50)]
public string BusinessName { get; set; }
[StringLength(50)]
public string Identifier { get; set; }
[EmailAddress]
[Required]
[StringLength(256)]
public string BillingEmail { get; set; }
public Permissions Permissions { get; set; }
public OrganizationKeysRequestModel Keys { get; set; }
namespace Bit.Api.Models.Request.Organizations;
public virtual Organization ToOrganization(Organization existingOrganization, GlobalSettings globalSettings)
public class OrganizationUpdateRequestModel
{
[Required]
[StringLength(50)]
public string Name { get; set; }
[StringLength(50)]
public string BusinessName { get; set; }
[StringLength(50)]
public string Identifier { get; set; }
[EmailAddress]
[Required]
[StringLength(256)]
public string BillingEmail { get; set; }
public Permissions Permissions { get; set; }
public OrganizationKeysRequestModel Keys { get; set; }
public virtual Organization ToOrganization(Organization existingOrganization, GlobalSettings globalSettings)
{
if (!globalSettings.SelfHosted)
{
if (!globalSettings.SelfHosted)
{
// These items come from the license file
existingOrganization.Name = Name;
existingOrganization.BusinessName = BusinessName;
existingOrganization.BillingEmail = BillingEmail?.ToLowerInvariant()?.Trim();
}
existingOrganization.Identifier = Identifier;
Keys?.ToOrganization(existingOrganization);
return existingOrganization;
// These items come from the license file
existingOrganization.Name = Name;
existingOrganization.BusinessName = BusinessName;
existingOrganization.BillingEmail = BillingEmail?.ToLowerInvariant()?.Trim();
}
existingOrganization.Identifier = Identifier;
Keys?.ToOrganization(existingOrganization);
return existingOrganization;
}
}

View File

@ -2,41 +2,40 @@
using Bit.Core.Enums;
using Bit.Core.Models.Business;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationUpgradeRequestModel
{
public class OrganizationUpgradeRequestModel
[StringLength(50)]
public string BusinessName { get; set; }
public PlanType PlanType { get; set; }
[Range(0, int.MaxValue)]
public int AdditionalSeats { get; set; }
[Range(0, 99)]
public short? AdditionalStorageGb { get; set; }
public bool PremiumAccessAddon { get; set; }
public string BillingAddressCountry { get; set; }
public string BillingAddressPostalCode { get; set; }
public OrganizationKeysRequestModel Keys { get; set; }
public OrganizationUpgrade ToOrganizationUpgrade()
{
[StringLength(50)]
public string BusinessName { get; set; }
public PlanType PlanType { get; set; }
[Range(0, int.MaxValue)]
public int AdditionalSeats { get; set; }
[Range(0, 99)]
public short? AdditionalStorageGb { get; set; }
public bool PremiumAccessAddon { get; set; }
public string BillingAddressCountry { get; set; }
public string BillingAddressPostalCode { get; set; }
public OrganizationKeysRequestModel Keys { get; set; }
public OrganizationUpgrade ToOrganizationUpgrade()
var orgUpgrade = new OrganizationUpgrade
{
var orgUpgrade = new OrganizationUpgrade
AdditionalSeats = AdditionalSeats,
AdditionalStorageGb = AdditionalStorageGb.GetValueOrDefault(),
BusinessName = BusinessName,
Plan = PlanType,
PremiumAccessAddon = PremiumAccessAddon,
TaxInfo = new TaxInfo()
{
AdditionalSeats = AdditionalSeats,
AdditionalStorageGb = AdditionalStorageGb.GetValueOrDefault(),
BusinessName = BusinessName,
Plan = PlanType,
PremiumAccessAddon = PremiumAccessAddon,
TaxInfo = new TaxInfo()
{
BillingAddressCountry = BillingAddressCountry,
BillingAddressPostalCode = BillingAddressPostalCode
}
};
BillingAddressCountry = BillingAddressCountry,
BillingAddressPostalCode = BillingAddressPostalCode
}
};
Keys?.ToOrganizationUpgrade(orgUpgrade);
Keys?.ToOrganizationUpgrade(orgUpgrade);
return orgUpgrade;
}
return orgUpgrade;
}
}

View File

@ -7,99 +7,98 @@ using Bit.Core.Models.Data;
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationUserInviteRequestModel
{
public class OrganizationUserInviteRequestModel
{
[Required]
[StrictEmailAddressList]
public IEnumerable<string> Emails { get; set; }
[Required]
public OrganizationUserType? Type { get; set; }
public bool AccessAll { get; set; }
public Permissions Permissions { get; set; }
public IEnumerable<SelectionReadOnlyRequestModel> Collections { get; set; }
[Required]
[StrictEmailAddressList]
public IEnumerable<string> Emails { get; set; }
[Required]
public OrganizationUserType? Type { get; set; }
public bool AccessAll { get; set; }
public Permissions Permissions { get; set; }
public IEnumerable<SelectionReadOnlyRequestModel> Collections { get; set; }
public OrganizationUserInviteData ToData()
public OrganizationUserInviteData ToData()
{
return new OrganizationUserInviteData
{
return new OrganizationUserInviteData
{
Emails = Emails,
Type = Type,
AccessAll = AccessAll,
Collections = Collections?.Select(c => c.ToSelectionReadOnly()),
Permissions = Permissions,
};
}
}
public class OrganizationUserAcceptRequestModel
{
[Required]
public string Token { get; set; }
// Used to auto-enroll in master password reset
public string ResetPasswordKey { get; set; }
}
public class OrganizationUserConfirmRequestModel
{
[Required]
public string Key { get; set; }
}
public class OrganizationUserBulkConfirmRequestModelEntry
{
[Required]
public Guid Id { get; set; }
[Required]
public string Key { get; set; }
}
public class OrganizationUserBulkConfirmRequestModel
{
[Required]
public IEnumerable<OrganizationUserBulkConfirmRequestModelEntry> Keys { get; set; }
public Dictionary<Guid, string> ToDictionary()
{
return Keys.ToDictionary(e => e.Id, e => e.Key);
}
}
public class OrganizationUserUpdateRequestModel
{
[Required]
public OrganizationUserType? Type { get; set; }
public bool AccessAll { get; set; }
public Permissions Permissions { get; set; }
public IEnumerable<SelectionReadOnlyRequestModel> Collections { get; set; }
public OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
{
existingUser.Type = Type.Value;
existingUser.Permissions = JsonSerializer.Serialize(Permissions, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
});
existingUser.AccessAll = AccessAll;
return existingUser;
}
}
public class OrganizationUserUpdateGroupsRequestModel
{
[Required]
public IEnumerable<string> GroupIds { get; set; }
}
public class OrganizationUserResetPasswordEnrollmentRequestModel : SecretVerificationRequestModel
{
public string ResetPasswordKey { get; set; }
}
public class OrganizationUserBulkRequestModel
{
[Required]
public IEnumerable<Guid> Ids { get; set; }
Emails = Emails,
Type = Type,
AccessAll = AccessAll,
Collections = Collections?.Select(c => c.ToSelectionReadOnly()),
Permissions = Permissions,
};
}
}
public class OrganizationUserAcceptRequestModel
{
[Required]
public string Token { get; set; }
// Used to auto-enroll in master password reset
public string ResetPasswordKey { get; set; }
}
public class OrganizationUserConfirmRequestModel
{
[Required]
public string Key { get; set; }
}
public class OrganizationUserBulkConfirmRequestModelEntry
{
[Required]
public Guid Id { get; set; }
[Required]
public string Key { get; set; }
}
public class OrganizationUserBulkConfirmRequestModel
{
[Required]
public IEnumerable<OrganizationUserBulkConfirmRequestModelEntry> Keys { get; set; }
public Dictionary<Guid, string> ToDictionary()
{
return Keys.ToDictionary(e => e.Id, e => e.Key);
}
}
public class OrganizationUserUpdateRequestModel
{
[Required]
public OrganizationUserType? Type { get; set; }
public bool AccessAll { get; set; }
public Permissions Permissions { get; set; }
public IEnumerable<SelectionReadOnlyRequestModel> Collections { get; set; }
public OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
{
existingUser.Type = Type.Value;
existingUser.Permissions = JsonSerializer.Serialize(Permissions, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
});
existingUser.AccessAll = AccessAll;
return existingUser;
}
}
public class OrganizationUserUpdateGroupsRequestModel
{
[Required]
public IEnumerable<string> GroupIds { get; set; }
}
public class OrganizationUserResetPasswordEnrollmentRequestModel : SecretVerificationRequestModel
{
public string ResetPasswordKey { get; set; }
}
public class OrganizationUserBulkRequestModel
{
[Required]
public IEnumerable<Guid> Ids { get; set; }
}

View File

@ -1,13 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationUserResetPasswordRequestModel
{
public class OrganizationUserResetPasswordRequestModel
{
[Required]
[StringLength(300)]
public string NewMasterPasswordHash { get; set; }
[Required]
public string Key { get; set; }
}
[Required]
[StringLength(300)]
public string NewMasterPasswordHash { get; set; }
[Required]
public string Key { get; set; }
}

View File

@ -1,14 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Organizations
namespace Bit.Api.Models.Request.Organizations;
public class OrganizationVerifyBankRequestModel
{
public class OrganizationVerifyBankRequestModel
{
[Required]
[Range(1, 99)]
public int? Amount1 { get; set; }
[Required]
[Range(1, 99)]
public int? Amount2 { get; set; }
}
[Required]
[Range(1, 99)]
public int? Amount1 { get; set; }
[Required]
[Range(1, 99)]
public int? Amount2 { get; set; }
}

View File

@ -2,13 +2,12 @@
using Bit.Api.Models.Request.Organizations;
using Bit.Core.Enums;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class PaymentRequestModel : OrganizationTaxInfoUpdateRequestModel
{
public class PaymentRequestModel : OrganizationTaxInfoUpdateRequestModel
{
[Required]
public PaymentMethodType? PaymentMethodType { get; set; }
[Required]
public string PaymentToken { get; set; }
}
[Required]
public PaymentMethodType? PaymentMethodType { get; set; }
[Required]
public string PaymentToken { get; set; }
}

View File

@ -3,30 +3,29 @@ using System.Text.Json;
using Bit.Core.Entities;
using Bit.Core.Enums;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class PolicyRequestModel
{
public class PolicyRequestModel
[Required]
public PolicyType? Type { get; set; }
[Required]
public bool? Enabled { get; set; }
public Dictionary<string, object> Data { get; set; }
public Policy ToPolicy(Guid orgId)
{
[Required]
public PolicyType? Type { get; set; }
[Required]
public bool? Enabled { get; set; }
public Dictionary<string, object> Data { get; set; }
public Policy ToPolicy(Guid orgId)
return ToPolicy(new Policy
{
return ToPolicy(new Policy
{
Type = Type.Value,
OrganizationId = orgId
});
}
Type = Type.Value,
OrganizationId = orgId
});
}
public Policy ToPolicy(Policy existingPolicy)
{
existingPolicy.Enabled = Enabled.GetValueOrDefault();
existingPolicy.Data = Data != null ? JsonSerializer.Serialize(Data) : null;
return existingPolicy;
}
public Policy ToPolicy(Policy existingPolicy)
{
existingPolicy.Enabled = Enabled.GetValueOrDefault();
existingPolicy.Data = Data != null ? JsonSerializer.Serialize(Data) : null;
return existingPolicy;
}
}

View File

@ -1,13 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request.Providers
{
public class ProviderOrganizationAddRequestModel
{
[Required]
public Guid OrganizationId { get; set; }
namespace Bit.Api.Models.Request.Providers;
[Required]
public string Key { get; set; }
}
public class ProviderOrganizationAddRequestModel
{
[Required]
public Guid OrganizationId { get; set; }
[Required]
public string Key { get; set; }
}

View File

@ -2,15 +2,14 @@
using Bit.Api.Models.Request.Organizations;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request.Providers
namespace Bit.Api.Models.Request.Providers;
public class ProviderOrganizationCreateRequestModel
{
public class ProviderOrganizationCreateRequestModel
{
[Required]
[StringLength(256)]
[StrictEmailAddress]
public string ClientOwnerEmail { get; set; }
[Required]
public OrganizationCreateRequestModel OrganizationCreateRequest { get; set; }
}
[Required]
[StringLength(256)]
[StrictEmailAddress]
public string ClientOwnerEmail { get; set; }
[Required]
public OrganizationCreateRequestModel OrganizationCreateRequest { get; set; }
}

View File

@ -1,31 +1,30 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Entities.Provider;
namespace Bit.Api.Models.Request.Providers
namespace Bit.Api.Models.Request.Providers;
public class ProviderSetupRequestModel
{
public class ProviderSetupRequestModel
[Required]
[StringLength(50)]
public string Name { get; set; }
[StringLength(50)]
public string BusinessName { get; set; }
[Required]
[StringLength(256)]
[EmailAddress]
public string BillingEmail { get; set; }
[Required]
public string Token { get; set; }
[Required]
public string Key { get; set; }
public virtual Provider ToProvider(Provider provider)
{
[Required]
[StringLength(50)]
public string Name { get; set; }
[StringLength(50)]
public string BusinessName { get; set; }
[Required]
[StringLength(256)]
[EmailAddress]
public string BillingEmail { get; set; }
[Required]
public string Token { get; set; }
[Required]
public string Key { get; set; }
provider.Name = Name;
provider.BusinessName = BusinessName;
provider.BillingEmail = BillingEmail;
public virtual Provider ToProvider(Provider provider)
{
provider.Name = Name;
provider.BusinessName = BusinessName;
provider.BillingEmail = BillingEmail;
return provider;
}
return provider;
}
}

View File

@ -2,30 +2,29 @@
using Bit.Core.Entities.Provider;
using Bit.Core.Settings;
namespace Bit.Api.Models.Request.Providers
{
public class ProviderUpdateRequestModel
{
[Required]
[StringLength(50)]
public string Name { get; set; }
[StringLength(50)]
public string BusinessName { get; set; }
[EmailAddress]
[Required]
[StringLength(256)]
public string BillingEmail { get; set; }
namespace Bit.Api.Models.Request.Providers;
public virtual Provider ToProvider(Provider existingProvider, GlobalSettings globalSettings)
public class ProviderUpdateRequestModel
{
[Required]
[StringLength(50)]
public string Name { get; set; }
[StringLength(50)]
public string BusinessName { get; set; }
[EmailAddress]
[Required]
[StringLength(256)]
public string BillingEmail { get; set; }
public virtual Provider ToProvider(Provider existingProvider, GlobalSettings globalSettings)
{
if (!globalSettings.SelfHosted)
{
if (!globalSettings.SelfHosted)
{
// These items come from the license file
existingProvider.Name = Name;
existingProvider.BusinessName = BusinessName;
existingProvider.BillingEmail = BillingEmail?.ToLowerInvariant()?.Trim();
}
return existingProvider;
// These items come from the license file
existingProvider.Name = Name;
existingProvider.BusinessName = BusinessName;
existingProvider.BillingEmail = BillingEmail?.ToLowerInvariant()?.Trim();
}
return existingProvider;
}
}

View File

@ -3,63 +3,62 @@ using Bit.Core.Entities.Provider;
using Bit.Core.Enums.Provider;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request.Providers
namespace Bit.Api.Models.Request.Providers;
public class ProviderUserInviteRequestModel
{
public class ProviderUserInviteRequestModel
[Required]
[StrictEmailAddressList]
public IEnumerable<string> Emails { get; set; }
[Required]
public ProviderUserType? Type { get; set; }
}
public class ProviderUserAcceptRequestModel
{
[Required]
public string Token { get; set; }
}
public class ProviderUserConfirmRequestModel
{
[Required]
public string Key { get; set; }
}
public class ProviderUserBulkConfirmRequestModelEntry
{
[Required]
public Guid Id { get; set; }
[Required]
public string Key { get; set; }
}
public class ProviderUserBulkConfirmRequestModel
{
[Required]
public IEnumerable<ProviderUserBulkConfirmRequestModelEntry> Keys { get; set; }
public Dictionary<Guid, string> ToDictionary()
{
[Required]
[StrictEmailAddressList]
public IEnumerable<string> Emails { get; set; }
[Required]
public ProviderUserType? Type { get; set; }
}
public class ProviderUserAcceptRequestModel
{
[Required]
public string Token { get; set; }
}
public class ProviderUserConfirmRequestModel
{
[Required]
public string Key { get; set; }
}
public class ProviderUserBulkConfirmRequestModelEntry
{
[Required]
public Guid Id { get; set; }
[Required]
public string Key { get; set; }
}
public class ProviderUserBulkConfirmRequestModel
{
[Required]
public IEnumerable<ProviderUserBulkConfirmRequestModelEntry> Keys { get; set; }
public Dictionary<Guid, string> ToDictionary()
{
return Keys.ToDictionary(e => e.Id, e => e.Key);
}
}
public class ProviderUserUpdateRequestModel
{
[Required]
public ProviderUserType? Type { get; set; }
public ProviderUser ToProviderUser(ProviderUser existingUser)
{
existingUser.Type = Type.Value;
return existingUser;
}
}
public class ProviderUserBulkRequestModel
{
[Required]
public IEnumerable<Guid> Ids { get; set; }
return Keys.ToDictionary(e => e.Id, e => e.Key);
}
}
public class ProviderUserUpdateRequestModel
{
[Required]
public ProviderUserType? Type { get; set; }
public ProviderUser ToProviderUser(ProviderUser existingUser)
{
existingUser.Type = Type.Value;
return existingUser;
}
}
public class ProviderUserBulkRequestModel
{
[Required]
public IEnumerable<Guid> Ids { get; set; }
}

View File

@ -1,23 +1,22 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Models.Data;
namespace Bit.Api.Models.Request
{
public class SelectionReadOnlyRequestModel
{
[Required]
public string Id { get; set; }
public bool ReadOnly { get; set; }
public bool HidePasswords { get; set; }
namespace Bit.Api.Models.Request;
public SelectionReadOnly ToSelectionReadOnly()
public class SelectionReadOnlyRequestModel
{
[Required]
public string Id { get; set; }
public bool ReadOnly { get; set; }
public bool HidePasswords { get; set; }
public SelectionReadOnly ToSelectionReadOnly()
{
return new SelectionReadOnly
{
return new SelectionReadOnly
{
Id = new Guid(Id),
ReadOnly = ReadOnly,
HidePasswords = HidePasswords,
};
}
Id = new Guid(Id),
ReadOnly = ReadOnly,
HidePasswords = HidePasswords,
};
}
}

View File

@ -1,10 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class SendAccessRequestModel
{
public class SendAccessRequestModel
{
[StringLength(300)]
public string Password { get; set; }
}
[StringLength(300)]
public string Password { get; set; }
}

View File

@ -7,135 +7,134 @@ using Bit.Core.Models.Data;
using Bit.Core.Services;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class SendRequestModel
{
public class SendRequestModel
public SendType Type { get; set; }
public long? FileLength { get; set; } = null;
[EncryptedString]
[EncryptedStringLength(1000)]
public string Name { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Notes { get; set; }
[Required]
[EncryptedString]
[EncryptedStringLength(1000)]
public string Key { get; set; }
[Range(1, int.MaxValue)]
public int? MaxAccessCount { get; set; }
public DateTime? ExpirationDate { get; set; }
[Required]
public DateTime? DeletionDate { get; set; }
public SendFileModel File { get; set; }
public SendTextModel Text { get; set; }
[StringLength(1000)]
public string Password { get; set; }
[Required]
public bool? Disabled { get; set; }
public bool? HideEmail { get; set; }
public Send ToSend(Guid userId, ISendService sendService)
{
public SendType Type { get; set; }
public long? FileLength { get; set; } = null;
[EncryptedString]
[EncryptedStringLength(1000)]
public string Name { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Notes { get; set; }
[Required]
[EncryptedString]
[EncryptedStringLength(1000)]
public string Key { get; set; }
[Range(1, int.MaxValue)]
public int? MaxAccessCount { get; set; }
public DateTime? ExpirationDate { get; set; }
[Required]
public DateTime? DeletionDate { get; set; }
public SendFileModel File { get; set; }
public SendTextModel Text { get; set; }
[StringLength(1000)]
public string Password { get; set; }
[Required]
public bool? Disabled { get; set; }
public bool? HideEmail { get; set; }
public Send ToSend(Guid userId, ISendService sendService)
var send = new Send
{
var send = new Send
{
Type = Type,
UserId = (Guid?)userId
};
ToSend(send, sendService);
return send;
Type = Type,
UserId = (Guid?)userId
};
ToSend(send, sendService);
return send;
}
public (Send, SendFileData) ToSend(Guid userId, string fileName, ISendService sendService)
{
var send = ToSendBase(new Send
{
Type = Type,
UserId = (Guid?)userId
}, sendService);
var data = new SendFileData(Name, Notes, fileName);
return (send, data);
}
public Send ToSend(Send existingSend, ISendService sendService)
{
existingSend = ToSendBase(existingSend, sendService);
switch (existingSend.Type)
{
case SendType.File:
var fileData = JsonSerializer.Deserialize<SendFileData>(existingSend.Data);
fileData.Name = Name;
fileData.Notes = Notes;
existingSend.Data = JsonSerializer.Serialize(fileData, JsonHelpers.IgnoreWritingNull);
break;
case SendType.Text:
existingSend.Data = JsonSerializer.Serialize(ToSendTextData(), JsonHelpers.IgnoreWritingNull);
break;
default:
throw new ArgumentException("Unsupported type: " + nameof(Type) + ".");
}
return existingSend;
}
public (Send, SendFileData) ToSend(Guid userId, string fileName, ISendService sendService)
public void ValidateCreation()
{
var now = DateTime.UtcNow;
// Add 1 minute for a sane buffer and client clock float
var nowPlus1Minute = now.AddMinutes(1);
if (ExpirationDate.HasValue && ExpirationDate.Value <= nowPlus1Minute)
{
var send = ToSendBase(new Send
{
Type = Type,
UserId = (Guid?)userId
}, sendService);
var data = new SendFileData(Name, Notes, fileName);
return (send, data);
throw new BadRequestException("You cannot create a Send that is already expired. " +
"Adjust the expiration date and try again.");
}
ValidateEdit();
}
public Send ToSend(Send existingSend, ISendService sendService)
public void ValidateEdit()
{
var now = DateTime.UtcNow;
// Add 1 minute for a sane buffer and client clock float
var nowPlus1Minute = now.AddMinutes(1);
if (DeletionDate.HasValue)
{
existingSend = ToSendBase(existingSend, sendService);
switch (existingSend.Type)
if (DeletionDate.Value <= nowPlus1Minute)
{
case SendType.File:
var fileData = JsonSerializer.Deserialize<SendFileData>(existingSend.Data);
fileData.Name = Name;
fileData.Notes = Notes;
existingSend.Data = JsonSerializer.Serialize(fileData, JsonHelpers.IgnoreWritingNull);
break;
case SendType.Text:
existingSend.Data = JsonSerializer.Serialize(ToSendTextData(), JsonHelpers.IgnoreWritingNull);
break;
default:
throw new ArgumentException("Unsupported type: " + nameof(Type) + ".");
throw new BadRequestException("You cannot have a Send with a deletion date in the past. " +
"Adjust the deletion date and try again.");
}
return existingSend;
}
public void ValidateCreation()
{
var now = DateTime.UtcNow;
// Add 1 minute for a sane buffer and client clock float
var nowPlus1Minute = now.AddMinutes(1);
if (ExpirationDate.HasValue && ExpirationDate.Value <= nowPlus1Minute)
if (DeletionDate.Value > now.AddDays(31))
{
throw new BadRequestException("You cannot create a Send that is already expired. " +
"Adjust the expiration date and try again.");
throw new BadRequestException("You cannot have a Send with a deletion date that far " +
"into the future. Adjust the Deletion Date to a value less than 31 days from now " +
"and try again.");
}
ValidateEdit();
}
public void ValidateEdit()
{
var now = DateTime.UtcNow;
// Add 1 minute for a sane buffer and client clock float
var nowPlus1Minute = now.AddMinutes(1);
if (DeletionDate.HasValue)
{
if (DeletionDate.Value <= nowPlus1Minute)
{
throw new BadRequestException("You cannot have a Send with a deletion date in the past. " +
"Adjust the deletion date and try again.");
}
if (DeletionDate.Value > now.AddDays(31))
{
throw new BadRequestException("You cannot have a Send with a deletion date that far " +
"into the future. Adjust the Deletion Date to a value less than 31 days from now " +
"and try again.");
}
}
}
private Send ToSendBase(Send existingSend, ISendService sendService)
{
existingSend.Key = Key;
existingSend.ExpirationDate = ExpirationDate;
existingSend.DeletionDate = DeletionDate.Value;
existingSend.MaxAccessCount = MaxAccessCount;
if (!string.IsNullOrWhiteSpace(Password))
{
existingSend.Password = sendService.HashPassword(Password);
}
existingSend.Disabled = Disabled.GetValueOrDefault();
existingSend.HideEmail = HideEmail.GetValueOrDefault();
return existingSend;
}
private SendTextData ToSendTextData()
{
return new SendTextData(Name, Notes, Text.Text, Text.Hidden);
}
}
public class SendWithIdRequestModel : SendRequestModel
private Send ToSendBase(Send existingSend, ISendService sendService)
{
[Required]
public Guid? Id { get; set; }
existingSend.Key = Key;
existingSend.ExpirationDate = ExpirationDate;
existingSend.DeletionDate = DeletionDate.Value;
existingSend.MaxAccessCount = MaxAccessCount;
if (!string.IsNullOrWhiteSpace(Password))
{
existingSend.Password = sendService.HashPassword(Password);
}
existingSend.Disabled = Disabled.GetValueOrDefault();
existingSend.HideEmail = HideEmail.GetValueOrDefault();
return existingSend;
}
private SendTextData ToSendTextData()
{
return new SendTextData(Name, Notes, Text.Text, Text.Hidden);
}
}
public class SendWithIdRequestModel : SendRequestModel
{
[Required]
public Guid? Id { get; set; }
}

View File

@ -5,270 +5,269 @@ using Bit.Core.Enums;
using Bit.Core.Models;
using Fido2NetLib;
namespace Bit.Api.Models.Request
namespace Bit.Api.Models.Request;
public class UpdateTwoFactorAuthenticatorRequestModel : SecretVerificationRequestModel
{
public class UpdateTwoFactorAuthenticatorRequestModel : SecretVerificationRequestModel
[Required]
[StringLength(50)]
public string Token { get; set; }
[Required]
[StringLength(50)]
public string Key { get; set; }
public User ToUser(User extistingUser)
{
[Required]
[StringLength(50)]
public string Token { get; set; }
[Required]
[StringLength(50)]
public string Key { get; set; }
public User ToUser(User extistingUser)
var providers = extistingUser.GetTwoFactorProviders();
if (providers == null)
{
var providers = extistingUser.GetTwoFactorProviders();
if (providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
else if (providers.ContainsKey(TwoFactorProviderType.Authenticator))
{
providers.Remove(TwoFactorProviderType.Authenticator);
}
providers.Add(TwoFactorProviderType.Authenticator, new TwoFactorProvider
{
MetaData = new Dictionary<string, object> { ["Key"] = Key },
Enabled = true
});
extistingUser.SetTwoFactorProviders(providers);
return extistingUser;
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
}
public class UpdateTwoFactorDuoRequestModel : SecretVerificationRequestModel, IValidatableObject
{
[Required]
[StringLength(50)]
public string IntegrationKey { get; set; }
[Required]
[StringLength(50)]
public string SecretKey { get; set; }
[Required]
[StringLength(50)]
public string Host { get; set; }
public User ToUser(User extistingUser)
else if (providers.ContainsKey(TwoFactorProviderType.Authenticator))
{
var providers = extistingUser.GetTwoFactorProviders();
if (providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
else if (providers.ContainsKey(TwoFactorProviderType.Duo))
{
providers.Remove(TwoFactorProviderType.Duo);
}
providers.Add(TwoFactorProviderType.Duo, new TwoFactorProvider
{
MetaData = new Dictionary<string, object>
{
["SKey"] = SecretKey,
["IKey"] = IntegrationKey,
["Host"] = Host
},
Enabled = true
});
extistingUser.SetTwoFactorProviders(providers);
return extistingUser;
providers.Remove(TwoFactorProviderType.Authenticator);
}
public Organization ToOrganization(Organization extistingOrg)
providers.Add(TwoFactorProviderType.Authenticator, new TwoFactorProvider
{
var providers = extistingOrg.GetTwoFactorProviders();
if (providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
else if (providers.ContainsKey(TwoFactorProviderType.OrganizationDuo))
{
providers.Remove(TwoFactorProviderType.OrganizationDuo);
}
providers.Add(TwoFactorProviderType.OrganizationDuo, new TwoFactorProvider
{
MetaData = new Dictionary<string, object>
{
["SKey"] = SecretKey,
["IKey"] = IntegrationKey,
["Host"] = Host
},
Enabled = true
});
extistingOrg.SetTwoFactorProviders(providers);
return extistingOrg;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!Core.Utilities.Duo.DuoApi.ValidHost(Host))
{
yield return new ValidationResult("Host is invalid.", new string[] { nameof(Host) });
}
}
}
public class UpdateTwoFactorYubicoOtpRequestModel : SecretVerificationRequestModel, IValidatableObject
{
public string Key1 { get; set; }
public string Key2 { get; set; }
public string Key3 { get; set; }
public string Key4 { get; set; }
public string Key5 { get; set; }
[Required]
public bool? Nfc { get; set; }
public User ToUser(User extistingUser)
{
var providers = extistingUser.GetTwoFactorProviders();
if (providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
else if (providers.ContainsKey(TwoFactorProviderType.YubiKey))
{
providers.Remove(TwoFactorProviderType.YubiKey);
}
providers.Add(TwoFactorProviderType.YubiKey, new TwoFactorProvider
{
MetaData = new Dictionary<string, object>
{
["Key1"] = FormatKey(Key1),
["Key2"] = FormatKey(Key2),
["Key3"] = FormatKey(Key3),
["Key4"] = FormatKey(Key4),
["Key5"] = FormatKey(Key5),
["Nfc"] = Nfc.Value
},
Enabled = true
});
extistingUser.SetTwoFactorProviders(providers);
return extistingUser;
}
private string FormatKey(string keyValue)
{
if (string.IsNullOrWhiteSpace(keyValue))
{
return null;
}
return keyValue.Substring(0, 12);
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrWhiteSpace(Key1) && string.IsNullOrWhiteSpace(Key2) && string.IsNullOrWhiteSpace(Key3) &&
string.IsNullOrWhiteSpace(Key4) && string.IsNullOrWhiteSpace(Key5))
{
yield return new ValidationResult("A key is required.", new string[] { nameof(Key1) });
}
if (!string.IsNullOrWhiteSpace(Key1) && Key1.Length < 12)
{
yield return new ValidationResult("Key 1 in invalid.", new string[] { nameof(Key1) });
}
if (!string.IsNullOrWhiteSpace(Key2) && Key2.Length < 12)
{
yield return new ValidationResult("Key 2 in invalid.", new string[] { nameof(Key2) });
}
if (!string.IsNullOrWhiteSpace(Key3) && Key3.Length < 12)
{
yield return new ValidationResult("Key 3 in invalid.", new string[] { nameof(Key3) });
}
if (!string.IsNullOrWhiteSpace(Key4) && Key4.Length < 12)
{
yield return new ValidationResult("Key 4 in invalid.", new string[] { nameof(Key4) });
}
if (!string.IsNullOrWhiteSpace(Key5) && Key5.Length < 12)
{
yield return new ValidationResult("Key 5 in invalid.", new string[] { nameof(Key5) });
}
}
}
public class TwoFactorEmailRequestModel : SecretVerificationRequestModel
{
[Required]
[EmailAddress]
[StringLength(256)]
public string Email { get; set; }
public string DeviceIdentifier { get; set; }
public User ToUser(User extistingUser)
{
var providers = extistingUser.GetTwoFactorProviders();
if (providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
else if (providers.ContainsKey(TwoFactorProviderType.Email))
{
providers.Remove(TwoFactorProviderType.Email);
}
providers.Add(TwoFactorProviderType.Email, new TwoFactorProvider
{
MetaData = new Dictionary<string, object> { ["Email"] = Email.ToLowerInvariant() },
Enabled = true
});
extistingUser.SetTwoFactorProviders(providers);
return extistingUser;
}
}
public class TwoFactorWebAuthnRequestModel : TwoFactorWebAuthnDeleteRequestModel
{
[Required]
public AuthenticatorAttestationRawResponse DeviceResponse { get; set; }
public string Name { get; set; }
}
public class TwoFactorWebAuthnDeleteRequestModel : SecretVerificationRequestModel, IValidatableObject
{
[Required]
public int? Id { get; set; }
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
foreach (var validationResult in base.Validate(validationContext))
{
yield return validationResult;
}
if (!Id.HasValue || Id < 0 || Id > 5)
{
yield return new ValidationResult("Invalid Key Id", new string[] { nameof(Id) });
}
}
}
public class UpdateTwoFactorEmailRequestModel : TwoFactorEmailRequestModel
{
[Required]
[StringLength(50)]
public string Token { get; set; }
}
public class TwoFactorProviderRequestModel : SecretVerificationRequestModel
{
[Required]
public TwoFactorProviderType? Type { get; set; }
}
public class TwoFactorRecoveryRequestModel : TwoFactorEmailRequestModel
{
[Required]
[StringLength(32)]
public string RecoveryCode { get; set; }
MetaData = new Dictionary<string, object> { ["Key"] = Key },
Enabled = true
});
extistingUser.SetTwoFactorProviders(providers);
return extistingUser;
}
}
public class UpdateTwoFactorDuoRequestModel : SecretVerificationRequestModel, IValidatableObject
{
[Required]
[StringLength(50)]
public string IntegrationKey { get; set; }
[Required]
[StringLength(50)]
public string SecretKey { get; set; }
[Required]
[StringLength(50)]
public string Host { get; set; }
public User ToUser(User extistingUser)
{
var providers = extistingUser.GetTwoFactorProviders();
if (providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
else if (providers.ContainsKey(TwoFactorProviderType.Duo))
{
providers.Remove(TwoFactorProviderType.Duo);
}
providers.Add(TwoFactorProviderType.Duo, new TwoFactorProvider
{
MetaData = new Dictionary<string, object>
{
["SKey"] = SecretKey,
["IKey"] = IntegrationKey,
["Host"] = Host
},
Enabled = true
});
extistingUser.SetTwoFactorProviders(providers);
return extistingUser;
}
public Organization ToOrganization(Organization extistingOrg)
{
var providers = extistingOrg.GetTwoFactorProviders();
if (providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
else if (providers.ContainsKey(TwoFactorProviderType.OrganizationDuo))
{
providers.Remove(TwoFactorProviderType.OrganizationDuo);
}
providers.Add(TwoFactorProviderType.OrganizationDuo, new TwoFactorProvider
{
MetaData = new Dictionary<string, object>
{
["SKey"] = SecretKey,
["IKey"] = IntegrationKey,
["Host"] = Host
},
Enabled = true
});
extistingOrg.SetTwoFactorProviders(providers);
return extistingOrg;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!Core.Utilities.Duo.DuoApi.ValidHost(Host))
{
yield return new ValidationResult("Host is invalid.", new string[] { nameof(Host) });
}
}
}
public class UpdateTwoFactorYubicoOtpRequestModel : SecretVerificationRequestModel, IValidatableObject
{
public string Key1 { get; set; }
public string Key2 { get; set; }
public string Key3 { get; set; }
public string Key4 { get; set; }
public string Key5 { get; set; }
[Required]
public bool? Nfc { get; set; }
public User ToUser(User extistingUser)
{
var providers = extistingUser.GetTwoFactorProviders();
if (providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
else if (providers.ContainsKey(TwoFactorProviderType.YubiKey))
{
providers.Remove(TwoFactorProviderType.YubiKey);
}
providers.Add(TwoFactorProviderType.YubiKey, new TwoFactorProvider
{
MetaData = new Dictionary<string, object>
{
["Key1"] = FormatKey(Key1),
["Key2"] = FormatKey(Key2),
["Key3"] = FormatKey(Key3),
["Key4"] = FormatKey(Key4),
["Key5"] = FormatKey(Key5),
["Nfc"] = Nfc.Value
},
Enabled = true
});
extistingUser.SetTwoFactorProviders(providers);
return extistingUser;
}
private string FormatKey(string keyValue)
{
if (string.IsNullOrWhiteSpace(keyValue))
{
return null;
}
return keyValue.Substring(0, 12);
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrWhiteSpace(Key1) && string.IsNullOrWhiteSpace(Key2) && string.IsNullOrWhiteSpace(Key3) &&
string.IsNullOrWhiteSpace(Key4) && string.IsNullOrWhiteSpace(Key5))
{
yield return new ValidationResult("A key is required.", new string[] { nameof(Key1) });
}
if (!string.IsNullOrWhiteSpace(Key1) && Key1.Length < 12)
{
yield return new ValidationResult("Key 1 in invalid.", new string[] { nameof(Key1) });
}
if (!string.IsNullOrWhiteSpace(Key2) && Key2.Length < 12)
{
yield return new ValidationResult("Key 2 in invalid.", new string[] { nameof(Key2) });
}
if (!string.IsNullOrWhiteSpace(Key3) && Key3.Length < 12)
{
yield return new ValidationResult("Key 3 in invalid.", new string[] { nameof(Key3) });
}
if (!string.IsNullOrWhiteSpace(Key4) && Key4.Length < 12)
{
yield return new ValidationResult("Key 4 in invalid.", new string[] { nameof(Key4) });
}
if (!string.IsNullOrWhiteSpace(Key5) && Key5.Length < 12)
{
yield return new ValidationResult("Key 5 in invalid.", new string[] { nameof(Key5) });
}
}
}
public class TwoFactorEmailRequestModel : SecretVerificationRequestModel
{
[Required]
[EmailAddress]
[StringLength(256)]
public string Email { get; set; }
public string DeviceIdentifier { get; set; }
public User ToUser(User extistingUser)
{
var providers = extistingUser.GetTwoFactorProviders();
if (providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
else if (providers.ContainsKey(TwoFactorProviderType.Email))
{
providers.Remove(TwoFactorProviderType.Email);
}
providers.Add(TwoFactorProviderType.Email, new TwoFactorProvider
{
MetaData = new Dictionary<string, object> { ["Email"] = Email.ToLowerInvariant() },
Enabled = true
});
extistingUser.SetTwoFactorProviders(providers);
return extistingUser;
}
}
public class TwoFactorWebAuthnRequestModel : TwoFactorWebAuthnDeleteRequestModel
{
[Required]
public AuthenticatorAttestationRawResponse DeviceResponse { get; set; }
public string Name { get; set; }
}
public class TwoFactorWebAuthnDeleteRequestModel : SecretVerificationRequestModel, IValidatableObject
{
[Required]
public int? Id { get; set; }
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
foreach (var validationResult in base.Validate(validationContext))
{
yield return validationResult;
}
if (!Id.HasValue || Id < 0 || Id > 5)
{
yield return new ValidationResult("Invalid Key Id", new string[] { nameof(Id) });
}
}
}
public class UpdateTwoFactorEmailRequestModel : TwoFactorEmailRequestModel
{
[Required]
[StringLength(50)]
public string Token { get; set; }
}
public class TwoFactorProviderRequestModel : SecretVerificationRequestModel
{
[Required]
public TwoFactorProviderType? Type { get; set; }
}
public class TwoFactorRecoveryRequestModel : TwoFactorEmailRequestModel
{
[Required]
[StringLength(32)]
public string RecoveryCode { get; set; }
}

View File

@ -2,19 +2,18 @@
using Bit.Core.Entities;
using Bit.Core.Enums;
namespace Bit.Api.Models.Request
{
public class UpdateDomainsRequestModel
{
public IEnumerable<IEnumerable<string>> EquivalentDomains { get; set; }
public IEnumerable<GlobalEquivalentDomainsType> ExcludedGlobalEquivalentDomains { get; set; }
namespace Bit.Api.Models.Request;
public User ToUser(User existingUser)
{
existingUser.EquivalentDomains = EquivalentDomains != null ? JsonSerializer.Serialize(EquivalentDomains) : null;
existingUser.ExcludedGlobalEquivalentDomains = ExcludedGlobalEquivalentDomains != null ?
JsonSerializer.Serialize(ExcludedGlobalEquivalentDomains) : null;
return existingUser;
}
public class UpdateDomainsRequestModel
{
public IEnumerable<IEnumerable<string>> EquivalentDomains { get; set; }
public IEnumerable<GlobalEquivalentDomainsType> ExcludedGlobalEquivalentDomains { get; set; }
public User ToUser(User existingUser)
{
existingUser.EquivalentDomains = EquivalentDomains != null ? JsonSerializer.Serialize(EquivalentDomains) : null;
existingUser.ExcludedGlobalEquivalentDomains = ExcludedGlobalEquivalentDomains != null ?
JsonSerializer.Serialize(ExcludedGlobalEquivalentDomains) : null;
return existingUser;
}
}

View File

@ -1,33 +1,32 @@
using Bit.Core.Entities;
using Bit.Core.Models.Api;
namespace Bit.Api.Models.Response
namespace Bit.Api.Models.Response;
public class ApiKeyResponseModel : ResponseModel
{
public class ApiKeyResponseModel : ResponseModel
public ApiKeyResponseModel(OrganizationApiKey organizationApiKey, string obj = "apiKey")
: base(obj)
{
public ApiKeyResponseModel(OrganizationApiKey organizationApiKey, string obj = "apiKey")
: base(obj)
if (organizationApiKey == null)
{
if (organizationApiKey == null)
{
throw new ArgumentNullException(nameof(organizationApiKey));
}
ApiKey = organizationApiKey.ApiKey;
RevisionDate = organizationApiKey.RevisionDate;
throw new ArgumentNullException(nameof(organizationApiKey));
}
public ApiKeyResponseModel(User user, string obj = "apiKey")
: base(obj)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
ApiKey = user.ApiKey;
RevisionDate = user.RevisionDate;
}
public string ApiKey { get; set; }
public DateTime RevisionDate { get; set; }
ApiKey = organizationApiKey.ApiKey;
RevisionDate = organizationApiKey.RevisionDate;
}
public ApiKeyResponseModel(User user, string obj = "apiKey")
: base(obj)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
ApiKey = user.ApiKey;
RevisionDate = user.RevisionDate;
}
public string ApiKey { get; set; }
public DateTime RevisionDate { get; set; }
}

View File

@ -5,49 +5,48 @@ using Bit.Core.Models.Data;
using Bit.Core.Settings;
using Bit.Core.Utilities;
namespace Bit.Api.Models.Response
namespace Bit.Api.Models.Response;
public class AttachmentResponseModel : ResponseModel
{
public class AttachmentResponseModel : ResponseModel
public AttachmentResponseModel(AttachmentResponseData data) : base("attachment")
{
public AttachmentResponseModel(AttachmentResponseData data) : base("attachment")
Id = data.Id;
Url = data.Url;
FileName = data.Data.FileName;
Key = data.Data.Key;
Size = data.Data.Size;
SizeName = CoreHelpers.ReadableBytesSize(data.Data.Size);
}
public AttachmentResponseModel(string id, CipherAttachment.MetaData data, Cipher cipher,
IGlobalSettings globalSettings)
: base("attachment")
{
Id = id;
Url = $"{globalSettings.Attachment.BaseUrl}/{cipher.Id}/{id}";
FileName = data.FileName;
Key = data.Key;
Size = data.Size;
SizeName = CoreHelpers.ReadableBytesSize(data.Size);
}
public string Id { get; set; }
public string Url { get; set; }
public string FileName { get; set; }
public string Key { get; set; }
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
public long Size { get; set; }
public string SizeName { get; set; }
public static IEnumerable<AttachmentResponseModel> FromCipher(Cipher cipher, IGlobalSettings globalSettings)
{
var attachments = cipher.GetAttachments();
if (attachments == null)
{
Id = data.Id;
Url = data.Url;
FileName = data.Data.FileName;
Key = data.Data.Key;
Size = data.Data.Size;
SizeName = CoreHelpers.ReadableBytesSize(data.Data.Size);
return null;
}
public AttachmentResponseModel(string id, CipherAttachment.MetaData data, Cipher cipher,
IGlobalSettings globalSettings)
: base("attachment")
{
Id = id;
Url = $"{globalSettings.Attachment.BaseUrl}/{cipher.Id}/{id}";
FileName = data.FileName;
Key = data.Key;
Size = data.Size;
SizeName = CoreHelpers.ReadableBytesSize(data.Size);
}
public string Id { get; set; }
public string Url { get; set; }
public string FileName { get; set; }
public string Key { get; set; }
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
public long Size { get; set; }
public string SizeName { get; set; }
public static IEnumerable<AttachmentResponseModel> FromCipher(Cipher cipher, IGlobalSettings globalSettings)
{
var attachments = cipher.GetAttachments();
if (attachments == null)
{
return null;
}
return attachments.Select(a => new AttachmentResponseModel(a.Key, a.Value, cipher, globalSettings));
}
return attachments.Select(a => new AttachmentResponseModel(a.Key, a.Value, cipher, globalSettings));
}
}

View File

@ -1,16 +1,15 @@
using Bit.Core.Enums;
using Bit.Core.Models.Api;
namespace Bit.Api.Models.Response
{
public class AttachmentUploadDataResponseModel : ResponseModel
{
public string AttachmentId { get; set; }
public string Url { get; set; }
public FileUploadType FileUploadType { get; set; }
public CipherResponseModel CipherResponse { get; set; }
public CipherMiniResponseModel CipherMiniResponse { get; set; }
namespace Bit.Api.Models.Response;
public AttachmentUploadDataResponseModel() : base("attachment-fileUpload") { }
}
public class AttachmentUploadDataResponseModel : ResponseModel
{
public string AttachmentId { get; set; }
public string Url { get; set; }
public FileUploadType FileUploadType { get; set; }
public CipherResponseModel CipherResponse { get; set; }
public CipherMiniResponseModel CipherMiniResponse { get; set; }
public AttachmentUploadDataResponseModel() : base("attachment-fileUpload") { }
}

View File

@ -1,17 +1,16 @@
using Bit.Core.Models.Api;
using Bit.Core.Models.Business;
namespace Bit.Api.Models.Response
namespace Bit.Api.Models.Response;
public class BillingHistoryResponseModel : ResponseModel
{
public class BillingHistoryResponseModel : ResponseModel
public BillingHistoryResponseModel(BillingInfo billing)
: base("billingHistory")
{
public BillingHistoryResponseModel(BillingInfo billing)
: base("billingHistory")
{
Transactions = billing.Transactions?.Select(t => new BillingTransaction(t));
Invoices = billing.Invoices?.Select(i => new BillingInvoice(i));
}
public IEnumerable<BillingInvoice> Invoices { get; set; }
public IEnumerable<BillingTransaction> Transactions { get; set; }
Transactions = billing.Transactions?.Select(t => new BillingTransaction(t));
Invoices = billing.Invoices?.Select(i => new BillingInvoice(i));
}
public IEnumerable<BillingInvoice> Invoices { get; set; }
public IEnumerable<BillingTransaction> Transactions { get; set; }
}

View File

@ -1,18 +1,17 @@
using Bit.Core.Models.Api;
using Bit.Core.Models.Business;
namespace Bit.Api.Models.Response
{
public class BillingPaymentResponseModel : ResponseModel
{
public BillingPaymentResponseModel(BillingInfo billing)
: base("billingPayment")
{
Balance = billing.Balance;
PaymentSource = billing.PaymentSource != null ? new BillingSource(billing.PaymentSource) : null;
}
namespace Bit.Api.Models.Response;
public decimal Balance { get; set; }
public BillingSource PaymentSource { get; set; }
public class BillingPaymentResponseModel : ResponseModel
{
public BillingPaymentResponseModel(BillingInfo billing)
: base("billingPayment")
{
Balance = billing.Balance;
PaymentSource = billing.PaymentSource != null ? new BillingSource(billing.PaymentSource) : null;
}
public decimal Balance { get; set; }
public BillingSource PaymentSource { get; set; }
}

View File

@ -2,82 +2,81 @@
using Bit.Core.Models.Api;
using Bit.Core.Models.Business;
namespace Bit.Api.Models.Response
namespace Bit.Api.Models.Response;
public class BillingResponseModel : ResponseModel
{
public class BillingResponseModel : ResponseModel
public BillingResponseModel(BillingInfo billing)
: base("billing")
{
public BillingResponseModel(BillingInfo billing)
: base("billing")
{
Balance = billing.Balance;
PaymentSource = billing.PaymentSource != null ? new BillingSource(billing.PaymentSource) : null;
Transactions = billing.Transactions?.Select(t => new BillingTransaction(t));
Invoices = billing.Invoices?.Select(i => new BillingInvoice(i));
}
public decimal Balance { get; set; }
public BillingSource PaymentSource { get; set; }
public IEnumerable<BillingInvoice> Invoices { get; set; }
public IEnumerable<BillingTransaction> Transactions { get; set; }
Balance = billing.Balance;
PaymentSource = billing.PaymentSource != null ? new BillingSource(billing.PaymentSource) : null;
Transactions = billing.Transactions?.Select(t => new BillingTransaction(t));
Invoices = billing.Invoices?.Select(i => new BillingInvoice(i));
}
public class BillingSource
{
public BillingSource(BillingInfo.BillingSource source)
{
Type = source.Type;
CardBrand = source.CardBrand;
Description = source.Description;
NeedsVerification = source.NeedsVerification;
}
public PaymentMethodType Type { get; set; }
public string CardBrand { get; set; }
public string Description { get; set; }
public bool NeedsVerification { get; set; }
}
public class BillingInvoice
{
public BillingInvoice(BillingInfo.BillingInvoice inv)
{
Amount = inv.Amount;
Date = inv.Date;
Url = inv.Url;
PdfUrl = inv.PdfUrl;
Number = inv.Number;
Paid = inv.Paid;
}
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; }
}
public class BillingTransaction
{
public BillingTransaction(BillingInfo.BillingTransaction transaction)
{
CreatedDate = transaction.CreatedDate;
Amount = transaction.Amount;
Refunded = transaction.Refunded;
RefundedAmount = transaction.RefundedAmount;
PartiallyRefunded = transaction.PartiallyRefunded;
Type = transaction.Type;
PaymentMethodType = transaction.PaymentMethodType;
Details = transaction.Details;
}
public DateTime CreatedDate { get; set; }
public decimal Amount { get; set; }
public bool? Refunded { get; set; }
public bool? PartiallyRefunded { get; set; }
public decimal? RefundedAmount { get; set; }
public TransactionType Type { get; set; }
public PaymentMethodType? PaymentMethodType { get; set; }
public string Details { get; set; }
}
public decimal Balance { get; set; }
public BillingSource PaymentSource { get; set; }
public IEnumerable<BillingInvoice> Invoices { get; set; }
public IEnumerable<BillingTransaction> Transactions { get; set; }
}
public class BillingSource
{
public BillingSource(BillingInfo.BillingSource source)
{
Type = source.Type;
CardBrand = source.CardBrand;
Description = source.Description;
NeedsVerification = source.NeedsVerification;
}
public PaymentMethodType Type { get; set; }
public string CardBrand { get; set; }
public string Description { get; set; }
public bool NeedsVerification { get; set; }
}
public class BillingInvoice
{
public BillingInvoice(BillingInfo.BillingInvoice inv)
{
Amount = inv.Amount;
Date = inv.Date;
Url = inv.Url;
PdfUrl = inv.PdfUrl;
Number = inv.Number;
Paid = inv.Paid;
}
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; }
}
public class BillingTransaction
{
public BillingTransaction(BillingInfo.BillingTransaction transaction)
{
CreatedDate = transaction.CreatedDate;
Amount = transaction.Amount;
Refunded = transaction.Refunded;
RefundedAmount = transaction.RefundedAmount;
PartiallyRefunded = transaction.PartiallyRefunded;
Type = transaction.Type;
PaymentMethodType = transaction.PaymentMethodType;
Details = transaction.Details;
}
public DateTime CreatedDate { get; set; }
public decimal Amount { get; set; }
public bool? Refunded { get; set; }
public bool? PartiallyRefunded { get; set; }
public decimal? RefundedAmount { get; set; }
public TransactionType Type { get; set; }
public PaymentMethodType? PaymentMethodType { get; set; }
public string Details { get; set; }
}

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