1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-01 16:12:49 -05:00

Start Migration from Newtonsoft.Json to System.Text.Json (#1803)

* Start switch to System.Text.Json

* Work on switching to System.Text.Json

* Main work on STJ refactor

* Fix build errors

* Run formatting

* Delete unused file

* Use legacy for two factor providers

* Run formatter

* Add TokenProviderTests

* Run formatting

* Fix merge issues

* Switch to use JsonSerializer

* Address PR feedback

* Fix formatting

* Ran formatter

* Switch to async

* Ensure Enums are serialized as strings

* Fix formatting

* Enqueue single items as arrays

* Remove CreateAsync method on AzureQueueService
This commit is contained in:
Justin Baur
2022-01-21 09:36:25 -05:00
committed by GitHub
parent 897a76ff48
commit 5268f2781e
91 changed files with 974 additions and 698 deletions

View File

@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Bit.Billing.Models;
using Bit.Core.Repositories;
@ -9,8 +11,6 @@ using Bit.Core.Settings;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Bit.Core.Services
{
@ -97,14 +97,16 @@ namespace Bit.Core.Services
}
var url = string.Format("https://{0}.itunes.apple.com/verifyReceipt", prod ? "buy" : "sandbox");
var json = new JObject(new JProperty("receipt-data", receiptData),
new JProperty("password", _globalSettings.AppleIap.Password)).ToString();
var response = await _httpClient.PostAsync(url, new StringContent(json));
var response = await _httpClient.PostAsJsonAsync(url, new AppleVerifyReceiptRequestModel
{
ReceiptData = receiptData,
Password = _globalSettings.AppleIap.Password
});
if (response.IsSuccessStatusCode)
{
var responseJson = await response.Content.ReadAsStringAsync();
var receiptStatus = JsonConvert.DeserializeObject<AppleReceiptStatus>(responseJson);
var receiptStatus = await response.Content.ReadFromJsonAsync<AppleReceiptStatus>();
if (receiptStatus.Status == 21007)
{
return await GetReceiptStatusAsync(receiptData, false, attempt + 1, receiptStatus);
@ -124,4 +126,12 @@ namespace Bit.Core.Services
return null;
}
}
public class AppleVerifyReceiptRequestModel
{
[JsonPropertyName("receipt-data")]
public string ReceiptData { get; set; }
[JsonPropertyName("password")]
public string Password { get; set; }
}
}

View File

@ -5,7 +5,7 @@ using System.Threading.Tasks;
using Azure.Storage.Queues;
using Bit.Core.Models.Data;
using Bit.Core.Settings;
using Newtonsoft.Json;
using Bit.Core.Utilities;
namespace Bit.Core.Services
{
@ -13,7 +13,9 @@ namespace Bit.Core.Services
{
public AzureQueueEventWriteService(GlobalSettings globalSettings) : base(
new QueueClient(globalSettings.Events.ConnectionString, "event"),
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })
JsonHelpers.IgnoreWritingNull)
{ }
public Task CreateAsync(IEvent e) => CreateManyAsync(new[] { e });
}
}

View File

