Skip to content

Commit 53449ed

Browse files
Merge pull request #646 from nofrixion/feature/MOOV-4824-merchant-token-ip-address
Feature/moov 4824 merchant token ip address
2 parents 0a0c5c7 + 22de043 commit 53449ed

File tree

4 files changed

+109
-1
lines changed

4 files changed

+109
-1
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// -----------------------------------------------------------------------------
2+
// Filename: IPAddressAttribute.cs
3+
//
4+
// Description: A custom attribute to validate multiple IP addresses:
5+
//
6+
// Author(s):
7+
// Donal O'Connor ([email protected])
8+
//
9+
// History:
10+
// 10 09 2025 Donal O'Connor Created, Harcourt St, Dublin, Ireland.
11+
//
12+
// License:
13+
// Proprietary NoFrixion.
14+
// -----------------------------------------------------------------------------
15+
16+
using System.ComponentModel.DataAnnotations;
17+
18+
namespace NoFrixion.MoneyMoov.Attributes;
19+
20+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
21+
public class IPAddressAttribute : ValidationAttribute
22+
{
23+
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
24+
{
25+
if (value == null)
26+
{
27+
return ValidationResult.Success;
28+
}
29+
30+
if (value is not string ipAddressesValue)
31+
{
32+
return new ValidationResult($"The {validationContext.DisplayName} field must be a string.");
33+
}
34+
35+
if (string.IsNullOrWhiteSpace(ipAddressesValue))
36+
{
37+
return ValidationResult.Success;
38+
}
39+
40+
var ipAddresses = ipAddressesValue.Split([','], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
41+
42+
foreach (var ipAddress in ipAddresses)
43+
{
44+
if (!System.Net.IPAddress.TryParse(ipAddress, out _) && !System.Net.IPNetwork.TryParse(ipAddress, out _))
45+
{
46+
return new ValidationResult($"The {validationContext.DisplayName} field contains an invalid IP address: {ipAddress}");
47+
}
48+
}
49+
50+
return ValidationResult.Success;
51+
}
52+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// -----------------------------------------------------------------------------
2+
// Filename: MerchantTokenPermissionsEnumExtensions.cs
3+
//
4+
// Description: Contains extension methods for the MerchantTokenPermissionsEnum enum.:
5+
//
6+
// Author(s):
7+
// Donal O'Connor ([email protected])
8+
//
9+
// History:
10+
// 11 09 2025 Donal O'Connor Created, Harcourt St, Dublin, Ireland.
11+
//
12+
// License:
13+
// Proprietary NoFrixion.
14+
// -----------------------------------------------------------------------------
15+
16+
namespace NoFrixion.MoneyMoov.Enums;
17+
18+
public static class MerchantTokenPermissionsEnumExtensions
19+
{
20+
public static bool IsPrivilegedPermission(this MerchantTokenPermissionsEnum permission)
21+
{
22+
if (permission.HasFlag(MerchantTokenPermissionsEnum.ViewPaymentAccount))
23+
{
24+
return true;
25+
}
26+
if (permission.HasFlag(MerchantTokenPermissionsEnum.ViewPayout))
27+
{
28+
return true;
29+
}
30+
if (permission.HasFlag(MerchantTokenPermissionsEnum.ViewTransactions))
31+
{
32+
return true;
33+
}
34+
35+
return false;
36+
}
37+
}

src/NoFrixion.MoneyMoov/Models/Token/TokenAdd.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
using System.ComponentModel.DataAnnotations;
1616
using System.Text.RegularExpressions;
17+
using NoFrixion.MoneyMoov.Attributes;
18+
1719
namespace NoFrixion.MoneyMoov.Models;
1820

1921
#nullable disable
@@ -92,6 +94,13 @@ private bool ValidateDescription()
9294
return false;
9395
}
9496

97+
/// <summary>
98+
/// Optional. If set represents a comma separated list of IP addresses that this token is authorised to be used from.
99+
/// Attempts to use the token from an IP address not in the list will be rejected.
100+
/// </summary>
101+
[IPAddress]
102+
public string IPAddressWhitelist { get; set; }
103+
95104
/// <summary>
96105
/// Places all the token add member's properties into a dictionary. Useful
97106
/// for testing when HTML form encoding is required.
@@ -104,7 +113,8 @@ public IReadOnlyDictionary<string, string> ToDictionary()
104113

105114
dict.Add(nameof(MerchantID), MerchantID.ToString());
106115
dict.Add(nameof(Description), Description.ToString());
107-
116+
dict.Add(nameof(IPAddressWhitelist), IPAddressWhitelist?.ToString());
117+
108118
if (PermissionTypes?.Count() > 0)
109119
{
110120
int permissionTypeNumber = 0;

src/NoFrixion.MoneyMoov/Models/Token/TokenUpdate.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
// Proprietary NoFrixion.
1414
// -----------------------------------------------------------------------------
1515

16+
using NoFrixion.MoneyMoov.Attributes;
17+
1618
namespace NoFrixion.MoneyMoov.Models;
1719

1820
public class TokenUpdate
@@ -25,4 +27,11 @@ public class TokenUpdate
2527
/// The permissions that the merchant token supports.
2628
/// </summary>
2729
public List<MerchantTokenPermissionsEnum>? PermissionTypes { get; set; }
30+
31+
/// <summary>
32+
/// Optional. If set represents a comma separated list of IP addresses that this token is authorised to be used from.
33+
/// Attempts to use the token from an IP address not in the list will be rejected.
34+
/// </summary>
35+
[IPAddress]
36+
public string? IPAddressWhitelist { get; set; }
2837
}

0 commit comments

Comments
 (0)