Skip to content

Commit

Permalink
notification to org and person with resource working
Browse files Browse the repository at this point in the history
  • Loading branch information
acn-sbuad committed Jun 5, 2024
1 parent 7d4d945 commit c393d10
Show file tree
Hide file tree
Showing 31 changed files with 286 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@

using FluentValidation;

using LocalTest.Notifications.Core.Models.Orders;


#if !LOCALTEST
using Microsoft.AspNetCore.Authorization;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@

using FluentValidation;

using LocalTest.Notifications.Core.Models.Orders;


#if !LOCALTEST
using Microsoft.AspNetCore.Authorization;
#endif
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Altinn.Notifications.Models;
using LocalTest.Notifications.Core.Models.Orders;
using Altinn.Notifications.Core.Models.Orders;
using Altinn.Notifications.Models;

namespace Altinn.Notifications.Mappers;

Expand Down
2 changes: 1 addition & 1 deletion src/Notifications/API/Models/BaseNotificationOrderExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public class BaseNotificationOrderExt
/// Gets or sets the preferred notification channel of the notification order
/// </summary>
[JsonPropertyName("notificationChannel")]
[JsonConverter(typeof(JsonStringEnumConverter))]
[JsonConverter(typeof(JsonStringEnumConverter))]
public NotificationChannelExt NotificationChannel { get; set; }

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json;
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Altinn.Notifications.Models;
Expand All @@ -15,19 +16,21 @@ public class EmailNotificationOrderRequestExt : NotificationOrderRequestBaseExt
/// Gets or sets the subject of the email
/// </summary>
[JsonPropertyName("subject")]
[Required]
public string Subject { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the body of the email
/// </summary>
[JsonPropertyName("body")]
[Required]
public string Body { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the content type of the email
/// </summary>
[JsonPropertyName("contentType")]
public EmailContentTypeExt ContentType { get; set; } = EmailContentTypeExt.Plain;
public EmailContentTypeExt? ContentType { get; set; }

/// <summary>
/// Json serialized the <see cref="EmailNotificationOrderRequestExt"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Text.Json;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;

namespace Altinn.Notifications.Models;
Expand All @@ -24,13 +24,14 @@ public class NotificationOrderRequestBaseExt
/// Gets or sets the list of recipients
/// </summary>
[JsonPropertyName("recipients")]
[Required]
public List<RecipientExt> Recipients { get; set; } = new List<RecipientExt>();

/// <summary>
/// Gets or sets whether notifications generated by this order should ignore KRR reservations
/// </summary>
[JsonPropertyName("ignoreReservation")]
public bool IgnoreReservation { get; set; }
public bool? IgnoreReservation { get; set; }

/// <summary>
/// Gets or sets the id of the resource that the notification is related to
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
using System.Text.RegularExpressions;

using Altinn.Notifications.Core.Helpers;
using Altinn.Notifications.Models;

using FluentValidation;
using PhoneNumbers;

namespace Altinn.Notifications.Validators;

Expand All @@ -20,8 +18,13 @@ public SmsNotificationOrderRequestValidator()
RuleFor(order => order.Recipients)
.NotEmpty()
.WithMessage("One or more recipient is required.")
.Must(recipients => recipients.TrueForAll(a => IsValidMobileNumber(a.MobileNumber)))
.WithMessage("A valid mobile number starting with country code must be provided for all recipients.");
.Must(recipients => recipients.TrueForAll(a =>
{
return
(!string.IsNullOrWhiteSpace(a.MobileNumber) && MobileNumberHelper.IsValidMobileNumber(a.MobileNumber)) ||
(!string.IsNullOrWhiteSpace(a.OrganizationNumber) ^ !string.IsNullOrWhiteSpace(a.NationalIdentityNumber));
}))
.WithMessage("Either a valid mobile number starting with country code, organization number, or national identity number must be provided for each recipient.");

RuleFor(order => order.RequestedSendTime)
.Must(sendTime => sendTime.Kind != DateTimeKind.Unspecified)
Expand All @@ -31,26 +34,4 @@ public SmsNotificationOrderRequestValidator()

RuleFor(order => order.Body).NotEmpty();
}

/// <summary>
/// Validated as mobile number based on the Altinn 2 regex
/// </summary>
/// <param name="mobileNumber">The string to validate as an mobile number</param>
/// <returns>A boolean indicating that the mobile number is valid or not</returns>
internal static bool IsValidMobileNumber(string? mobileNumber)
{
if (string.IsNullOrEmpty(mobileNumber) || (!mobileNumber.StartsWith('+') && !mobileNumber.StartsWith("00")))
{
return false;
}

if (mobileNumber.StartsWith("00"))
{
mobileNumber = "+" + mobileNumber.Remove(0, 2);
}

PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.GetInstance();
PhoneNumber phoneNumber = phoneNumberUtil.Parse(mobileNumber, null);
return phoneNumberUtil.IsValidNumber(phoneNumber);
}
}
22 changes: 22 additions & 0 deletions src/Notifications/Core/Integrations/IAuthorizationService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Altinn.Notifications.Core.Models.ContactPoints;