@ -5,7 +5,7 @@ using System.Threading.Tasks;
using Azure.Storage.Queues;
using Bit.Core.Models.Mail;
using Bit.Core.Settings;
using Newtonsoft.Json;
using Bit.Core.Utilities;
namespace Bit.Core.Services
{
@ -13,11 +13,11 @@ namespace Bit.Core.Services
{
public AzureQueueMailService(GlobalSettings globalSettings) : base(
new QueueClient(globalSettings.Mail.ConnectionString, "mail"),
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })
JsonHelpers.IgnoreWritingNull)
{ }
public Task EnqueueAsync(IMailQueueMessage message, Func<IMailQueueMessage, Task> fallback) =>
CreateAsync(message);
CreateManyAsync(new[] { message });
public Task EnqueueManyAsync(IEnumerable<IMailQueueMessage> messages, Func<IMailQueueMessage, Task> fallback) =>
CreateManyAsync(messages);

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.Storage.Queues;
using Bit.Core.Context;
@ -7,8 +8,8 @@ using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models;
using Bit.Core.Settings;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
namespace Bit.Core.Services
{
@ -18,11 +19,6 @@ namespace Bit.Core.Services
private readonly GlobalSettings _globalSettings;
private readonly IHttpContextAccessor _httpContextAccessor;
private JsonSerializerSettings _jsonSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
public AzureQueuePushNotificationService(
GlobalSettings globalSettings,
IHttpContextAccessor httpContextAccessor)
@ -170,8 +166,8 @@ namespace Bit.Core.Services
private async Task SendMessageAsync<T>(PushType type, T payload, bool excludeCurrentContext)
{
var contextId = GetContextIdentifier(excludeCurrentContext);
var message = JsonConvert.SerializeObject(new PushNotificationData<T>(type, payload, contextId),
_jsonSettings);
var message = JsonSerializer.Serialize(new PushNotificationData<T>(type, payload, contextId),
JsonHelpers.IgnoreWritingNull);
await _queueClient.SendMessageAsync(message);
}

View File

@ -1,10 +1,11 @@
using System;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.Storage.Queues;
using Bit.Core.Models.Business;
using Bit.Core.Settings;
using Newtonsoft.Json;
using Bit.Core.Utilities;
namespace Bit.Core.Services
{
@ -14,10 +15,6 @@ namespace Bit.Core.Services
private readonly QueueClient _queueClient;
private readonly GlobalSettings _globalSettings;
private readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
};
public AzureQueueReferenceEventService(
GlobalSettings globalSettings)
@ -40,7 +37,7 @@ namespace Bit.Core.Services
}
try
{
var message = JsonConvert.SerializeObject(referenceEvent, _jsonSerializerSettings);
var message = JsonSerializer.Serialize(referenceEvent, JsonHelpers.IgnoreWritingNullAndCamelCase);
// Messages need to be base64 encoded
var encodedMessage = Convert.ToBase64String(Encoding.UTF8.GetBytes(message));
await _queueClient.SendMessageAsync(encodedMessage);

View File

@ -1,29 +1,22 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.Storage.Queues;
using Bit.Core.Utilities;
using Newtonsoft.Json;
namespace Bit.Core.Services
{
public abstract class AzureQueueService<T>
{
protected QueueClient _queueClient;
protected JsonSerializerSettings _jsonSettings;
protected JsonSerializerOptions _jsonOptions;
protected AzureQueueService(QueueClient queueClient, JsonSerializerSettings jsonSettings)
protected AzureQueueService(QueueClient queueClient, JsonSerializerOptions jsonOptions)
{
_queueClient = queueClient;
_jsonSettings = jsonSettings;
}
public async Task CreateAsync(T message)
{
var json = JsonConvert.SerializeObject(message, _jsonSettings);
var base64 = CoreHelpers.Base64EncodeString(json);
await _queueClient.SendMessageAsync(base64);
_jsonOptions = jsonOptions;
}
public async Task CreateManyAsync(IEnumerable<T> messages)
@ -33,19 +26,13 @@ namespace Bit.Core.Services
return;
}
if (!messages.Skip(1).Any())
{
await CreateAsync(messages.First());
return;
}
foreach (var json in SerializeMany(messages, _jsonSettings))
foreach (var json in SerializeMany(messages, _jsonOptions))
{
await _queueClient.SendMessageAsync(json);
}
}
protected IEnumerable<string> SerializeMany(IEnumerable<T> messages, JsonSerializerSettings jsonSettings)
protected IEnumerable<string> SerializeMany(IEnumerable<T> messages, JsonSerializerOptions jsonOptions)
{
// Calculate Base-64 encoded text with padding
int getBase64Size(int byteCount) => ((4 * byteCount / 3) + 3) & ~3;
@ -69,7 +56,7 @@ namespace Bit.Core.Services
}
var serializedMessages = messages.Select(message =>
JsonConvert.SerializeObject(message, jsonSettings));
JsonSerializer.Serialize(message, jsonOptions));
foreach (var message in serializedMessages)
{

View File

@ -3,23 +3,23 @@ using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Bit.Core.Utilities;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Bit.Core.Services
{
public abstract class BaseIdentityClientService
public abstract class BaseIdentityClientService : IDisposable
{
private readonly string _identityScope;
private readonly string _identityClientId;
private readonly string _identityClientSecret;
private readonly ILogger<BaseIdentityClientService> _logger;
private dynamic _decodedToken;
private JsonDocument _decodedToken;
private DateTime? _nextAuthAttempt = null;
public BaseIdentityClientService(
@ -127,9 +127,9 @@ namespace Bit.Core.Services
return false;
}
var responseContent = await response.Content.ReadAsStringAsync();
dynamic tokenResponse = JsonConvert.DeserializeObject(responseContent);
AccessToken = (string)tokenResponse.access_token;
using var jsonDocument = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
AccessToken = jsonDocument.RootElement.GetProperty("access_token").GetString();
return true;
}
@ -145,8 +145,7 @@ namespace Bit.Core.Services
{
if (requestObject != null)
{
var stringContent = JsonConvert.SerializeObject(requestObject);
Content = new StringContent(stringContent, Encoding.UTF8, "application/json");
Content = JsonContent.Create(requestObject);
}
}
}
@ -154,17 +153,16 @@ namespace Bit.Core.Services
protected bool TokenNeedsRefresh(int minutes = 5)
{
var decoded = DecodeToken();
var exp = decoded?["exp"];
if (exp == null)
if (!decoded.RootElement.TryGetProperty("exp", out var expProp))
{
throw new InvalidOperationException("No exp in token.");
}
var expiration = CoreHelpers.FromEpocSeconds(exp.Value<long>());
var expiration = CoreHelpers.FromEpocSeconds(expProp.GetInt64());
return DateTime.UtcNow.AddMinutes(-1 * minutes) > expiration;
}
protected JObject DecodeToken()
protected JsonDocument DecodeToken()
{
if (_decodedToken != null)
{
@ -188,8 +186,13 @@ namespace Bit.Core.Services
throw new InvalidOperationException($"{nameof(AccessToken)} must have 3 parts");
}
_decodedToken = JObject.Parse(Encoding.UTF8.GetString(decodedBytes, 0, decodedBytes.Length));
_decodedToken = JsonDocument.Parse(decodedBytes);
return _decodedToken;
}
public void Dispose()
{
_decodedToken.Dispose();
}
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Bit.Core.Entities;
using Bit.Core.Enums;
@ -12,7 +13,6 @@ using Bit.Core.Repositories;
using Bit.Core.Settings;
using Bit.Core.Utilities;
using Core.Models.Data;
using Newtonsoft.Json;
namespace Bit.Core.Services
{
@ -208,7 +208,7 @@ namespace Bit.Core.Services
UserId = cipher.UserId,
OrganizationId = cipher.OrganizationId,
AttachmentId = attachmentId,
AttachmentData = JsonConvert.SerializeObject(data)
AttachmentData = JsonSerializer.Serialize(data)
});
cipher.AddAttachment(attachmentId, data);
await _pushService.PushSyncCipherUpdateAsync(cipher, null);
@ -241,7 +241,7 @@ namespace Bit.Core.Services
UserId = cipher.UserId,
OrganizationId = cipher.OrganizationId,
AttachmentId = attachmentId,
AttachmentData = JsonConvert.SerializeObject(data)
AttachmentData = JsonSerializer.Serialize(data)
};
await _cipherRepository.UpdateAttachmentAsync(attachment);
@ -312,7 +312,7 @@ namespace Bit.Core.Services
UserId = cipher.UserId,
OrganizationId = cipher.OrganizationId,
AttachmentId = attachmentId,
AttachmentData = JsonConvert.SerializeObject(attachments[attachmentId])
AttachmentData = JsonSerializer.Serialize(attachments[attachmentId])
};
await _cipherRepository.UpdateAttachmentAsync(updatedAttachment);
@ -347,7 +347,7 @@ namespace Bit.Core.Services
UserId = cipher.UserId,
OrganizationId = cipher.OrganizationId,
AttachmentId = attachmentData.AttachmentId,
AttachmentData = JsonConvert.SerializeObject(attachmentData)
AttachmentData = JsonSerializer.Serialize(attachmentData)
};

