-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[PM-3836] Tools - Make Controllers, Services and API Models nullable #7212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4400bbd
835aed9
45ef350
d0b0ce0
abe9d60
da8043d
3dbc9fd
a783f60
f80a89f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,10 @@ | ||
| // FIXME: Update this file to be null safe and then delete the line below | ||
| #nullable disable | ||
|
|
||
| using Bit.Api.Vault.Models.Request; | ||
| using Bit.Api.Vault.Models.Request; | ||
|
|
||
| namespace Bit.Api.Tools.Models.Request.Accounts; | ||
|
|
||
| public class ImportCiphersRequestModel | ||
| { | ||
| public FolderWithIdRequestModel[] Folders { get; set; } | ||
| public CipherRequestModel[] Ciphers { get; set; } | ||
| public KeyValuePair<int, int>[] FolderRelationships { get; set; } | ||
| public FolderWithIdRequestModel[] Folders { get; set; } = []; | ||
| public CipherRequestModel[] Ciphers { get; set; } = []; | ||
| public KeyValuePair<int, int>[] FolderRelationships { get; set; } = []; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,11 @@ | ||
| // FIXME: Update this file to be null safe and then delete the line below | ||
| #nullable disable | ||
|
|
||
| using Bit.Api.Models.Request; | ||
| using Bit.Api.Models.Request; | ||
| using Bit.Api.Vault.Models.Request; | ||
|
|
||
| namespace Bit.Api.Tools.Models.Request.Organizations; | ||
|
|
||
| public class ImportOrganizationCiphersRequestModel | ||
| { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| public CollectionWithIdRequestModel[] Collections { get; set; } | ||
| public CipherRequestModel[] Ciphers { get; set; } | ||
| public KeyValuePair<int, int>[] CollectionRelationships { get; set; } | ||
| public CollectionWithIdRequestModel[] Collections { get; set; } = []; | ||
| public CipherRequestModel[] Ciphers { get; set; } = []; | ||
| public KeyValuePair<int, int>[] CollectionRelationships { get; set; } = []; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,9 @@ | ||
| // FIXME: Update this file to be null safe and then delete the line below | ||
| #nullable disable | ||
|
|
||
| using System.ComponentModel.DataAnnotations; | ||
| using System.ComponentModel.DataAnnotations; | ||
|
|
||
| namespace Bit.Api.Tools.Models.Request; | ||
|
|
||
| public class SendAccessRequestModel | ||
| { | ||
| [StringLength(300)] | ||
| public string Password { get; set; } | ||
| public string? Password { get; set; } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,4 @@ | ||
| // FIXME: Update this file to be null safe and then delete the line below | ||
| #nullable disable | ||
|
|
||
| using System.ComponentModel.DataAnnotations; | ||
| using System.ComponentModel.DataAnnotations; | ||
| using System.Text.Json; | ||
| using Bit.Api.Tools.Utilities; | ||
| using Bit.Core.Exceptions; | ||
|
|
@@ -10,7 +7,6 @@ | |
| using Bit.Core.Tools.Models.Data; | ||
| using Bit.Core.Tools.Services; | ||
| using Bit.Core.Utilities; | ||
|
|
||
| using static System.StringSplitOptions; | ||
|
|
||
| namespace Bit.Api.Tools.Models.Request; | ||
|
|
@@ -41,14 +37,14 @@ public class SendRequestModel | |
| /// </summary> | ||
| [EncryptedString] | ||
| [EncryptedStringLength(1000)] | ||
| public string Name { get; set; } | ||
| public string? Name { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Notes for the send. This is only visible to the owner of the send. | ||
| /// </summary> | ||
| [EncryptedString] | ||
| [EncryptedStringLength(1000)] | ||
| public string Notes { get; set; } | ||
| public string? Notes { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// A base64-encoded byte array containing the Send's encryption key. This key is | ||
|
|
@@ -57,7 +53,7 @@ public class SendRequestModel | |
| [Required] | ||
| [EncryptedString] | ||
| [EncryptedStringLength(1000)] | ||
| public string Key { get; set; } | ||
| public required string Key { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// The maximum number of times a send can be accessed before it expires. | ||
|
|
@@ -74,8 +70,8 @@ public class SendRequestModel | |
|
|
||
| /// <summary> | ||
| /// The date after which a send may be automatically deleted from the server. | ||
| /// When this is <see langword="null" />, the send may be deleted after it has | ||
| /// exceeded the global send timeout limit. | ||
| /// The server enforces a maximum of 31 days from creation. A background job | ||
| /// deletes sends once this date has passed. | ||
| /// </summary> | ||
| [Required] | ||
| public DateTime? DeletionDate { get; set; } | ||
|
|
@@ -84,26 +80,26 @@ public class SendRequestModel | |
| /// Contains file metadata uploaded with the send. | ||
| /// The file content is uploaded separately. | ||
| /// </summary> | ||
| public SendFileModel File { get; set; } | ||
| public SendFileModel? File { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Contains text data uploaded with the send. | ||
| /// </summary> | ||
| public SendTextModel Text { get; set; } | ||
| public SendTextModel? Text { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Base64-encoded byte array of a password hash that grants access to the send. | ||
| /// Mutually exclusive with <see cref="Emails"/>. | ||
| /// </summary> | ||
| [StringLength(1000)] | ||
| public string Password { get; set; } | ||
| public string? Password { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Comma-separated list of emails that may access the send using OTP | ||
| /// authentication. Mutually exclusive with <see cref="Password"/>. | ||
| /// </summary> | ||
| [StringLength(4000)] | ||
| public string Emails { get; set; } | ||
| public string? Emails { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// When <see langword="true"/>, send access is disabled. | ||
|
|
@@ -126,11 +122,7 @@ public class SendRequestModel | |
| /// <returns>The send object</returns> | ||
| public Send ToSend(Guid userId, ISendAuthorizationService sendAuthorizationService) | ||
| { | ||
| var send = new Send | ||
| { | ||
| Type = Type, | ||
| UserId = (Guid?)userId | ||
| }; | ||
| var send = new Send { Type = Type, UserId = (Guid?)userId }; | ||
| send = UpdateSend(send, sendAuthorizationService); | ||
| return send; | ||
| } | ||
|
|
@@ -146,12 +138,8 @@ public Send ToSend(Guid userId, ISendAuthorizationService sendAuthorizationServi | |
| { | ||
| // FIXME: This method does two things: creates a send and a send file data. | ||
| // It should only do one thing. | ||
| var send = ToSendBase(new Send | ||
| { | ||
| Type = Type, | ||
| UserId = (Guid?)userId | ||
| }, sendAuthorizationService); | ||
| var data = new SendFileData(Name, Notes, fileName); | ||
| var send = ToSendBase(new Send { Type = Type, UserId = (Guid?)userId }, sendAuthorizationService); | ||
| var data = new SendFileData(Name ?? string.Empty, Notes, fileName); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only the CLI can create or edit Sends having no name, the former behavior serialized and deserialized them as 'null', I've taken this opportunity to instead assign an empty string. Suggestions for a different default are welcome.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think empty string is fine, definitely an improvement over the former behavior. It does seem weird that the CLI is allowed to do that though, was that a deliberate design choice?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure about this, I'd like to raise this with Product next time we sync. Typically, we strive for parity among clients. I didn't want to increase the scope of this work by making any changes in |
||
| return (send, data); | ||
| } | ||
|
|
||
|
|
@@ -167,8 +155,10 @@ public Send UpdateSend(Send existingSend, ISendAuthorizationService sendAuthoriz | |
| switch (existingSend.Type) | ||
| { | ||
| case SendType.File: | ||
| var fileData = JsonSerializer.Deserialize<SendFileData>(existingSend.Data); | ||
| fileData.Name = Name; | ||
| // See Send.cs property definition for Data, it can safely be assumed non-null | ||
| var fileData = JsonSerializer.Deserialize<SendFileData>(existingSend.Data!) ?? | ||
| throw new JsonException("Failed to deserialize send file data."); | ||
| fileData.Name = Name ?? string.Empty; | ||
| fileData.Notes = Notes; | ||
| existingSend.Data = JsonSerializer.Serialize(fileData, JsonHelpers.IgnoreWritingNull); | ||
| break; | ||
|
|
@@ -178,6 +168,7 @@ public Send UpdateSend(Send existingSend, ISendAuthorizationService sendAuthoriz | |
| default: | ||
| throw new ArgumentException("Unsupported type: " + nameof(Type) + "."); | ||
| } | ||
|
|
||
| return existingSend; | ||
| } | ||
|
|
||
|
|
@@ -195,8 +186,9 @@ public void ValidateCreation() | |
| if (ExpirationDate.HasValue && ExpirationDate.Value <= nowPlus1Minute) | ||
| { | ||
| throw new BadRequestException("You cannot create a Send that is already expired. " + | ||
| "Adjust the expiration date and try again."); | ||
| "Adjust the expiration date and try again."); | ||
| } | ||
|
|
||
| ValidateEdit(); | ||
| } | ||
|
|
||
|
|
@@ -217,25 +209,29 @@ public void ValidateEdit() | |
| 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."); | ||
| "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."); | ||
| "into the future. Adjust the Deletion Date to a value less than 31 days from now " + | ||
| "and try again."); | ||
| } | ||
| } | ||
|
|
||
| if (ExpirationDate.HasValue) | ||
| { | ||
| if (ExpirationDate.Value <= nowPlus1Minute) | ||
| { | ||
| throw new BadRequestException("You cannot have a Send with an expiration date in the past. " + | ||
| "Adjust the expiration date and try again."); | ||
| "Adjust the expiration date and try again."); | ||
| } | ||
| if (ExpirationDate.Value > DeletionDate.Value) | ||
|
|
||
| if (DeletionDate.HasValue && ExpirationDate.Value > DeletionDate.Value) | ||
| { | ||
| throw new BadRequestException("You cannot have a Send with an expiration date greater than the deletion date. " + | ||
| throw new BadRequestException( | ||
| "You cannot have a Send with an expiration date greater than the deletion date. " + | ||
| "Adjust the expiration date and try again."); | ||
| } | ||
| } | ||
|
|
@@ -245,7 +241,7 @@ private Send ToSendBase(Send existingSend, ISendAuthorizationService authorizati | |
| { | ||
| existingSend.Key = Key; | ||
| existingSend.ExpirationDate = ExpirationDate; | ||
| existingSend.DeletionDate = DeletionDate.Value; | ||
| existingSend.DeletionDate = DeletionDate!.Value; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is safe since |
||
| existingSend.MaxAccessCount = MaxAccessCount; | ||
| existingSend.Disabled = Disabled.GetValueOrDefault(); | ||
| existingSend.HideEmail = HideEmail.GetValueOrDefault(); | ||
|
|
@@ -268,7 +264,7 @@ private Send ToSendBase(Send existingSend, ISendAuthorizationService authorizati | |
| existingSend.Password = null; | ||
| break; | ||
| case Core.Tools.Enums.AuthType.Password: | ||
| existingSend.Password = authorizationService.HashPassword(Password); | ||
| existingSend.Password = authorizationService.HashPassword(Password!); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clients all enforce that a password protected Send must have a password |
||
| existingSend.Emails = null; | ||
| break; | ||
| case Core.Tools.Enums.AuthType.None: | ||
|
|
@@ -312,9 +308,11 @@ private Send ToSendBase(Send existingSend, ISendAuthorizationService authorizati | |
| return existingSend; | ||
| } | ||
|
|
||
| // Only called from the SendType.Text branch of UpdateSend, Text is required by client and not null | ||
| private SendTextData ToSendTextData() | ||
| { | ||
| return new SendTextData(Name, Notes, Text.Text, Text.Hidden); | ||
| var text = Text ?? throw new ArgumentNullException(nameof(Text), "Text is required for text sends."); | ||
| return new SendTextData(Name ?? string.Empty, Notes, text.Text, text.Hidden); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,11 @@ | ||
| // FIXME: Update this file to be null safe and then delete the line below | ||
| #nullable disable | ||
|
|
||
| using Bit.Core.Models.Api; | ||
| using Bit.Core.Models.Api; | ||
|
|
||
| namespace Bit.Api.Tools.Models.Response; | ||
|
|
||
| public class SendFileDownloadDataResponseModel : ResponseModel | ||
| { | ||
| public string Id { get; set; } | ||
| public string Url { get; set; } | ||
| public string? Id { get; set; } | ||
| public string? Url { get; set; } | ||
|
|
||
| public SendFileDownloadDataResponseModel() : base("send-fileDownload") { } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See corresponding model in clients