namespace Altinn.Notifications.Core.Integrations;

/// <summary>
/// Describes the necessary functions of an authorization service that can perform
/// notification recipient filtering based on authorization
/// </summary>
public interface IAuthorizationService
{
/// <summary>
/// Describes a method that can create an authorization request to authorize a set of
/// users for access to a resource.
/// </summary>
/// <param name="organizationContactPoints">
/// The contact points of an organization including user registered contact points.
/// </param>
/// <param name="resourceId">The id of the resource.</param>
/// <returns>A new list of <see cref="OrganizationContactPoints"/> with filtered list of recipients.</returns>
Task<List<OrganizationContactPoints>> AuthorizeUserContactPointsForResource(
List<OrganizationContactPoints> organizationContactPoints, string resourceId);
}
8 changes: 4 additions & 4 deletions src/Notifications/Core/Integrations/IProfileClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public interface IProfileClient
public Task<List<UserContactPoints>> GetUserContactPoints(List<string> nationalIdentityNumbers);

/// <summary>
/// Retrieves the user registered contact points for a list of organization corresponding to a list of organization numbers
/// Retrieves the user registered contact points for a list of organizations identified by organization numbers
/// </summary>
/// <param name="resourceId">The id of the resource to look up contact points for</param>
/// <param name="organizationNumbers">The set or organizations to retrieve contact points for</param>
/// <returns></returns>
public Task<List<OrganizationContactPoints>> GetUserRegisteredOrganizationContactPoints(string resourceId, List<string> organizationNumbers);
/// <param name="resourceId">The id of the resource to look up contact points for</param>
/// <returns>A list of organiation contact points containing user registered contact points</returns>
public Task<List<OrganizationContactPoints>> GetUserRegisteredContactPoints(List<string> organizationNumbers, string resourceId);
}
3 changes: 1 addition & 2 deletions src/Notifications/Core/Models/Address/SmsAddressPoint.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#nullable enable
using Altinn.Notifications.Core.Enums;
using Altinn.Notifications.Core.Enums;

namespace Altinn.Notifications.Core.Models.Address;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System.Text.Json;
using System.Text.Json.Serialization;

using Altinn.Notifications.Core.Enums;