View File

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading.Tasks;
using Bit.Core.Context;
using Bit.Core.Entities;
@ -8,7 +10,6 @@ using Bit.Core.Models.Business.Tokenables;
using Bit.Core.Settings;
using Bit.Core.Tokens;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Bit.Core.Services
{
@ -77,9 +78,9 @@ namespace Bit.Core.Services
return false;
}
var responseContent = await responseMessage.Content.ReadAsStringAsync();
dynamic jsonResponse = JsonConvert.DeserializeObject(responseContent);
return (bool)jsonResponse.success;
using var jsonDocument = await responseMessage.Content.ReadFromJsonAsync<JsonDocument>();
var root = jsonDocument.RootElement;
return root.GetProperty("success").GetBoolean();
}
public bool RequireCaptchaValidation(ICurrentContext currentContext) =>

View File

@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text.Json;
using System.Threading.Tasks;
using Bit.Core.Entities;
using Bit.Core.Entities.Provider;
@ -565,6 +566,35 @@ namespace Bit.Core.Services
var clickTrackingText = (clickTrackingOff ? "clicktracking=off" : string.Empty);
writer.WriteSafeString($"<a href=\"{href}\" target=\"_blank\" {clickTrackingText}>{text}</a>");
});
Handlebars.RegisterHelper("jsonIf", (output, options, context, arguments) =>
{
// Special case for JsonElement
if (arguments[0] is JsonElement jsonElement
&& (jsonElement.ValueKind == JsonValueKind.True || jsonElement.ValueKind == JsonValueKind.False))
{
if (jsonElement.GetBoolean())
{
options.Template(output, context);
}
else
{
options.Inverse(output, context);
}
return;
}
// Fallback to normal
if (HandlebarsUtils.IsTruthy(arguments[0]))
{
options.Template(output, context);
}
else
{
options.Inverse(output, context);
}
});
}
public async Task SendEmergencyAccessInviteEmailAsync(EmergencyAccess emergencyAccess, string name, string token)

