1631786ce2
Add push contracts, provider delivery and channel diagnostics. Link email channels to services and document migration and validation. Ref: IT-1074
45 lines
2.1 KiB
C#
45 lines
2.1 KiB
C#
using System.Net.Mail;
|
|
using System.Security.Cryptography;
|
|
using System.Text.Json;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace HrynCo.NotificationService.DAL.Abstract.PushChannels;
|
|
|
|
// Parse only service-account fields; never honor caller-supplied OAuth endpoints.
|
|
public sealed class FirebaseServiceAccountCredentials
|
|
{
|
|
public required string ProjectId { get; init; }
|
|
public required string ClientEmail { get; init; }
|
|
public required string PrivateKey { get; init; }
|
|
|
|
public static bool IsValidProjectId(string projectId) => Regex.IsMatch(projectId,
|
|
"^[a-z][a-z0-9-]{4,28}[a-z0-9]$", RegexOptions.CultureInvariant, TimeSpan.FromSeconds(1));
|
|
|
|
public static FirebaseServiceAccountCredentials Parse(string json, string projectId)
|
|
{
|
|
if (!IsValidProjectId(projectId) || json.Length > 32768)
|
|
throw new FormatException("Invalid Firebase configuration.");
|
|
using var document = JsonDocument.Parse(json);
|
|
var root = document.RootElement;
|
|
if (Read(root, "type") != "service_account" || Read(root, "project_id") != projectId)
|
|
throw new FormatException("The service account must belong to the selected Firebase project.");
|
|
var email = Read(root, "client_email");
|
|
if (!MailAddress.TryCreate(email, out var address) || address.Address != email)
|
|
throw new FormatException("Invalid service account email.");
|
|
var key = Read(root, "private_key");
|
|
using var rsa = RSA.Create();
|
|
rsa.ImportFromPem(key);
|
|
// Exporting private parameters also rejects a public-key-only PEM.
|
|
rsa.ExportParameters(true);
|
|
return new FirebaseServiceAccountCredentials { ProjectId = projectId, ClientEmail = email, PrivateKey = key };
|
|
}
|
|
|
|
private static string Read(JsonElement root, string name)
|
|
{
|
|
if (root.ValueKind != JsonValueKind.Object || !root.TryGetProperty(name, out var value)
|
|
|| value.ValueKind != JsonValueKind.String)
|
|
throw new FormatException("Missing service account fields.");
|
|
return value.GetString() ?? string.Empty;
|
|
}
|
|
}
|