mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-05-09 07:46:13 -04:00
Refactor to use central ClientHeaderInfo model with parsing built-in (#1967)
This commit is contained in:
committed by
Leendert de Borst
parent
459bd6afe0
commit
65ad2dd5cb
@@ -100,34 +100,13 @@ public class AuthController(IAliasServerDbContextFactory dbContextFactory, UserM
|
||||
|
||||
// Check client version compatibility if header is provided
|
||||
var clientSupported = false;
|
||||
if (!string.IsNullOrEmpty(clientHeader))
|
||||
var clientInfo = ClientHeaderInfo.Parse(clientHeader);
|
||||
if (!string.IsNullOrEmpty(clientInfo.ClientVersion)
|
||||
&& AppInfo.MinimumClientVersions.TryGetValue(clientInfo.ClientName, out var minimumVersion))
|
||||
{
|
||||
// Client header format should be "{platform}-{version}" e.g. "chrome-1.4.0"
|
||||
var parts = clientHeader.Split('-');
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
var platform = parts[0].ToLowerInvariant();
|
||||
var clientVersion = parts[1];
|
||||
|
||||
if (AppInfo.MinimumClientVersions.TryGetValue(platform, out var minimumVersion))
|
||||
{
|
||||
// Check if version meets minimum requirement AND is not in blocked list
|
||||
var meetsMinimum = VersionHelper.IsVersionEqualOrNewer(clientVersion, minimumVersion);
|
||||
var isBlocked = VersionHelper.IsVersionBlocked(platform, clientVersion, AppInfo.UnsupportedClientVersions);
|
||||
|
||||
clientSupported = meetsMinimum && !isBlocked;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown platform
|
||||
clientSupported = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid header format
|
||||
clientSupported = false;
|
||||
}
|
||||
var meetsMinimum = VersionHelper.IsVersionEqualOrNewer(clientInfo.ClientVersion, minimumVersion);
|
||||
var isBlocked = VersionHelper.IsVersionBlocked(clientInfo.ClientName, clientInfo.ClientVersion, AppInfo.UnsupportedClientVersions);
|
||||
clientSupported = meetsMinimum && !isBlocked;
|
||||
}
|
||||
|
||||
return Ok(new StatusResponse
|
||||
|
||||
@@ -106,19 +106,14 @@ public static class AuthHelper
|
||||
var userAgent = request.Headers.UserAgent.ToString();
|
||||
var acceptLanguage = request.Headers.AcceptLanguage.ToString();
|
||||
|
||||
// Client header is formatted like "[client name]-[version]" or "[client name]-[version]-[app-instance-id]"
|
||||
// Examples: "chrome-0.25.0", "android-0.29.0-550e8400e29b41d4a716446655440000"
|
||||
var clientHeader = request.Headers["X-AliasVault-Client"].ToString();
|
||||
var clientParts = clientHeader?.Split('-') ?? [];
|
||||
var clientName = clientParts.Length > 0 ? clientParts[0] : "unknown";
|
||||
var clientInfo = ClientHeaderInfo.Parse(request.Headers[ClientHeaderInfo.HeaderName].ToString());
|
||||
|
||||
// For Android, extract app instance ID if present (UUID without dashes as 3rd part)
|
||||
var appInstanceSuffix = string.Empty;
|
||||
if (clientName == "android" && clientParts.Length >= 3)
|
||||
{
|
||||
appInstanceSuffix = $"|{clientParts[2]}";
|
||||
}
|
||||
// Only Android appends an app instance id, used to keep device identifiers unique
|
||||
// across multiple Android User Profiles on the same physical device.
|
||||
var appInstanceSuffix = clientInfo.ClientName == "android" && clientInfo.AppInstanceId is not null
|
||||
? $"|{clientInfo.AppInstanceId}"
|
||||
: string.Empty;
|
||||
|
||||
return $"{clientName}|{userAgent}|{acceptLanguage}{appInstanceSuffix}";
|
||||
return $"{clientInfo.ClientName}|{userAgent}|{acceptLanguage}{appInstanceSuffix}";
|
||||
}
|
||||
}
|
||||
|
||||
53
apps/server/AliasVault.Api/Helpers/ClientHeaderInfo.cs
Normal file
53
apps/server/AliasVault.Api/Helpers/ClientHeaderInfo.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ClientHeaderInfo.cs" company="aliasvault">
|
||||
// Copyright (c) aliasvault. All rights reserved.
|
||||
// Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace AliasVault.Api.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Parsed components of the X-AliasVault-Client request header.
|
||||
///
|
||||
/// Header format is "{client}-{version}", optionally followed by additional dash-separated
|
||||
/// segments.
|
||||
///
|
||||
/// Note: currently only the Android app appends a third segment with a per-install
|
||||
/// app instance id (UUID without dashes) to support multiple Android User Profiles.
|
||||
///
|
||||
/// Examples:
|
||||
/// - "chrome-0.29.0"
|
||||
/// - "ios-0.29.0"
|
||||
/// - "android-0.29.0-550e8400e29b41d4a716446655440000".
|
||||
/// </summary>
|
||||
/// <param name="ClientName">Lowercased client/platform identifier (e.g. "chrome", "android"). "unknown" when the header is missing or empty.</param>
|
||||
/// <param name="ClientVersion">Client version string (e.g. "0.29.0"), or null when not present.</param>
|
||||
/// <param name="AppInstanceId">Per-install app instance identifier, or null when not present.</param>
|
||||
public sealed record ClientHeaderInfo(string ClientName, string? ClientVersion, string? AppInstanceId)
|
||||
{
|
||||
/// <summary>
|
||||
/// Header name used by AliasVault clients to identify themselves.
|
||||
/// </summary>
|
||||
public const string HeaderName = "X-AliasVault-Client";
|
||||
|
||||
/// <summary>
|
||||
/// Parse a raw X-AliasVault-Client header value into its components.
|
||||
/// </summary>
|
||||
/// <param name="headerValue">Raw header value, may be null or empty.</param>
|
||||
/// <returns>Parsed ClientHeaderInfo. Missing trailing segments are returned as null.</returns>
|
||||
public static ClientHeaderInfo Parse(string? headerValue)
|
||||
{
|
||||
if (string.IsNullOrEmpty(headerValue))
|
||||
{
|
||||
return new ClientHeaderInfo("unknown", null, null);
|
||||
}
|
||||
|
||||
var parts = headerValue.Split('-');
|
||||
var clientName = parts[0].ToLowerInvariant();
|
||||
var clientVersion = parts.Length > 1 ? parts[1] : null;
|
||||
var appInstanceId = parts.Length > 2 ? parts[2] : null;
|
||||
|
||||
return new ClientHeaderInfo(clientName, clientVersion, appInstanceId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user