View File

@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Bit.Core.Entities;
using Bit.Core.Models.Business;
@ -13,7 +14,6 @@ using Bit.Core.Utilities;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Bit.Core.Services
{
@ -246,7 +246,7 @@ namespace Bit.Core.Services
}
var data = File.ReadAllText(filePath, Encoding.UTF8);
return JsonConvert.DeserializeObject<UserLicense>(data);
return JsonSerializer.Deserialize<UserLicense>(data);
}
private OrganizationLicense ReadOrganizationLicense(Organization organization)
@ -258,7 +258,7 @@ namespace Bit.Core.Services
}
var data = File.ReadAllText(filePath, Encoding.UTF8);
return JsonConvert.DeserializeObject<OrganizationLicense>(data);
return JsonSerializer.Deserialize<OrganizationLicense>(data);
}
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Bit.Core.Context;
@ -11,7 +12,6 @@ using Bit.Core.Repositories;
using Bit.Core.Settings;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.NotificationHubs;
using Newtonsoft.Json;
namespace Bit.Core.Services
{
@ -229,7 +229,7 @@ namespace Bit.Core.Services
new Dictionary<string, string>
{
{ "type", ((byte)type).ToString() },
{ "payload", JsonConvert.SerializeObject(payload) }
{ "payload", JsonSerializer.Serialize(payload) }
}, tag);
}

View File

