forked from NpgsqlRest/NpgsqlRest
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNpgsqlRestParameter.cs
More file actions
144 lines (125 loc) · 5.13 KB
/
Copy pathNpgsqlRestParameter.cs
File metadata and controls
144 lines (125 loc) · 5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
using System.Text;
using System.Text.Json.Nodes;
using Microsoft.Extensions.Primitives;
using Npgsql;
namespace NpgsqlRest;
public class NpgsqlRestParameter : NpgsqlParameter
{
public int Ordinal { get; private set; }
public string ConvertedName { get; private set; }
public string ActualName { get; private set; }
public TypeDescriptor TypeDescriptor { get; init; }
public ParamType ParamType { get; set; } = default!;
public StringValues? QueryStringValues { get; set; } = null;
public JsonNode? JsonBodyNode { get; set; } = null;
public NpgsqlRestParameter? HashOf { get; set; } = null;
/// <summary>
/// The original string representation of the parameter value as received from the request
/// (query string or JSON body). Used for cache key generation to ensure consistency.
/// </summary>
public string? OriginalStringValue { get; set; } = null;
public bool IsUploadMetadata { get; set; } = false;
public bool IsIpAddress { get; set; } = false;
public string? UserClaim { get; set; } = null;
public bool IsUserClaims { get; set; } = false;
public bool IsFromUserClaims => UserClaim is not null || IsUserClaims is true;
public NpgsqlRestParameter(
int ordinal,
string convertedName,
string actualName,
TypeDescriptor typeDescriptor)
{
Ordinal = ordinal;
ConvertedName = convertedName;
ActualName = actualName;
TypeDescriptor = typeDescriptor;
NpgsqlDbType = typeDescriptor.ActualDbType;
if (actualName is not null &&
Options.AuthenticationOptions.ParameterNameClaimsMapping.TryGetValue(actualName, out var claimName))
{
UserClaim = claimName;
}
if (actualName is not null &&
string.Equals(Options.AuthenticationOptions.IpAddressParameterName, actualName, StringComparison.OrdinalIgnoreCase))
{
IsIpAddress = true;
}
if (actualName is not null &&
string.Equals(Options.AuthenticationOptions.ClaimsJsonParameterName, actualName, StringComparison.OrdinalIgnoreCase))
{
IsUserClaims = true;
}
if (Options.UploadOptions.UseDefaultUploadMetadataParameter is true)
{
if (string.Equals(Options.UploadOptions.DefaultUploadMetadataParameterName, actualName, StringComparison.OrdinalIgnoreCase))
{
IsUploadMetadata = true;
}
}
}
private const char CacheKeySeparator = '\x1F'; // Unit Separator - non-printable ASCII character
private const string CacheKeyNull = "\x00NULL\x00"; // Distinct marker for null/DBNull values
internal string GetCacheStringValue()
{
if (Value is null || Value == DBNull.Value)
{
return CacheKeyNull;
}
// Prefer original string value from request for consistency
if (OriginalStringValue is not null)
{
return OriginalStringValue;
}
// Fallback for internally-set values (user claims, IP address, etc.)
if (TypeDescriptor.IsArray)
{
// Arrays can be stored as List<object?> (from query string parsing) or object[]
IList<object?>? list = Value as IList<object?>;
if (list is null || list.Count == 0)
{
return "[]";
}
var sb = new StringBuilder();
sb.Append('[');
for (int i = 0; i < list.Count; i++)
{
if (i > 0)
{
sb.Append(CacheKeySeparator);
}
sb.Append(list[i]?.ToString() ?? CacheKeyNull);
}
sb.Append(']');
return sb.ToString();
}
return Value.ToString() ?? CacheKeyNull;
}
internal static char GetCacheKeySeparator() => CacheKeySeparator;
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
#pragma warning disable CS8603 // Possible null reference return.
public NpgsqlRestParameter NpgsqlRestParameterMemberwiseClone() => MemberwiseClone() as NpgsqlRestParameter;
private NpgsqlRestParameter() { }
#pragma warning restore CS8603 // Possible null reference return.
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private static readonly NpgsqlRestParameter TextParam = new()
{
NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Text,
Value = DBNull.Value,
};
public static NpgsqlParameter CreateParamWithType(NpgsqlTypes.NpgsqlDbType type)
{
var result = TextParam.NpgsqlRestParameterMemberwiseClone();
result.NpgsqlDbType = type;
return result;
}
public static NpgsqlParameter CreateTextParam(object? value)
{
var result = TextParam.NpgsqlRestParameterMemberwiseClone();
if (value is null)
{
return result;
}
result.Value = value;
return result;
}
}