-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#328 Implementation of API logic for placing a SMS notifications order (
#384) * RecipientExt Phone number property added * SMS notification order request data model added * SMS notification orders controller added * SMS phone number validation initiated * Phone number validation added to singleton * Changed PhoneNumber to MobileNumber * With rebase phone changed to mobile * Change of phone to mobile * Attribute for SMS address point added * Mobile number validation rules regex fix * Validator test initiated for SMS notifiaction order request * Validatee recipient provided for SMS return true added * Validatee recipient provided for SMS return false added * Validate SMS recipient not defined return false added * Validate send time has local timezone return true added * Validate send time has UTC Now timezone return true added * Validate send time has unspecified timezone return false added * Validate Send Numbwer missing returns false * Type added to the validationResult variable * Test for valid SMS number added * Explicit type added to the variable * Explicit type added to the variable * Type definition for recipients variable fixed * Sender Number removed from must rule * Order mapper helper function added for getting mobile number * Norwegian phone number strict validation added * Tests adapted for Norwegian phone numbet validation * Test refactored for readability purpose * Typo fixed * Both MapToRecipientExt tests merged into one * SMS order mapper moved to OrderMapper class * SMS order mapper tests added * Fixed merge conflicts with main * Integration tests added for the SMS notificaitons API * Sender number changed to Altinn for integration tests * PostTests API base path fixed for integration tests * Revert:Removed the k6 tests added with integration tests * Ternary to if-else to remove code smell * Removed 5 digit pass as LinkMobility need 9 digits * Validation logic changed for SMS mobile numbers * RegEx removed from validation logic * Invalid mobile number error message updated Co-authored-by: Stephanie Buadu <47737608+acn-sbuad@users.noreply.github.com> * Arguments fixed for the tests * Tests messgae update --------- Co-authored-by: Stephanie Buadu <47737608+acn-sbuad@users.noreply.github.com>
- Loading branch information
Showing
13 changed files
with
973 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
src/Altinn.Notifications/Controllers/SmsNotificationOrdersController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
using System.Collections; | ||
using Altinn.Notifications.Configuration; | ||
using Altinn.Notifications.Core.Models; | ||
using Altinn.Notifications.Core.Models.Orders; | ||
using Altinn.Notifications.Core.Services.Interfaces; | ||
using Altinn.Notifications.Extensions; | ||
using Altinn.Notifications.Mappers; | ||
using Altinn.Notifications.Models; | ||
using Altinn.Notifications.Validators; | ||
|
||
using FluentValidation; | ||
|
||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Mvc; | ||
|
||
using Swashbuckle.AspNetCore.Annotations; | ||
using Swashbuckle.AspNetCore.Filters; | ||
|
||
namespace Altinn.Notifications.Controllers; | ||
|
||
/// <summary> | ||
/// Controller for all operations related to SMS notification orders | ||
/// </summary> | ||
[Route("notifications/api/v1/orders/sms")] | ||
[ApiController] | ||
[Authorize(Policy = AuthorizationConstants.POLICY_CREATE_SCOPE_OR_PLATFORM_ACCESS)] | ||
[SwaggerResponse(401, "Caller is unauthorized")] | ||
[SwaggerResponse(403, "Caller is not authorized to access the requested resource")] | ||
|
||
public class SmsNotificationOrdersController : ControllerBase | ||
{ | ||
private readonly IValidator<SmsNotificationOrderRequestExt> _validator; | ||
private readonly IOrderRequestService _orderRequestService; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="SmsNotificationOrdersController"/> class. | ||
/// </summary> | ||
public SmsNotificationOrdersController(IValidator<SmsNotificationOrderRequestExt> validator, IOrderRequestService orderRequestService) | ||
{ | ||
_validator = validator; | ||
_orderRequestService = orderRequestService; | ||
} | ||
|
||
/// <summary> | ||
/// Add an SMS notification order. | ||
/// </summary> | ||
/// <remarks> | ||
/// The API will accept the request after som basic validation of the request. | ||
/// The system will also attempt to verify that it will be possible to fulfill the order. | ||
/// </remarks> | ||
/// <returns>The id of the registered notification order</returns> | ||
[HttpPost] | ||
[Consumes("application/json")] | ||
[Produces("application/json")] | ||
[SwaggerResponse(202, "The notification order was accepted", typeof(OrderIdExt))] | ||
[SwaggerResponse(400, "The notification order is invalid", typeof(ValidationProblemDetails))] | ||
[SwaggerResponseHeader(202, "Location", "string", "Link to access the newly created notification order.")] | ||
public async Task<ActionResult<OrderIdExt>> Post(SmsNotificationOrderRequestExt smsNotificationOrderRequest) | ||
{ | ||
FluentValidation.Results.ValidationResult validationResult = _validator.Validate(smsNotificationOrderRequest); | ||
if (!validationResult.IsValid) | ||
{ | ||
validationResult.AddToModelState(this.ModelState); | ||
return ValidationProblem(ModelState); | ||
} | ||
|
||
string? creator = HttpContext.GetOrg(); | ||
|
||
if (creator == null) | ||
{ | ||
return Forbid(); | ||
} | ||
|
||
NotificationOrderRequest orderRequest = smsNotificationOrderRequest.MapToOrderRequest(creator); | ||
(NotificationOrder? registeredOrder, ServiceError? error) = await _orderRequestService.RegisterNotificationOrder(orderRequest); | ||
|
||
if (error != null) | ||
{ | ||
return StatusCode(error.ErrorCode, error.ErrorMessage); | ||
} | ||
|
||
string selfLink = registeredOrder!.GetSelfLink(); | ||
return Accepted(selfLink, new OrderIdExt(registeredOrder!.Id)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
src/Altinn.Notifications/Models/SmsNotificationOrderRequestExt.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
|
||
namespace Altinn.Notifications.Models; | ||
|
||
/// <summary> | ||
/// Class representing an SMS notiication order request | ||
/// </summary> | ||
/// <remarks> | ||
/// External representation to be used in the API. | ||
/// </remarks> | ||
public class SmsNotificationOrderRequestExt | ||
{ | ||
/// <summary> | ||
/// Gets or sets the sender number of the SMS | ||
/// </summary> | ||
[JsonPropertyName("senderNumber")] | ||
public string SenderNumber { get; set; } = string.Empty; | ||
|
||
/// <summary> | ||
/// Gets or sets the body of the SMS | ||
/// </summary> | ||
[JsonPropertyName("body")] | ||
public string Body { get; set; } = string.Empty; | ||
|
||
/// <summary> | ||
/// Gets or sets the send time of the SMS. Defaults to UtcNow. | ||
/// </summary> | ||
[JsonPropertyName("requestedSendTime")] | ||
public DateTime RequestedSendTime { get; set; } = DateTime.UtcNow; | ||
|
||
/// <summary> | ||
/// Gets or sets the senders reference on the notification | ||
/// </summary> | ||
[JsonPropertyName("sendersReference")] | ||
public string? SendersReference { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the list of recipients | ||
/// </summary> | ||
[JsonPropertyName("recipients")] | ||
public List<RecipientExt> Recipients { get; set; } = new List<RecipientExt>(); | ||
|
||
/// <summary> | ||
/// Json serialized the <see cref="SmsNotificationOrderRequestExt"/> | ||
/// </summary> | ||
public string Serialize() | ||
{ | ||
return JsonSerializer.Serialize(this); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
src/Altinn.Notifications/Validators/SmsNotificationOrderRequestValidator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
using System.Text.RegularExpressions; | ||
|
||
using Altinn.Notifications.Models; | ||
|
||
using FluentValidation; | ||
using PhoneNumbers; | ||
|
||
namespace Altinn.Notifications.Validators; | ||
|
||
/// <summary> | ||
/// Class containing validation logic for the <see cref="SmsNotificationOrderRequestExt"/> model | ||
/// </summary> | ||
public class SmsNotificationOrderRequestValidator : AbstractValidator<SmsNotificationOrderRequestExt> | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="SmsNotificationOrderRequestValidator"/> class. | ||
/// </summary> | ||
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."); | ||
|
||
RuleFor(order => order.RequestedSendTime) | ||
.Must(sendTime => sendTime.Kind != DateTimeKind.Unspecified) | ||
.WithMessage("The requested send time value must have specified a time zone.") | ||
.Must(sendTime => sendTime >= DateTime.UtcNow.AddMinutes(-5)) | ||
.WithMessage("Send time must be in the future. Leave blank to send immediately."); | ||
|
||
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); | ||
} | ||
} |
Oops, something went wrong.