@ -9,7 +9,6 @@ using Bit.Core.Models;
using Bit.Core.Settings;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Bit.Core.Services
{
@ -18,11 +17,6 @@ namespace Bit.Core.Services
private readonly GlobalSettings _globalSettings;
private readonly IHttpContextAccessor _httpContextAccessor;
private JsonSerializerSettings _jsonSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
public NotificationsApiPushNotificationService(
GlobalSettings globalSettings,
IHttpContextAccessor httpContextAccessor,

View File

@ -15,7 +15,6 @@ using Bit.Core.Settings;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Stripe;
namespace Bit.Core.Services
@ -727,8 +726,8 @@ namespace Bit.Core.Services
var dir = $"{_globalSettings.LicenseDirectory}/organization";
Directory.CreateDirectory(dir);
System.IO.File.WriteAllText($"{dir}/{organization.Id}.json",
JsonConvert.SerializeObject(license, Formatting.Indented));
using var fs = System.IO.File.OpenWrite(Path.Combine(dir, $"{organization.Id}.json"));
await JsonSerializer.SerializeAsync(fs, license, JsonHelpers.Indented);
return result;
}
@ -900,8 +899,8 @@ namespace Bit.Core.Services
var dir = $"{_globalSettings.LicenseDirectory}/organization";
Directory.CreateDirectory(dir);
System.IO.File.WriteAllText($"{dir}/{organization.Id}.json",
JsonConvert.SerializeObject(license, Formatting.Indented));
using var fs = System.IO.File.OpenWrite(Path.Combine(dir, $"{organization.Id}.json"));
await JsonSerializer.SerializeAsync(fs, license, JsonHelpers.Indented);
organization.Name = license.Name;
organization.BusinessName = license.BusinessName;
@ -1146,10 +1145,7 @@ namespace Bit.Core.Services
if (invite.Permissions != null)
{
orgUser.Permissions = System.Text.Json.JsonSerializer.Serialize(invite.Permissions, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
});
orgUser.Permissions = JsonSerializer.Serialize(invite.Permissions, JsonHelpers.CamelCase);
}
if (!orgUser.AccessAll && invite.Collections.Any())
@ -1765,7 +1761,7 @@ namespace Bit.Core.Services
// Block the user from withdrawal if auto enrollment is enabled
if (resetPasswordKey == null && resetPasswordPolicy.Data != null)
{
var data = JsonConvert.DeserializeObject<ResetPasswordDataModel>(resetPasswordPolicy.Data);
var data = JsonSerializer.Deserialize<ResetPasswordDataModel>(resetPasswordPolicy.Data);
if (data?.AutoEnrollEnabled ?? false)
{

View File

@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Net.Http.Json;
using System.Threading.Tasks;
using Bit.Core.Settings;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Bit.Core.Services
{
@ -76,15 +75,13 @@ namespace Bit.Core.Services
request.tag = string.Concat(request.tag, "-Cat_", message.Category);
}
var reqJson = JsonConvert.SerializeObject(request);
var responseMessage = await httpClient.PostAsync(
var responseMessage = await httpClient.PostAsJsonAsync(
$"https://{_globalSettings.Mail.PostalDomain}/api/v1/send/message",
new StringContent(reqJson, Encoding.UTF8, "application/json"));
request);
if (responseMessage.IsSuccessStatusCode)
{
var json = await responseMessage.Content.ReadAsStringAsync();
var response = JsonConvert.DeserializeObject<PostalResponse>(json);
var response = await responseMessage.Content.ReadFromJsonAsync<PostalResponse>();
if (response.status != "success")
{
_logger.LogError("Postal send status was not successful: {0}, {1}",

View File

@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Bit.Core.Context;
using Bit.Core.Entities;
@ -12,7 +13,6 @@ using Bit.Core.Repositories;
using Bit.Core.Settings;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Identity;
using Newtonsoft.Json;
namespace Bit.Core.Services
{
@ -104,8 +104,8 @@ namespace Bit.Core.Services
data.Id = fileId;
data.Size = fileLength;
data.Validated = false;
send.Data = JsonConvert.SerializeObject(data,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
send.Data = JsonSerializer.Serialize(data,
JsonHelpers.IgnoreWritingNull);
await SaveSendAsync(send);
return await _sendFileStorageService.GetSendFileUploadUrlAsync(send, fileId);
}
@ -129,7 +129,7 @@ namespace Bit.Core.Services
throw new BadRequestException("Not a File Type Send.");
}
var data = JsonConvert.DeserializeObject<SendFileData>(send.Data);
var data = JsonSerializer.Deserialize<SendFileData>(send.Data);
if (data.Validated)
{
@ -146,7 +146,7 @@ namespace Bit.Core.Services
public async Task<bool> ValidateSendFile(Send send)
{
var fileData = JsonConvert.DeserializeObject<SendFileData>(send.Data);
var fileData = JsonSerializer.Deserialize<SendFileData>(send.Data);
var (valid, realSize) = await _sendFileStorageService.ValidateFileAsync(send, fileData.Id, fileData.Size, _fileSizeLeeway);
@ -163,8 +163,8 @@ namespace Bit.Core.Services
fileData.Size = realSize.Value;
}
fileData.Validated = true;
send.Data = JsonConvert.SerializeObject(fileData,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
send.Data = JsonSerializer.Serialize(fileData,
JsonHelpers.IgnoreWritingNull);
await SaveSendAsync(send);
return valid;
@ -175,7 +175,7 @@ namespace Bit.Core.Services
await _sendRepository.DeleteAsync(send);
if (send.Type == Enums.SendType.File)
{
var data = JsonConvert.DeserializeObject<SendFileData>(send.Data);
var data = JsonSerializer.Deserialize<SendFileData>(send.Data);
await _sendFileStorageService.DeleteFileAsync(send, data.Id);
}
await _pushService.PushSyncSendDeleteAsync(send);

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.Text.Json;
using System.Threading.Tasks;
using Bit.Core.Context;
using Bit.Core.Entities;
@ -19,7 +20,6 @@ using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using File = System.IO.File;
using U2fLib = U2F.Core.Crypto.U2F;
@ -983,7 +983,8 @@ namespace Bit.Core.Services
var dir = $"{_globalSettings.LicenseDirectory}/user";
Directory.CreateDirectory(dir);
File.WriteAllText($"{dir}/{user.Id}.json", JsonConvert.SerializeObject(license, Formatting.Indented));
using var fs = File.OpenWrite(Path.Combine(dir, $"{user.Id}.json"));
await JsonSerializer.SerializeAsync(fs, license, JsonHelpers.Indented);
}
else
{
@ -1068,7 +1069,8 @@ namespace Bit.Core.Services
var dir = $"{_globalSettings.LicenseDirectory}/user";
Directory.CreateDirectory(dir);
File.WriteAllText($"{dir}/{user.Id}.json", JsonConvert.SerializeObject(license, Formatting.Indented));
using var fs = File.OpenWrite(Path.Combine(dir, $"{user.Id}.json"));
await JsonSerializer.SerializeAsync(fs, license, JsonHelpers.Indented);
user.Premium = license.Premium;
user.RevisionDate = DateTime.UtcNow;