namespace Altinn.Notifications.Core.Models.AltinnServiceUpdate
{
/// <summary>
/// A class representing a generic service update
/// </summary>
public class GenericServiceUpdate
{
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
WriteIndented = true,
Converters = { new JsonStringEnumConverter() },
PropertyNameCaseInsensitive = true
};

/// <summary>
/// The source of the service update
/// </summary>
public string Source { get; set; } = string.Empty;

/// <summary>
/// The schema of the service update data
/// </summary>
public AltinnServiceUpdateSchema Schema { get; set; }

/// <summary>
/// The data of the service update as a json serialized string
/// </summary>
public string Data { get; set; } = string.Empty;

/// <summary>
/// Serialize the <see cref="GenericServiceUpdate"/> into a json string
/// </summary>
/// <returns></returns>
public string Serialize()
{
return JsonSerializer.Serialize(this, _serializerOptions);
}

/// <summary>
/// Try to parse a json string into a<see cref="GenericServiceUpdate"/>
/// </summary>
public static bool TryParse(string input, out GenericServiceUpdate value)
{
GenericServiceUpdate? parsedOutput;
value = new GenericServiceUpdate();

if (string.IsNullOrEmpty(input))
{
return false;
}

try
{
parsedOutput = JsonSerializer.Deserialize<GenericServiceUpdate>(input!, _serializerOptions);

value = parsedOutput!;
return !string.IsNullOrEmpty(value.Source);
}
catch
{
// try parse, we simply return false if fails
}

return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Altinn.Notifications.Core.Models.AltinnServiceUpdate
{
/// <summary>
/// A class holding data on an exceeded resource limit in an Altinn service
/// </summary>
public class ResourceLimitExceeded
{
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
WriteIndented = true,
Converters = { new JsonStringEnumConverter() },
PropertyNameCaseInsensitive = true
};

/// <summary>
/// The resource that has reached its capacity limit
/// </summary>
public string Resource { get; set; } = string.Empty;

/// <summary>
/// The timestamp for when the service is available again
/// </summary>
public DateTime ResetTime { get; set; }

/// <summary>
/// Serialize the <see cref="ResourceLimitExceeded"/> into a json string
/// </summary>
/// <returns></returns>
public string Serialize()
{
return JsonSerializer.Serialize(this, _serializerOptions);
}

/// <summary>
/// Try to parse a json string into a<see cref="ResourceLimitExceeded"/>
/// </summary>
public static bool Tryparse(string input, out ResourceLimitExceeded value)
{
ResourceLimitExceeded? parsedOutput;
value = new ResourceLimitExceeded();

if (string.IsNullOrEmpty(input))
{
return false;
}

try
{
parsedOutput = JsonSerializer.Deserialize<ResourceLimitExceeded>(input!, _serializerOptions);

value = parsedOutput!;
return !string.IsNullOrEmpty(value.Resource);
}
catch
{
// try parse, we simply return false if fails
}

return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Altinn.Notifications.Core.Models.ContactPoints;
using System.Linq;

namespace Altinn.Notifications.Core.Models.ContactPoints;

/// <summary>
/// Class describing the contact points for an organization
Expand Down Expand Up @@ -26,7 +28,25 @@ public class OrganizationContactPoints
public List<string> EmailList { get; set; } = new();

/// <summary>
/// Gets or sets a list of user registered contanct points associated with the organisation.
/// Gets or sets a list of user registered contact points associated with the organization.
/// </summary>
public List<UserContactPoints> UserContactPoints { get; set; } = new();

/// <summary>
/// Create a new instance with the same values as the existing instance
/// </summary>
/// <returns>The new instance with copied values.</returns>
public OrganizationContactPoints CloneWithoutContactPoints()
{
OrganizationContactPoints clone = new()
{
OrganizationNumber = OrganizationNumber,
PartyId = PartyId,
MobileNumberList = new(),
EmailList = new(),
UserContactPoints = new()
};

return clone;
}
}
16 changes: 16 additions & 0 deletions src/Notifications/Core/Models/ContactPoints/UserContactPoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,20 @@ public class UserContactPoints
/// Gets or sets the email address
/// </summary>
public string Email { get; set; } = string.Empty;

/// <summary>
/// Create a new instance with the same values as the existing instance
/// </summary>
/// <returns>The new instance with copied values.</returns>
public UserContactPoints Clone()
{
return new()
{
UserId = UserId,
NationalIdentityNumber = NationalIdentityNumber,
IsReserved = IsReserved,
MobileNumber = MobileNumber,
Email = Email
};
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#nullable enable
using Altinn.Notifications.Core.Enums;

namespace Altinn.Notifications.Core.Models.NotificationTemplate;
Expand Down
2 changes: 1 addition & 1 deletion src/Notifications/Core/Models/Orders/NotificationOrder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,4 @@ public static bool TryParse(string input, out NotificationOrder value)

return false;
}
}
}
Loading

0 comments on commit c393d10

Please sign in to comment.